Hi Chris and Happy Easter too,
The spring is shiny in Pau too ;-).
Discretization of 1 level-set value
As Mmg doesn’t deal with mesh generation, you are right, the only way to do what you want is to pass through an isovalue discretization:
You will need to start from a volume mesh (for example, from a cube (2.9 MB) mesh) and from a closed surface (your first input, I join the surface mesh of a cylinder (30.6 KB) );
From these data, you can compute the signed distance function to the surface at the nodes of the volume mesh. Mmg doesn’t provide such a tool but you can try the mshdist software (written by Charles Dapogny and Pascal Frey). Unfortunately, this software doesn’t provide API functions. To call mshdist by command line:
mshdist cube.mesh cylinder.mesh
It creates a cube.sol (303.3 KB) file that contains the signed distance to the cylinder surface.
You can use Mmg to discretize the wanted isovalue. An example with the API is available in the
There are few differences with the mesh adaptation mode:
- you must initialize a data structure to store the level-set function (instead of the size map):
- and call the
MMG3D_mmg3dls(mmgMesh,mmgLs,NULL) function instead of the
- to avoid the automatic detection of spurious sharp edges, it is better to disable the sharp angle detection (not shown in the library example):
- you can choose the level-set to be discretized (default is 0), to discretize the 0.2 value:
you obtain the wanted surface mesh and the external and internal volumes. On my example, the 0 level-set look like this (you can have better results if you adapt the initial volume mesh over the level-set to discretize):
I am not sure if you only want to create a mesh at a given shift of the initial one (if yes, you just have to play with the level-set value) or if you want both meshes (initial and shifted one) inside the same volume mesh.
Discretization of a second level-set with preservation of the first one
For this second case, Mmg3d is not totally ready but I have tried to implement something in the
You have to create an exterior and interior volume mesh for your initial surface mesh with different references. It can be created using the level-set discretization of Mmg or with another tool. Here I will suppose that we start from the mesh obtained at stage 4.
Then you must specify the mapping between the inital references and their new values if they are splitted (you can also ask to not split a given ref but it is useless in your case). You can do it using a parameter file named <testcase>.mmg3d file (<testcase> must be replaced by the name of yout initial mesh without extension (in my example cube.o.mmg3d) for a command line call or via API functions for a library call.
The parameter file must have the following format:
3 4 5
2 6 7
Which is equivalent to the following API calls:
It says that you have 2 different references, the reference 3 is splitted into the reference 2 (interior mesh) and the reference 3 (exterior mesh) and the reference 2 is splitted into 4 (interior) and 5 (exterior).
- The last step consists to discretize the new level-set that you want in your mesh.
Note that it is a very very experimental feature (implemented last week and I am confined with small children ;-)). In particular, for now I have done nothing regarding the topology checks so you can end with errors like this:
-- PHASE 3 : MESH IMPROVEMENT
*** Topological problem: non manifold surface at point 11907
In this case, it worth to try to adapt the output mesh with a classic call of mesh adaptation (it can work).
To conclude this long answer:
The drawbacks of this method are that:
- you need to compute a signed distance function so I don’t know how to do that from an open boundary (your second input);
- as the distance function is smooth, you will not be able to capture the sharp angles of you cylinder (the 2 boundary loops);
- you can meet bugs because it is freshly implemented.
I hope that it will help you.