On Mon, Oct 24, 2011 at 1:01 PM, Jed Brown <[email protected]> wrote:
> On Mon, Oct 24, 2011 at 10:24, John Peterson <[email protected]> wrote:
>>
>> On Tue, Oct 18, 2011 at 10:18 PM, Jed Brown <[email protected]> wrote:
>> >
>> > I rebuilt everything and sadly, the same problem is still present with
>> > r4873.
>>
>> One other difference between Mac and Linux we noted was the ordering
>> of linking imposed by make's $(wildcard ) functionality. (This
>> ordering may also be file-system dependent?)
>>
>> Anyway, the Makefile patch below seems to fix things for us on
>> openSUSE 11.4/GCC 4.5.1/GNU ld 2.21.
>>
>> If you'd like try applying the patch below and seeing if it fixes
>> anything, it would at least give us another data point.
>>
>> If this does fix the problem on other linux's, it could imply some
>> issue with the libmesh source (probably explicit template
>> instantiations) but I'm not really sure where to start looking?
>
> Yes, this patch fixes the problem for me too. Thanks for tracking this down.
I've investigated this issue a bit further, and as Jed deduced, the
FE<Dim,XYZ> version of n_dofs() is indeed being called where the
FE<Dim,LAGRANGE> version should be.
This issue is not limited to ex4, e.g. it happens in ex3 as well. But
in that case, it causes the Newton iteration in inverse_map() to fail
rather than tripping an assert.
Interestingly, the problem is not present in debug mode, and the
problem goes away if you link the object files in alphabetical order
(as the previous patch I sent demonstrated.) This makes the bug
really annoying and somewhat delicate to reproduce on different
systems.
I don't know anything about the internals of the linker that would
explain why this happens (buggy linker function name resolution?) but
I do have what I think is a reasonable fix that should be portable.
First, I contend we are doing something slightly strange with the FE
template functions to begin with: we're using explicit
*instantiation* to generate template code rather than explicit
*specialization*.
Conceptually I'd say these two techniques are similar, but they are
syntactically different and they are certainly distinguished between
by the standard[0].
What our code looks like in practice is essentially:
fe_lagrange.C
-------------
// function definition
unsigned int FE<Dim,T>::n_dofs(const ElemType t, const Order o) { //
function body specialized for Lagrange }
...
// explicit instantiation (for 2D, but all Dims are instantiated with a macro)
unsigned int FE<2,LAGRANGE>::n_dofs(const ElemType t, const Order o);
fe_xyz.C
--------
// function definition
unsigned int FE<Dim,T>::n_dofs(const ElemType t, const Order o) { //
function body specialized for XYZ }
...
// explicit instantiation (for 2D, but all Dims are instantiated with a macro)
unsigned int FE<2,XYZ>::n_dofs(const ElemType t, const Order o);
I think this is legal C++... at least I haven't found anything stating
it's illegal, but it's not exactly in the spirit of what we're doing.
We're specializing the behavior of n_dofs() for different template
arguments; it follows that we should probably use the template
specialization syntax to do so. And indeed, changing the n_dofs()
function in fe_lagrange.C to use explicit specialization[1] rather
than instantiation *does* fix the problem on the system I have access
to. (It works regardless of what order the object files are linked
in, etc.)
There's no reason the problem will always be limited to n_dofs(), so
I'm planning to change all the FE function instantiations to
specializations. There's also no reason for this problem to be
limited to Lagrange FEM, so I'm changing the other FE types as well.
Obviously this will be a fairly large patch, so I would appreciate it
if folks using/testing some of the less common FE types will let me
know if I've broken their stuff once the patch comes through!
--
John
[0] For example, 14.7 p5 states: "both an explicit instantiation and a
declaration of an explicit specialization shall not appear in a
program unless the explicit instantiation follows a declaration of the
explicit specialization."
[1] For those interested, my fix is to declare a function
"lagrange_n_dofs()" in an anonymous namespace in fe_lagrange.C, and
then do the explicit specialization:
template <> unsigned int FE<2,LAGRANGE>::n_dofs(const ElemType t,
const Order o) { return lagrange_n_dofs(t, o); }
for all relevant dimensions. The logic of lagrange_n_dofs() is the
same for all dimensions.
------------------------------------------------------------------------------
The demand for IT networking professionals continues to grow, and the
demand for specialized networking skills is growing even more rapidly.
Take a complimentary Learning@Cisco Self-Assessment and learn
about Cisco certifications, training, and career opportunities.
http://p.sf.net/sfu/cisco-dev2dev
_______________________________________________
Libmesh-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libmesh-devel