Skip to content

Changes to C0 polyhedron tetrahedralization loops#4359

Open
GiudGiud wants to merge 19 commits intolibMesh:develfrom
GiudGiud:PR_poly_fixup
Open

Changes to C0 polyhedron tetrahedralization loops#4359
GiudGiud wants to merge 19 commits intolibMesh:develfrom
GiudGiud:PR_poly_fixup

Conversation

@GiudGiud
Copy link
Contributor

@GiudGiud GiudGiud commented Dec 22, 2025

based on top of the hexagon tiling PR, ignore that content for now! It's in another PR

see companion PR in MOOSE creating a bunch of polys with exodus viz of the tets:
idaholab/moose#32141

@GiudGiud GiudGiud force-pushed the PR_poly_fixup branch 2 times, most recently from 5990f8c to 45a4142 Compare December 25, 2025 17:39
@GiudGiud GiudGiud changed the title Poly fixups WIP Changes to C0 polyhedron tetrahedralization loops Dec 28, 2025
if (local_tet_quality[j2] == 0 || local_tet_quality[j2] == far_node)
{
nodes_by_geometry.erase(geometry_it);
has_skipped_adding_tets_and_retriangulating = true;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is the saddest part of this PR. If we could still work with a valid surface mesh it would be a lot safer

unfortunately I seem to need this for every planar 4 node face, we always end up with an empty final tet

Copy link
Member

Choose a reason for hiding this comment

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

unfortunately I seem to need this for every planar 4 node face, we always end up with an empty final tet

Oh, man - are we getting hit again by the nastiest open secret of tet meshing?

It is not always possible to generate a mesh that has only non-degenerate tets and conforms to an existing triangulation, unless we add at least one "Steiner point" on the volume interior! See this horrifyingly simple example: https://github.com/libMesh/libmesh/blob/devel/tests/geom/elem_test.h#L224-L240 I think this is probably why it's so hard to find a tet mesher that doesn't habitually add interior points and screw up Yaqi's plans: if you know you're sometimes going to need to add points just to make a mesh possible, why hesitate to add points to make a mesh better?

I fear the only completely robust solution for our polyhedra code may be to add a new element (C0IPPolyhedron? I'd hope to come up with a better name...) that adds a single Interior Point, after which getting a nice tetrahedralization becomes trivial.

But in the short run, if you're allowed to swap diagonals then I think you can generally fix the problem with some diagonal swapping.

Is this PR ready for review now that it's no longer marked WIP?

Copy link
Contributor Author

@GiudGiud GiudGiud Jan 1, 2026

Choose a reason for hiding this comment

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

Happy New Year!

But in the short run, if you're allowed to swap diagonals then I think you can generally fix the problem with some diagonal swapping.

I'm doing this to extrude polygons into prisms. On the sides I have quads. Are you saying I just need to do something to the diagonals of these (quad) polygons? There's no API for it right now right? It just comes from the ordering of the nodes in the polygon?

I fear the only completely robust solution for our polyhedra code may be to add a new element (C0IPPolyhedron? I'd hope to come up with a better name...) that adds a single Interior Point, after which getting a nice tetrahedralization becomes trivial.

Could we just use the centroid as the interior node? Seems like the tetrahedralization is trivial after doing that? (centroid to every triangle)
The thing is that I am doing this for finite volume sims, so I don't really need extra nodes. In fact I am not even sure I need a tetrahedralization (well except to compute the volume)

Is this PR ready for review now that it's no longer marked WIP?

Certainly ready for a look. if you use my MOOSE PR you can look at the current tetrahedralization of the hexagonal prism in exodus. You should see there is a non-matching edge inside, but is it a problem for the FE math? Certainly is a problem for me when converting the polyhedra to tets in some mesh generators

Copy link
Contributor Author

@GiudGiud GiudGiud Jan 1, 2026

Choose a reason for hiding this comment

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

the only completely robust solution for our polyhedra code may be to add a new element (C0IPPolyhedron

What about a C0PolygonalPrism element? We could always triangulate it as the union of triangular prisms, and we could possibly have custom FE that would be worth including in libmesh? "Tensor product" of the 1D line and the C0Polygon

EDIT: well except if we do the FE math with the tets, the 1D line won't really appear in one direction. We'd have to do something different. Maybe we would not use tets at all? Just triangular prism sub-elements

Copy link
Member

Choose a reason for hiding this comment

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

Are you saying I just need to do something to the diagonals of these (quad) polygons? There's no API for it right now right? It just comes from the ordering of the nodes in the polygon?

Correct, correct, and correct (at construction time), I'm afraid. If you retriangulate() after construction time then we'll try to come up with a geometrically nicer triangulation, but you can't really control that without changing the geometry, a no-no in this context. The only way to assign the quad diagonals is to make use of knowing the default triangulation and then use that to choose which of the nodes of the quad you assign to node 0 after constructing it.

Could we just use the centroid as the interior node? Seems like the tetrahedralization is trivial after doing that?

In our mesh generators IMHO the vertex_average would be the best choice; the tetrahedralization for a convex polyhedron is trivial for any interior point choice.

In fact I am not even sure I need a tetrahedralization (well except to compute the volume)

Not directly, but we do use it in the Lagrange shape functions, so anything trying to compute a mapping will scream if it's not there. We might be able to get by without it thanks to having thrown up our hands at the idea of figuring out what a "master" element looks like for an arbitrary polyhedron, though...

What about a C0PolygonalPrism element?

Not crazy, but I think the IP polyhedron will end up being less new work.

Copy link
Member

Choose a reason for hiding this comment

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

Pinging @jwpeterson since he's had opinions on these names in the original PRs.

Fine with C0PolyhedronP1Plus

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok I ll work on this. Don't think we have funding for this anymore though
I m planning to make it inherit from C0Polyedron. That makes sense right, adding interior points in the derived class

Copy link
Contributor Author

Choose a reason for hiding this comment

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

or do you prefer an intermediate base class? C0PolyhedronBase and two derived children, the regular one and the P1Plus

Copy link
Member

Choose a reason for hiding this comment

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

I have "Polyhedral/tetrahedral mesh enhancements" in my notes under "FY25-26 NEAMS Tasks"/"Named M2 Tasks", with "Polyhedra: very high priority" even, but I'll ping @lindsayad in case my meeting stenography skills failed me. The biggest goal there (IMHO - no notes on that) was I/O support, but if even a simple extrusion is giving us tetrahedralization problems then we probably can't hope to start reading arbitrary files until we've fixed that.

We probably want a C0PolyhedronBase here.

Copy link
Member

Choose a reason for hiding this comment

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

Your notes are spot-on and perfectly timed with my slack NEAMS-MP posts today!

@moosebuild
Copy link

moosebuild commented Dec 28, 2025

Job Coverage, step Generate coverage on 26c1123 wanted to post the following:

Coverage

3463d9 #4359 26c112
Total Total +/- New
Rate 65.38% 65.46% +0.08% 100.00%
Hits 78029 78155 +126 64
Misses 41320 41247 -73 0

Diff coverage report

Full coverage report

This comment will be updated on new commits.

// with no additional interior point
try
{
// In 3D, this will require nested loops: an outer loop to remove
Copy link
Contributor Author

Choose a reason for hiding this comment

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

prefer as is or with an indentation (and a big diff)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

comment goes line 400 now

@GiudGiud
Copy link
Contributor Author

Going to try unit tests on the FE / quadratures.
My suspicion is that the element with the midnode as I have it has one more dof (as you'd expect) and is not equivalent. This would be the right reason to make it another class?

@GiudGiud GiudGiud force-pushed the PR_poly_fixup branch 2 times, most recently from 156336b to 105e26c Compare March 17, 2026 01:07
public: \
FETest_##order##_##family##_##elemtype() : \
FETest<order,family,elemtype>() { \
FETest_##order##_##family##_##elemtype##_##case_name() : \
Copy link
Contributor Author

@GiudGiud GiudGiud Mar 17, 2026

Choose a reason for hiding this comment

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

@roystgnr I m not sure how to "not append _ + something" when case_name isnt set.

Except if I copy paste the macro and duplicate it.
For now it appends _Default to all existing unit test names

OR
if I append "_" for the Default instead of "_Default"

@GiudGiud GiudGiud force-pushed the PR_poly_fixup branch 10 times, most recently from c8b481b to 827a736 Compare March 17, 2026 16:21
@@ -93,6 +93,10 @@ Polyhedron::Polyhedron (const std::vector<std::shared_ptr<Polygon>> & sides,
}
}

// Plan room for an extra node so we don't invalidate this->_nodes when we add to
// nodelinks_data in the derived class
_nodelinks_data.reserve(_nodelinks_data.size() + 1);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

could also modify the derived class but this is cheaper?

Copy link
Contributor Author

@GiudGiud GiudGiud left a comment

Choose a reason for hiding this comment

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

This grew but I think it's ready for a look now!

@GiudGiud
Copy link
Contributor Author

GiudGiud commented Mar 17, 2026

looks like we are not consistently getting the midnode with the cube poly. I ll try a few diagonal changes to see if it stabilizes on civet
on mac I get it consistently
EDIT: was opt vs devel not linux vs arm

@GiudGiud GiudGiud force-pushed the PR_poly_fixup branch 2 times, most recently from aa4f570 to 6c30f70 Compare March 17, 2026 22:39
@GiudGiud GiudGiud force-pushed the PR_poly_fixup branch 3 times, most recently from 0588f58 to ed9f740 Compare March 18, 2026 00:42
@GiudGiud
Copy link
Contributor Author

ok found the problem. Testing occurs in opt mode, and we did not detect the flat tets being added in opt mode.
Should be good now (except maybe dbg mode? we'll see)

@@ -43,4 +43,7 @@ INSTANTIATE_FETEST(SECOND, LAGRANGE, PYRAMID14);
INSTANTIATE_FETEST(THIRD, LAGRANGE, PYRAMID18);

INSTANTIATE_FETEST(FIRST, LAGRANGE, C0POLYHEDRON);
// We don't match the linear solution at this time
// struct MidNode {};
// INSTANTIATE_FETEST_CASE(FIRST, LAGRANGE, C0POLYHEDRON, MidNode);
Copy link
Contributor Author

@GiudGiud GiudGiud Mar 18, 2026

Choose a reason for hiding this comment

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

am I interpreting this right. We are just not 1st order because of the additional midnode dof so we don't match the analytic first order solution
EDIT: does not seem right though

1) test: FETest_FIRST_LAGRANGE_C0POLYHEDRON_MidNode::testU (F) line: 814 ../../tests/fe/fe_test.h
double equality assertion failed
- Expected: 0.03125
- Actual  : 0.00705710457070803
- Delta   : 1e-09


2) test: FETest_FIRST_LAGRANGE_C0POLYHEDRON_MidNode::testGradU (F) line: 851 ../../tests/fe/fe_test.h
double equality assertion failed
- Expected: 0.955297792418862
- Actual  : 1
- Delta   : 1.5e-08


3) test: FETest_FIRST_LAGRANGE_C0POLYHEDRON_MidNode::testGradUComp (F) line: 886 ../../tests/fe/fe_test.h
double equality assertion failed
- Expected: 0.955297792418862
- Actual  : 1
- Delta   : 1.5e-08

Copy link
Contributor Author

@GiudGiud GiudGiud Mar 18, 2026

Choose a reason for hiding this comment

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

or does this indicate a mistake with the mapping / the FE math?
The FE math for Lagrange looks like it would not change from having more sub-tets

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok changed the generic projector and it works now

GiudGiud added 19 commits March 17, 2026 22:35
…rst technique fails

- adapt code for one point not being a node

Clean up tetrahedralization routines when using the mid-node
Revert the master subelement back to the parent class
- if created, add to the mesh after creating the element
Adapt other elem and FE tests to new constructor
Add another error to catch for reverting to the mid-node creating algorithm
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.

5 participants