(Sorry if you get multiples.... I was having trouble sending it)

Let's see... we _do_ have a similar situation in one part of our code.... and one solution is instead of storing data as member variables of a class.... store them in containers in that class.... that way there is one interface... but any of the derived objects can provide whatever data they like.

For instance... if all of the data in a context is going to be Reals you can do this:

class ACon
{
public:
 std::map<std::string, Real> real_data;
}

Then BCon just associates Reals with names and adds them to the std::map... say for instance "time" like so:

real_data["time"] = current_time;

Then in BSys when you want to get "time" you do:

time = AConPtr->real_data["time"]

We've actually wrapped a fancy system around this where the derived classes of ACon call declareRealProperty("name") in their constructors... which returns a reference to the memory that is stored in the std::map that the derived class then uses as if it is a class member.  Then BSys would actually do this instead:

AConPtr->getProperty("name")

And would get back that reference automatically.... note that there are no virtual functions required.

Now... what do you do if you don't know what the types are that your derived classes are going to need to store?  You store your values in Parameters instead... since they are templated you can store whatever you like.... and this essentially lets you associate the name of a property with any object you like.

I don't know what to call this method... it reminds me a bit of type erasure.... but kind of for a different purpose.  I first started doing this type of thing with python.... where it makes a lot of sense because you can actually inject new member variables into a class (since essentially member variables are just stored in a dictionary that associates the name of the variable with it's data.... sounds familiar huh?).

Derek


On Fri, Jan 9, 2009 at 4:29 PM, Roy Stogner <roystgnr@ices.utexas.edu> wrote:

To enable a bit more modularity, automatic multithreading, etc., as
I've mentioned before, I'd like to change the DiffSystem/FEMSystem
interface.

Right now, the library has methods like:

DiffSystem::element_residual()

Which, overridden by the user, can access DiffSystem member variables
with state information (like time) and solution information (like
elem_solution) to fill residual information (like elem_residual and
elem_jacobian).  This is general enough that we could write structured
finite difference methods on top of it if we wanted to.

But for now, we all use the only important subclass, FEMSystem, which
adds more member variables with FEM (or if you wanted, cell-centered
FVM) specific information - the FE, Quadrature rule, and Elem classes,
for example.


That's fine, but now I'd like to move all those member variables into
a method argument:

DiffSystem::element_residual(DiffContext&)

So that, in particular, different threads can work on different
DiffContext objects at the same time without creating multiple
systems.  We'd then move FEMSystem-specific member variables into a
FEMContext subclass of DiffContext, and users whose FEMSystem
subclasses add new member variables would add them to
"CahnHilliardContext" or some such.


People with more C++ intuition than I are already seeing the problem
that arises?

If BSys subclasses ASys, and BCon subclasses ACon, then
BSys::method(BCon&) is not an implementation of ASys::method(ACon&),
and for our purposes BSys::method() won't work with just an ACon&.
Worse: if ASys is FEMSystem and BSys is UserInventedSystem, then
there's no way for ASys to even create a BCon to pass in.


My workaround ideas aren't great:

Declare BSys::method(ACon&), and force everyone to cast to BCon?  This
forces new users to write hideous code - either with the overhead of
dynamic_cast, or with hackish-looking C-style pointer casts.

Create a factory method ACon& ASys::factory(), have BSys reimplement
it to return BCon (and require that any users who need
more context do the same), and have ASys call this factory for each
thread that needs a context?


Anyone have any better ideas?
---
Roy

------------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It is the best place to buy or sell services for
just about anything Open Source.
http://p.sf.net/sfu/Xq1LFB
_______________________________________________
Libmesh-devel mailing list
Libmesh-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libmesh-devel