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 libexamples/mmg3d/IsosurfDiscretization_lsOnly/main.[c|F90]
files.
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):
MMG3D_Init_mesh(MMG5_ARG_start,MMG5_ARG_ppMesh,&mmgMesh,MMG5_ARG_ppLs,&mmgLs,MMG5_ARG_end);
- and call the
MMG3D_mmg3dls(mmgMesh,mmgLs,NULL)
function instead of the MMG3D_mmg3dlib
one;
- to avoid the automatic detection of spurious sharp edges, it is better to disable the sharp angle detection (not shown in the library example):
MMG3D_Set_iparameter(mmgMesh,mmgSol,MMG3D_IPARAM_angle,0);
- you can choose the level-set to be discretized (default is 0), to discretize the 0.2 value:
MMG3D_Set_dparameter(mmgMesh,mmgSol,MMG3D_DPARAM_ls,0.2);
-
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 feature/multi-mat3d
branch:
-
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:
LSReferences
2
3 4 5
2 6 7
Which is equivalent to the following API calls:
MMG3D_Set_iparameter(mmgMesh,mmgLS,MMG3D_IPARAM_numberOfMat,2);
MMG3D_Set_multiMat(mmgMesh,mmgLs,3,MMG5_MMAT_Split,4,5);
MMG3D_Set_multiMat(mmgMesh,mmgLs,2,MMG5_MMAT_Split,6,7);
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.
Regards,
Algiane