On Mon, Mar 31, 2008 at 04:01:29PM +0200, Martin Sandve Alnæs wrote:
> 2008/3/31, Anders Logg <[EMAIL PROTECTED]>:
> > On Mon, Mar 31, 2008 at 03:28:16PM +0200, Ola Skavhaug wrote:
> > > Anders Logg skrev den 31/03-2008 følgende:
> > > > On Mon, Mar 31, 2008 at 03:00:27PM +0200, Ola Skavhaug wrote:
> > > > > Anders Logg skrev den 31/03-2008 følgende:
> > > > > > On Mon, Mar 31, 2008 at 02:47:30PM +0200, Ola Skavhaug wrote:
> > > > > > > Anders Logg skrev den 31/03-2008 følgende:
> > > > > > > > On Mon, Mar 31, 2008 at 02:05:25PM +0200, Ola Skavhaug wrote:
> > > > > > > > > Anders Logg skrev den 31/03-2008 følgende:
> > > > > > > > > > On Mon, Mar 31, 2008 at 01:11:42PM +0200, Martin Sandve
> > Alnæs wrote:
> > > > > > > > > > > 2008/3/31, Anders Logg <[EMAIL PROTECTED]>:
> > > > > > > > > > > > On Sun, Mar 30, 2008 at 11:04:57PM +0200, Martin
> > Sandve Alnæs wrote:
> > > > > > > > > > > > > 2008/3/30, Anders Logg <[EMAIL PROTECTED]>:
> > > > > > > > > > > > > > On Sun, Mar 30, 2008 at 10:25:06PM +0200, Martin
> > Sandve Alnæs wrote:
> > > > > > > > > > > > > > > Then solve should be fixed to expect a
> > GenericVector, what's the problem?
> > > > > > > > > > > > > >
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > Yes, but that needs some thinking. The solve()
> > function needs to check
> > > > > > > > > > > > > > what kind of arguments it gets and redirect to
> > the correct backend.
> > > > > > > > > > > > > > For example, if (A, x, b) are PETSc objects,
> > then it needs to call a
> > > > > > > > > > > > > > PETSc solver (which does not work through the
> > GenericFoo interface).
> > > > > > > > > > > > > >
> > > > > > > > > > > > > > I guess you can work your magic try {
> > dynamic_cast<...> } here?
> > > > > > > > > > > > >
> > > > > > > > > > > > > Sure, that should be easy. I'll look at it tomorrow.
> > > > > > > > > > > >
> > > > > > > > > > > >
> > > > > > > > > > > > Fint!
> > > > > > > > > > > >
> > > > > > > > > > > > solve() ligger i dolfin/la/solve.{h,cpp}
> > > > > > > > > > >
> > > > > > > > > > > Vector creates problems when testing the type of a
> > GenericVector.
> > > > > > > > > > >
> > > > > > > > > > > All code that wants to test the type of a GenericVector
> > > > > > > > > > > will depend on Vector.
> > > > > > > > > > >
> > > > > > > > > > > Do you really want all this type trouble just to be able
> > to write
> > > > > > > > > > >
> > > > > > > > > > > Vector v;
> > > > > > > > > > >
> > > > > > > > > > > instead of
> > > > > > > > > > >
> > > > > > > > > > > typedef FooVec Vector;
> > > > > > > > > > > ...
> > > > > > > > > > > GenericVector *v = new Vector()
> > > > > > > > > >
> > > > > > > > > > Yes! "Vector v" looks almost infinitely better than having
> > to write
> > > > > > > > > > typedefs and calling new.
> > > > > > > > > >
> > > > > > > > > > But we don't really need to fix solve() if it's too much
> > trouble.
> > > > > > > > > > If we don't want to dynamically resolve the representation
> > of matrices
> > > > > > > > > > and vectors, then there will be some functions such as
> > assemble() that
> > > > > > > > > > work for any type of vector (GenericVector) and there will
> > be others
> > > > > > > > > > that work only for a specific implementation.
> > > > > > > > > >
> > > > > > > > > > So, if you have a Vector, then you can use it with
> > everything:
> > > > > > > > > >
> > > > > > > > > > assemble()
> > > > > > > > > > solve()
> > > > > > > > > > LUSolver
> > > > > > > > > > KrylovSolver
> > > > > > > > > >
> > > > > > > > > > but if you have a FooVector, then you must use it with the
> > > > > > > > > > Foo solvers:
> > > > > > > > > >
> > > > > > > > > > FooLUSolver
> > > > > > > > > > FooKrylovSolver
> > > > > > > > > >
> > > > > > > > > > So, if it's too much trouble to resolve the backend
> > dynamically, then
> > > > > > > > > > we don't really need to do it.
> > > > > > > > > >
> > > > > > > > > > The basic idea here is that if you don't care about the
> > backend,
> > > > > > > > > > just use Matrix and Vector and everything is simple
> > (assemble, solve).
> > > > > > > > > >
> > > > > > > > > > But if you want to use some special backend, then use
> > FooMatrix,
> > > > > > > > > > FooVector and FooSolver.
> > > > > > > > >
> > > > > > > > > That is the problem in having a simpler design, omitting the
> > Matrix-wrapper
> > > > > > > > > construction, and using only a typedef? F.ex.
> > > > > > > > >
> > > > > > > > > typedef Matrix uBlasMatrix;
> > > > > > > > >
> > > > > > > > > If we are consistent in the DOLFIN library, only
> > communicating GenericFoo
> > > > > > > > > across the interfaces, the chances of non-compatible code
> > being propagated
> > > > > > > > > into the library is minimal. The only place the additional
> > methods of a
> > > > > > > > > particular backend can be used is in user space (and hence
> > not our
> > > > > > > > > concern).
> > > > > > > > >
> > > > > > > > > This will give the nice syntax Anders wants, and conforms
> > with standard
> > > > > > > > > oo-design. The cost is that methods added to a backend will
> > be accessible
> > > > > > > > > through the Matrix typedef, and this might lead to
> > non-portable _user_ code.
> > > > > > > > >
> > > > > > > > > ??
> > > > > > > > >
> > > > > > > > > Ola
> > > > > > > >
> > > > > > > > Yes, the problem with what we had before, namely
> > > > > > > >
> > > > > > > > typedef FooMatrix Matrix;
> > > > > > > > typedef FooVector Vector;
> > > > > > > >
> > > > > > > > was that it allowed writing code depending on Matrix and
> > Vector which
> > > > > > > > was not portable (when changing the typedef).
> > > > > > > >
> > > > > > > > For example, it was fully possible to do
> > > > > > > >
> > > > > > > > Matrix A;
> > > > > > > > MatSetValues(A.mat(), ...);
> > > > > > > >
> > > > > > > > but this wouldn't work unless DOLFIN was compiled with
> > > > > > > >
> > > > > > > > typedef PETScMatrix Matrix;
> > > > > > > >
> > > > > > > > So, the purpose of the current design with a class Matrix
> > inheriting
> > > > > > > > from GenericMatrix and having a FooMatrix pointer is to make
> > sure that
> > > > > > > > Matrix can only do the things defined in GenericMatrix,
> > nothing less
> > > > > > > > (which is handled by the compiler) and nothing more (which we
> > must
> > > > > > > > take care of manually).
> > > > > > >
> > > > > > > I understand this. My point is that if we use GenericFoo
> > consistently though
> > > > > > > the interface of DOLFIN, the (mis)use of Matrix will only live
> > in user code.
> > > > > > >
> > > > > > > Ola
> > > > > >
> > > > > > Do mean that we don't need the Matrix and Vector classes, that we
> > can
> > > > > > use typedefs instead since we will only break someone else's code,
> > not
> > > > > > our own?
> > > > >
> > > > > Almost. They will break their own code, and will probably be able to
> > fix it.
> > > > > But your point is valid; we wont need the Matrix and Vector classes.
> > Typedefs
> > > > > should suffice.
> > > >
> > > > It wasn't my point, it was yours. :-) I'm not completely convinced we
> > > > should replace the classes with typedefs yet.
> > > >
> > > > Having the classes there instead of typedefs is just a safety measure
> > > > and the question is how much we want to pay for it (in terms of
> > > > maintenance). It seem the cost is pretty small (since they are already
> > > > there). We just need to add a few more functions at some point in the
> > > > near future.
> > >
> > > I don't think the cost is small. If we need to resolve the actual type
> > of a
> > > Matrix everywhere we get a GenericMatrix, this will give circular
> > dependencies.
> > > Having a clean cut object oriented design will enable us to simply
> > > dynamic_cast the generic base class pointer to the particular backend
> > instance
> > > and do the work. It is very ambitions to not use dynamic casts, and it
> > will
> > > for sure lead to much work. On the other hand, if someone implements a
> > backend
> > > and is able to implement all functionality by only using the base class
> > > interface, the design we probose will not stop that.
> > >
> > > Ola
> >
> >
> > You mean that if the Matrix that comes in to some function that wants
> > a GenericMatrix is actually a PETScMatrix, then it will be easy to do
> > the dynamic cast, but if it's a Matrix, then it will be very
> > difficult? ok, I can buy that.
>
> It's not very difficult, but cumbersome, and it can't be done in f.ex.
> uBlasVector since uBlasVector can't depend on Vector, since that would
> cause a circular dependency.
ok.
> > But in that case, do we need to do dynamic cast at all? Instead of
> >
> > void foo(GenericMatrix& A)
> > {
> > try { PETScMatrix }
> > try { uBlasMatrix }
> > }
>
> (Sidenote: there's no try involved in dynamic_cast. It just returns NULL.)
ok.
> > we can just overload:
> >
> > void foo(PETScMatrix& A) {}
> > void foo(uBlasMatrix& A) {}
> >
> >
> > ?
>
> The compiler can only select between these foo's at compile-time.
>
> A simple use case which requires type testing:
> I have a DiscreteFunction, and want to pass the underlying vector to
> some linear algebra code using petsc, ublas or trilinos directly. Then
> I need to get the underlying object and cast it. This is not a very
> exotic problem!
ok!
So the conclusion is we need to replace Matrix and Vector with
typedefs? (Like we had before.)
And the reason is that keeping them gives us a lot of pain when
implementing functions that need to check the type?
And the main example would be
void GenericMatrix::mult(const GenericVector& x, GenericVector& Ax) const;
?
If yes - yes - yes, then I say ok.
--
Anders
_______________________________________________
DOLFIN-dev mailing list
[email protected]
http://www.fenics.org/mailman/listinfo/dolfin-dev