On Thu, Oct 23, 2008 at 6:03 AM, Jed Brown <[EMAIL PROTECTED]> wrote:
> On Wed 2008-10-22 15:52, John Peterson wrote:
>>
>> I'm not too worried about supporting *completely* arbitrary
>> UserShellMatrix objects.  It's easy enough, and I think, reasonable,
>> to have folks derive their UserShellMatrices from NumericMatrix (for
>> the required interface) and PetscMatrixBase (for the required Mat
>> object data).  This approach also does not preclude them from, in
>> addition, deriving from (an eventual, correctly implemented)
>> EpetraMatrixBase and even other types, to allow use of a
>> UserShellMatrix with the other solver types.
>
> So the user implements UserShellMatrix1 through N, then we add FooSolver
> and they have to change their code to derive all their matrices from
> FooMatrix or FooShellMatrix.  This means that the user sees M:N
> inheritance and it's completely unnecessary.

M*N inheritance is unnecessary.  The user would implement
UserShellMatrixBase and inherit from all M different solvers they'd
like to use, then they'd derive their N different sub shell matrices
from UserShellMatrixBase.  If another linear solver package is added,
UserShellMatrixBase now inherits from M+1 solvers and the children
don't have to change.


> The hypothetical Matrix::foo_matrix() getter can be implemented outside
> of Matrix, it's functionally the same as a smart-cast.  An external
> implementation would try a dynamic_cast<PetscMatrix>, if it succeeds,
> just call .mat(), otherwise create a MatShell and return that.  For
> PETSc you don't need a smart-pointer, just use PetscObjectReference(),
> for others packages you may need one.  My rationale for putting this in
> Matrix is it guarantees that the MatShell wrapper is unique throughout
> the application.  Since the wrapper uses a trivial amount of memory and
> will always be observationally equivalent, it shouldn't be a problem to
> possibly have duplicates around.
>
> In my scheme, libmesh only needs to provide
>
> Matrix <- PetscMatrix
>       <- EpetraMatrix
>       <- LaspackMatrix


> The user derives Matrix to implement their shell matrices.

Right, but I think we already agreed that the interface required by a
shell matrix is a subset of that provided by a full-featured (what we
are now calling) SparseMatrix.  This was the rationale for creating a
new base class, smaller than SparseMatrix, which is easier to derive
from.

> The solvers
> all take a generic Matrix and call a smart-extractor (it could be
> namespaced as Foo::Mat libmesh::Foo::mat(Matrix A), it tries a
> dynamic_cast<FooMatrix> so it can call FooMatrix::mat(), otherwise it
> creates a Foo::Mat using Foo's shell matrix functionality).  Now
> FooMatrix only means that the matrix is Foo-native so that
> libmesh::Matrix operations are defined in terms of Foo::Mat operations.
> Being a FooMatrix has nothing to do with being able to use FooSolver.

Only it does, because to use a Petsc linear solver interface, a Matrix
needs to have a Petsc 'Mat' from somewhere.  You can 1) put it in the
base class, 2) create some kind of on-the-fly MatShell returner, or 3)
inherit from a base which contains the Mat as private data.  I find
that #3 is the most consistent object-oriented approach to take, and
best encapsulates the idea.


>> I'm still just (admittedly stubbornly) against the concept of the
>> abstract base having anything to do with derived types.
>
> In my scheme, being able to provide a PETSc::Mat is not an exclusive
> property of the derived type PetscMatrix, we can make a PETSc::Mat from
> any Matrix, we just need to know what operations have been implemented.
> I don't think it's desirable that PetscSolver needs a PetscMatrix, but
> you can wrap the new MatShell in a PetscMatrix if it makes you feel
> better (the solver is only ever going to call PetscMatrix::mat(), so the
> wrapping is completely gratuitous).

And yet the proper care and feeding of the Petsc Mat object is
non-trivial.  We have to introduce reference-counted objects to keep
track of them (possibly duplicating MatDestroy code in multiple
places), or inject Petsc-specific code (Mat's and
PetscObjectReferences) into ostensibly abstract library base classes,
or carefully manage data access through an inherited base class.  As
mentioned above, I prefer the latter technique.



>> While there may be no practical problems (or only minor
>> inconveniences, for example, the entire petsc_mat() interface must be
>> #ifdef'd out when LIBMESH_HAVE_PETSC is 0) with this approach, I just
>> think it is bad design.
>
> Why must the interface be #ifdef'd out?  There is no chance you would
> end up with a PetscMatrix if it wasn't compiled with PETSc, but there's
> no chance you'd have a PetscSolver either so you'd never try to call
> Matrix::petsc_mat().  If you did, you'd get not_implemented() since the
> implementation would be #ifdef'd out.

It won't compile if it's not #ifdef'd out when Petsc is unavailable.


> Putting one pointer in Matrix per solver package is ugly and avoidable,
> but it's simpler, reduces the number of objects to keep track of, and
> guarantees that shell objects are created at most once.  It does mean
> that the user will have to recompile (but not modify!) their code if new
> solver packages are added, but not if existing packages are
> enabled/disabled.

It's not exactly one pointer/solver package.  It's potentially all the
'private' implementation details of each of the M solver packages.
For example, Epetra needs Epetra_FECrsMatrix*, Epetra_Map*, and
Epetra_CrsGraph*.  These could all be encapsulated in yet another
pimpl-like class, and this is a valid design, but I don't think it's
the one we want to take, and it's certainly not one I'm volunteering
to implement...

-- 
John

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Libmesh-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libmesh-devel

Reply via email to