Skip to content

Netgen: curved meshes from Mesh constructor and refine_marked_elements#4930

Open
pbrubeck wants to merge 31 commits intomainfrom
pbrubeck/netgen-bendy-mesh
Open

Netgen: curved meshes from Mesh constructor and refine_marked_elements#4930
pbrubeck wants to merge 31 commits intomainfrom
pbrubeck/netgen-bendy-mesh

Conversation

@pbrubeck
Copy link
Contributor

@pbrubeck pbrubeck commented Feb 27, 2026

Description

Fixes #4784

Previously we had 2 methods to construct a curved Mesh out of a netgen mesh:

  1. First creating a firedrake Mesh from a linear netgen mesh, and then calling curve_field(degree) to produce new coordinates, then you could create a firedrake Mesh out of the curve field. The final Firedrake Mesh will not know that it comes from a netgen mesh, and therefore cannot be adaptively refined.
mesh1 = Mesh(netgen_mesh)
meshp = Mesh(mesh1.curve_field(p))
  1. Via the MeshHierarchy constructor, this method produces a MeshHierarchy in which each mesh knows that it comes from a netgen mesh
mesh1 = Mesh(netgen_mesh)
mh = MeshHierarchy(mesh1, refine, netgen_flags={"degree": p})
meshp = mh[0]

This PR enables the more intuitive approach (while not removing the other two)

meshp = Mesh(netgen_mesh, netgen_flags={"degree": p})

Also propagates the mesh order in refine_marked_elements.

Copy link
Contributor

@connorjward connorjward left a comment

Choose a reason for hiding this comment

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

This is a way better way to build these meshes. Could you amend our demos?

@pbrubeck pbrubeck force-pushed the pbrubeck/netgen-bendy-mesh branch from 9805342 to f56305c Compare March 16, 2026 16:44
@pbrubeck pbrubeck force-pushed the pbrubeck/netgen-bendy-mesh branch from f56305c to e877b90 Compare March 16, 2026 17:47
@pbrubeck pbrubeck force-pushed the pbrubeck/netgen-bendy-mesh branch 3 times, most recently from bded950 to 2916572 Compare March 18, 2026 11:53
@pbrubeck pbrubeck force-pushed the pbrubeck/netgen-bendy-mesh branch from 2916572 to 9250727 Compare March 18, 2026 11:55
@pbrubeck pbrubeck requested a review from connorjward March 18, 2026 12:10
(ng_dimension, reference_space_points.shape[0], self.geometric_dimension)
)
self.netgen_mesh.CalcElementMapping(reference_space_points, physical_space_points)
# NOTE: This will segfault for CSG!
Copy link
Contributor

Choose a reason for hiding this comment

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

Concerning...

Copy link
Contributor

Choose a reason for hiding this comment

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

We should handle this properly somehow.

Copy link
Contributor Author

@pbrubeck pbrubeck Mar 18, 2026

Choose a reason for hiding this comment

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

We could just raise an exception when self.netgen_mesh.getGeometry() is CSG, but what if this get fixed upstream?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think that we should leave this in here. Instead we should:

  • Raise an error if a user tries to use CSG that points to the upstream issue
  • Open our own issue, again linking to the upstream one, telling us to revisit this at a later point

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree we should raise an error if the geometry is CSG. I believe CSG is no longer developed by the NGSolve group in favour of OCC 2D and 3D, hence why it seg faults on new features like the one we use to convert back to a Netgen mesh the DMPlex after refinement.


netgen_mesh = self.netgen_mesh.Copy()
refine_faces = netgen_flags.get("refine_faces", False)
if self.comm.rank == 0:
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this be wrapped in a try except block so we don't deadlock if this ends up failing. I did the same thing here: https://github.com/firedrakeproject/firedrake/pull/4913/changes#diff-3b7ad5733ba21ccaa1be5b8aa4027e50a552acea3d0c66425ab7c47bd31ee278

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am calling Barrier() below, and this seems to prevent deadlocks

Copy link
Contributor Author

@pbrubeck pbrubeck Mar 18, 2026

Choose a reason for hiding this comment

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

Actually, the assumption that rank 0 keeps the global netgen mesh is not always true. A netgen MeshHierarchy will distribute the netgen mesh. I think we need a further PR where we make sure that the underlying netgen mesh is also distributed.

Copy link
Contributor

Choose a reason for hiding this comment

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

I am calling Barrier() below, and this seems to prevent deadlocks

That's not what I mean. If the code that is only running on rank 0 ever fails for some reason then things will hang in a really really hard to debug way (remember this?).

I've added a helper function for doing this in #4972 which is probably good to be merged later today.

I think we need a further PR where we make sure that the underlying netgen mesh is also distributed.

Sure. I agree that that might be out of scope here. It would be helpful if you could open an issue though.

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 you point me to the function?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I can remove the branching here... The netgen mesh on the other ranks should also be refined in both the redundant and the distributed cases

Copy link
Contributor

Choose a reason for hiding this comment

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

Could you point me to the function?

safe_noncollective in #4972

@pbrubeck pbrubeck force-pushed the pbrubeck/netgen-bendy-mesh branch 2 times, most recently from 113d7de to 7528fa0 Compare March 18, 2026 22:10
@pbrubeck pbrubeck force-pushed the pbrubeck/netgen-bendy-mesh branch from 7528fa0 to 546f11a Compare March 18, 2026 22:13
@pbrubeck pbrubeck requested a review from connorjward March 19, 2026 08:49

netgen_mesh = self.netgen_mesh.Copy()
refine_faces = netgen_flags.get("refine_faces", False)
if self.comm.rank == 0:
Copy link
Contributor

Choose a reason for hiding this comment

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

I am calling Barrier() below, and this seems to prevent deadlocks

That's not what I mean. If the code that is only running on rank 0 ever fails for some reason then things will hang in a really really hard to debug way (remember this?).

I've added a helper function for doing this in #4972 which is probably good to be merged later today.

I think we need a further PR where we make sure that the underlying netgen mesh is also distributed.

Sure. I agree that that might be out of scope here. It would be helpful if you could open an issue though.

(ng_dimension, reference_space_points.shape[0], self.geometric_dimension)
)
self.netgen_mesh.CalcElementMapping(reference_space_points, physical_space_points)
# NOTE: This will segfault for CSG!
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think that we should leave this in here. Instead we should:

  • Raise an error if a user tries to use CSG that points to the upstream issue
  • Open our own issue, again linking to the upstream one, telling us to revisit this at a later point

(ng_dimension, reference_points.shape[0], self.geometric_dimension)
)
self.netgen_mesh.CalcElementMapping(reference_points, physical_points)
# NOTE: This will segfault for MeshHierarchy on a netgen CSG geometry
Copy link
Contributor Author

@pbrubeck pbrubeck Mar 20, 2026

Choose a reason for hiding this comment

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

Curving a CSG mesh works fine, as long as this mesh has not been uniformly refined. It fails for CSG + MeshHierarchy, where we convert mesh.topology_dm.refine() into a netgen mesh. So this seems to me like a ngsPETSc issue.

Copy link
Contributor

@UZerbinati UZerbinati Mar 20, 2026

Choose a reason for hiding this comment

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

The new mechanics,which allow for 3D support, is as follows now. We create a refinement in PETSc, we construct the maps between coarse to fine and vice versa in PETSc which is faster (you really see it in 3D) and eventually I hope also load balanced, then we create the corresponding Netgen mesh. We then snap to the geometry and curve, we thus need to attach geometrical information to the mesh. This last feature is only supported for OCC and not for old school CSG. I believe this is the best way to go and I don't think we should insist in supporting the old CSG, it makes no sense since also Netgen is no longer actively developing it. There is the serious risk we will end up having to keep fixing issues arising from legacy code if we do so. Less is more in this case :)

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.

BUG: ngsPETSc update broke things

3 participants