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
