Ok - so I've fixed up EpetraVector... and all is well again.  You can now once again use Trilinos to solve linear problems in both serial and parallel... and now it'll be using pure Epetra_Vectors under the hood instead of FEVectors.

Now to finish up that NOX integration...


On Mon, Sep 15, 2008 at 12:15 PM, Derek Gaston <friedmud@gmail.com> wrote:
On Mon, Jun 16, 2008 at 3:26 PM, Derek Gaston <friedmud@gmail.com> wrote:
On Jun 16, 2008, at 3:24 PM, Benjamin Kirk wrote:
It does.  This is a very common usage -- summing local contribution to
shared, remote entries, so I am surprised that only Epetra_FEVector supports
it.  It seems to me Epetra_FEVector would be better derived from

I absolutely agree... and couldn't believe my eyes when I saw the inheritance chart in their doxygen docs... it doesn't make any sense at all.  If you read the docs it even describes FEVector as an extension of Vector!  My guess: some intern just hacked it in there...

Ben... so this whole Epetra_FEVector / Epetra_Vector junk _did_ end up coming back around to bite us in the ass.

It turns out that the interface for NOX expects Epetra_Vectors... not Epetra_MultiVectors nor Epetra_FEVectors... but specifically Epetra_Vectors.  What a pain in the ass.

Over the last couple of weeks I tried a couple of different ideas to get around this... multiple-inheritance, whole-sale copying of FEVector into libMesh and make it inherit from the right place, etc... but it turns out that the specific way that the NOX interface uses Epetra_Vectors absolutely _requires_ that your own code uses Epetra_Vector.  The reason is that it doesn't pass you back your original Epetra_Vector... instead it passes you a "new" one that has a "view" into your original data (so no data copying is going on but it's not physically this same object).  This behavior means that you can't dynamically cast the Epetra_Vectors that NOX gives you back into something that looks like an Epetra_FEVector... even if you went through all the work to make the inheritance tree look right.... sigh.

So... what to do?  Well, I looked at the functionality that Epetra_FEVector was giving us over just a regular Epetra_Vector... and it's really not much... mostly just a little bit of book-keeping for the parallel summing.  So I decided to lift all of that functionality and just place it into the libMesh::EpetraVector object directly... and instead of working with an Epetra_FEVector... we would work with an Epetra_Vector and just do all the manipulations for the parallel summing ourselves... external to the Epetra_Vector object.

I just checked in my first go at making this work.  I haven't completely tested it yet though... I'll do more of that over the next couple of days as I'm finishing up fleshing out the NOX interface.

Really though... what the hell is the point of doing an "object-oriented" C++ numerical library if you don't use polymorphism correctly?  I mean, just take a look through Epetra objects... notice anything missing from a polymorphism standpoint?   Yep... there's absolutely _no_ virtual functions!!!!!!  _This_ is why every object that inherits from something has to re-expose it's own functions with slightly different signatures to do (almost) the same thing as it's base class!  _This_ is also why Epetra_FEVector is pretty screwed up.  In reality they should have just been able to override the virtuals in MultiVector in order to handle the off-processor elements... but instead they had to hack around it... sigh.

My guess for this rediculousness: optimization.  My bet is that back when they started the OO version of Epetra everyone was still scared about how much time virtual table lookups cost... and so they decreed that there will be no virtuals.  I'd really like to see the timing studies on a modern computer that would justify this kind of optimization....

Ok - Rant-off.