Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Arbitrary-) Polygon elements #4074

Open
wants to merge 51 commits into
base: devel
Choose a base branch
from

Conversation

roystgnr
Copy link
Member

This ended up being a larger diff than I'd hoped for - we need to change a whole swath of Quadrature and FE APIs, to take an Elem * or Elem & instead of just an ElemType, if we want to be able to handle elements where a single type might have differing subelement decompositions and/or different values for things like n_dofs from element to element.

With just Polygon subclasses, it might been conceivable to just add PENTAGON, HEXAGON, etc. enumerated types until we reached n_sides()=17 or some such too-crazy-to-exceed value, but I'm hoping that the refactoring here also lets us handle an upcoming Polyhedron class hierarchy.

Since I'm deprecating a bunch of functions, I also uncommented the libmesh_deprecated() on a bunch of others while I was at it, and wrapped everything I could in #ifdef LIBMESH_ENABLE_DEPRECATED to try and catch use cases at compile time.

Some InfFE code was using FE/FEInterface calls that were deprecated by @lindsayad as part of his work on p-refinement flexibility, and I'm not sure if I updated them correctly for p_level() > 0 cases. I don't think anybody has yet tried combining infinite elements with p refinement (@BalticPinguin?), but if somebody did and I just broke it then on the one hand I apologize but on the other I consider that acceptable punishment for not getting an example with feature coverage into CI.

@moosebuild
Copy link

moosebuild commented Feb 12, 2025

Job Coverage, step Generate coverage on 8d05c27 wanted to post the following:

Coverage

159f51 #4074 8d05c2
Total Total +/- New
Rate 63.22% 63.29% +0.06% 75.23%
Hits 74214 74643 +429 498
Misses 43168 43301 +133 164

Diff coverage report

Full coverage report

Warnings

  • New new line coverage rate 75.23% is less than the suggested 90.0%

This comment will be updated on new commits.

@moosebuild
Copy link

Job Coverage, step Verify coverage on cf92f3f wanted to post the following:

The following coverage requirement(s) failed:

  • Failed to generate coverage rate (required: 55.0%)

@roystgnr
Copy link
Member Author

roystgnr commented Mar 4, 2025

Rebasing to fix a Makefile.in conflict, but the last CI only shows the Test MOOSE ARM mac MOOSE bug and a multiple-shas issue in Coverage, so this should be safe to merge finally.

roystgnr added 23 commits March 4, 2025 07:32
Some subclasses like Polygon might have to do this for themselves,
because they can't heap allocate until after initializing Elem.
Throwing in other method tests here while I'm at it, just to get a quick
check before I try to instantiate a Polygon1 in our usual Elem tests
If we have a POLYGON1 or a future POLYHEDRON1 or anything else where
the quadrature rule will need to depend on more than just a single
element type, we'll need to initialize quadrature objects with the
physical element.
Obviously we can't rely on static maps here in general anymore, since
we're not going to have a different ElemType and map entry for every
possible polyhedron.

So, add some invalid_uint entries for the general types, and handle
invalid_uint where we might run into it, and query the Elem itself
instead of these maps whereever we can.
This lets us do a lot in Polygon that might otherwise have to be pushed
down to subclasses, which will be good if we ever have any higher-order
or internal-node-having subclasses.
I'll finish Lagrange+Polygon1 support soon, but this will be faster even
then, and it'll get Polygon elem unit tests working earlier.
Not sure how I missed this earlier
Some of the tests here don't apply to a non-affine pentagon, or apply
with different numbers to a distorted pentagon, or won't apply until we
can do a Lagrange basis on a pentagon.
roystgnr added 20 commits March 4, 2025 07:32
This should be useful in distinguishing Polygon/Polyhedron from more
static types.
This should keep caching from breaking on polygon/polyhedra of mixed
runtime topology
This should be more forwards compatible than hardcoding a POLYGON1 test.
Putting this in FEInterface was kind of an unintuitive decision in the
first place, and now that we're adding runtime-dependent element
topology like Polygons we're going to *need* a physical Elem to work
with in those cases.
We make this one an equilateral pentagon because a non-skewed polygon
won't give us an exact representation of linears for p>1 MONOMIAL
We can't build the old Side objects for Polygon1; the build code there
relies on `side_nodes_map`.
This is a bit more descriptive of an important aspect (triangulated
mapping), and we can still add terms to indicate higher order in later
higher-order versions.
QComposite was hitting undefined behavior here, creating temporary
subelements for an internal Lagrange FE, and then when that FE would
reinit afterward it would test `get_elem_type()` and hit a dangling
pointer.
roystgnr added 3 commits March 4, 2025 09:14
Shouldn't have left it in the header after seeing how big it needed to
be.
Copy link
Member

@jwpeterson jwpeterson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My main comment is that we should prefer libmesh_error_msg() to libmesh_error() even for unlikely errors, since it's just better documentation even when we don't hit the errors.

Comment on lines 401 to 404
if (Elem::type_to_n_nodes_map[itemType] == invalid_uint)
libmesh_error();

nodes.resize(Elem::type_to_n_nodes_map[itemType]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems a little clunky to do the Elem::type_to_n_nodes_map[itemType] lookup twice (once for the error check, once for the resize) and I think you could further improve this diff by using a libmesh_error_msg() rather than giving no information if there's an error.

case C0POLYGON:
// C0Polygon requires using newer FE APIs
if (!e)
libmesh_error();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer a libmesh_error_msg() with some details here as well.

{
// C0Polygon requires using newer FE APIs
if (!elem)
libmesh_error();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libmesh_error_msg()

{
// C0Polygon requires using newer FE APIs
if (!elem)
libmesh_error();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libmesh_error_msg()

src/geom/elem.C Outdated
Comment on lines 162 to 173
invalid_uint, // unused
invalid_uint, // unused
invalid_uint, // unused
invalid_uint, // unused
invalid_uint, // unused
invalid_uint, // unused
invalid_uint, // unused
invalid_uint, // unused
invalid_uint, // unused
invalid_uint, // unused
invalid_uint, // unused

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because of the enumeration value you chose for C0POLYGON = 50, yes? What is the reason for having the gap, exactly? It doesn't look like we've left gaps for other types of Elems in the past so my first instinct would have just been to keep the numbering sequential for the new type...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, this is embarrassing... honestly, the gaps are there because I have another branch that was going to use them, for higher-order nodal (Lagrange + Rational-Bezier-Bernstein mappings) geometric element support. That branch is probably less than half finished and it's turned out to be less of a priority than I'd expected, though, so I'll reshuffle this now, and whenever I get back to that I'll move its numbers up when I hit the rebase conflicts.


const auto n_elem_ints = this->n_extra_integers();
returnval->add_extra_integers(n_elem_ints);
for (unsigned int i = 0; i != n_elem_ints; ++i)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be a make_range() loop but not a big preference for me.

Comment on lines 343 to 346
swap2nodes(s,ns-1-s);
swap2neighbors(s,ns-2-s);
swap2boundarysides(s,ns-2-s,boundary_info);
swap2boundaryedges(s,ns-2-s,boundary_info);
Copy link
Member

@jwpeterson jwpeterson Mar 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need spaces after commas, at least that is how we usually format comma-separated parameter lists?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, but I'm not changing any of the 200ish spots in older files where I forgot the spaces. ;-)

Comment on lines +275 to +278
case MIN_ANGLE:
bounds.first = 90. - (180./this->n_sides());
bounds.second = 180. - (360./this->n_sides());
break;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that you added these bounds for completeness, but there is no Elem::quality() implementation yet for Polygons is there?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no specialization, but the base class implementation actually works fine for polygons, and we now test with it in elem_test.C - I had to add a special case for them because a squashed pentagon I construct for one instantiation has an angle that's even worse than our standard pyramids.

// Some element types require data from a specific element, so can
// only be used with newer APIs.
if (t == C0POLYGON)
libmesh_error();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libmesh_error_msg()

roystgnr added 5 commits March 4, 2025 14:28
The base class `Elem::volume()` call caught bad quadrature weights even
when something (cancellation?) prevented them from being caught by our
FE tests.
This avoids a bunch of unused values in between, and the only point of
it was to reduce conflicts with another feature branch that may be
delayed a while regardless.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants