10 #include "GmshConfig.h"
26 #include <mmg/libmmg.h>
29 static void MMG2gmsh(
GRegion *gr, MMG5_pMesh mmg,
30 std::map<int, MVertex *> &mmg2gmsh)
32 std::map<int, MVertex *> kToMVertex;
33 int np, ne, nt, na, ref;
36 if(MMG3D_Get_meshSize(mmg, &np, &ne,
nullptr, &nt,
nullptr, &na) != 1)
43 for(
int k = 1; k <= np; k++) {
44 if(MMG3D_Get_vertex(mmg, &cx, &cy, &cz, &ref,
nullptr,
nullptr) != 1)
45 Msg::Error(
"Mmg3d: unable to get vertex %d", k);
47 auto it = mmg2gmsh.find(ref);
49 if(it == mmg2gmsh.end()) {
55 kToMVertex[k] = it->second;
59 for(
int k = 1; k <= ne; k++) {
60 int v1mmg, v2mmg, v3mmg, v4mmg;
61 if(MMG3D_Get_tetrahedron(mmg, &v1mmg, &v2mmg, &v3mmg, &v4mmg, &ref,
63 Msg::Error(
"Mmg3d: unable to get tetrahedron %d", k);
65 MVertex *v1 = kToMVertex[v1mmg];
66 MVertex *v2 = kToMVertex[v2mmg];
67 MVertex *v3 = kToMVertex[v3mmg];
68 MVertex *v4 = kToMVertex[v4mmg];
69 if(!v1 || !v2 || !v3 || !v4) {
70 Msg::Error(
"Mmg3d: unknown vertex in tetrahedron %d", k);
82 for(
int k = 1; k <= nt; k++) {
83 int v1mmg, v2mmg, v3mmg;
84 if(MMG3D_Get_triangle(mmg, &v1mmg, &v2mmg, &v3mmg, &ref,
nullptr) != 1)
85 Msg::Error(
"Mmg3d: unable to get triangle %d", k);
87 MVertex *v1 = kToMVertex[v1mmg];
88 MVertex *v2 = kToMVertex[v2mmg];
89 MVertex *v3 = kToMVertex[v3mmg];
90 if(!v1 || !v2 || !v3) {
91 Msg::Error(
"Mmg3d: unknown vertex in triangle %d", k);
100 static void gmsh2MMG(
GRegion *gr, MMG5_pMesh mmg, MMG5_pSol sol,
101 std::map<int, MVertex *> &mmg2gmsh)
104 std::set<MVertex *> allVertices;
105 for(
unsigned int i = 0; i < gr->
tetrahedra.size(); i++) {
106 allVertices.insert(gr->
tetrahedra[i]->getVertex(0));
107 allVertices.insert(gr->
tetrahedra[i]->getVertex(1));
108 allVertices.insert(gr->
tetrahedra[i]->getVertex(2));
109 allVertices.insert(gr->
tetrahedra[i]->getVertex(3));
111 int np = allVertices.size();
114 std::vector<GFace *>
f = gr->
faces();
116 for(
auto it =
f.begin(); it !=
f.end(); ++it) {
117 nt += (*it)->triangles.size();
125 if(MMG3D_Set_meshSize(mmg, np, ne, 0, nt, 0, 0) != 1)
128 if(MMG3D_Set_solSize(mmg, sol, MMG5_Vertex, np, MMG5_Tensor) != 1)
129 Msg::Error(
"Mmg3d: unable to set metric size");
131 std::map<MVertex *, std::pair<double, int> > LCS;
132 for(
auto it =
f.begin(); it !=
f.end(); ++it) {
133 for(
unsigned int i = 0; i < (*it)->triangles.size(); i++) {
136 for(
int k = 0; k < 3; k++) {
138 auto itv = LCS.find(v);
139 if(itv != LCS.end()) {
140 itv->second.first += L;
141 itv->second.second++;
144 LCS[v] = std::make_pair(L, 1);
151 std::map<int, int> gmsh2mmg_num;
152 for(
auto it = allVertices.begin(); it != allVertices.end(); ++it) {
153 if(MMG3D_Set_vertex(mmg, (*it)->x(), (*it)->y(), (*it)->z(),
154 (*it)->getNum(), k) != 1)
155 Msg::Error(
"Mmg3d: unable to set vertex %d", k);
157 gmsh2mmg_num[(*it)->getNum()] = k;
161 if(!v->
onWhat())
continue;
172 auto itv = LCS.find(v);
173 if(itv != LCS.end()) {
174 mmg2gmsh[(*it)->getNum()] = *it;
176 double LL = itv->second.first / itv->second.second;
184 if(MMG3D_Set_tensorSol(sol, m(0, 0), m(1, 0), m(2, 0), m(1, 1), m(2, 1),
186 Msg::Error(
"Mmg3d: unable to set solution %d", k);
191 for(k = 1; k <= ne; k++) {
192 if(MMG3D_Set_tetrahedron(
193 mmg, gmsh2mmg_num[gr->
tetrahedra[k - 1]->getVertex(0)->getNum()],
194 gmsh2mmg_num[gr->
tetrahedra[k - 1]->getVertex(1)->getNum()],
195 gmsh2mmg_num[gr->
tetrahedra[k - 1]->getVertex(2)->getNum()],
196 gmsh2mmg_num[gr->
tetrahedra[k - 1]->getVertex(3)->getNum()], gr->
tag(),
198 Msg::Error(
"Mmg3d: unable to set tetrahedron %d", k);
202 for(
auto it =
f.begin(); it !=
f.end(); ++it) {
203 for(
unsigned int i = 0; i < (*it)->triangles.size(); i++) {
204 if(MMG3D_Set_triangle(
205 mmg, gmsh2mmg_num[(*it)->triangles[i]->getVertex(0)->getNum()],
206 gmsh2mmg_num[(*it)->triangles[i]->getVertex(1)->getNum()],
207 gmsh2mmg_num[(*it)->triangles[i]->getVertex(2)->getNum()],
208 (*it)->tag(), k) != 1)
209 Msg::Error(
"Mmg3d: unable to set triangle %d", k);
215 static void updateSizes(
GRegion *gr, MMG5_pMesh mmg, MMG5_pSol sol,
216 std::map<int, MVertex *> &mmg2gmsh)
218 std::vector<GFace *>
f = gr->
faces();
220 std::map<MVertex *, std::pair<double, int> > LCS;
222 for(
auto it =
f.begin(); it !=
f.end(); ++it) {
223 for(
unsigned int i = 0; i < (*it)->triangles.size(); i++) {
226 for(
int k = 0; k < 3; k++) {
228 auto itv = LCS.find(v);
229 if(itv != LCS.end()) {
230 itv->second.first += L;
231 itv->second.second++;
234 LCS[v] = std::make_pair(L, 1);
243 MMG3D_Get_meshSize(mmg, &np,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr);
244 for(
int k = 1; k <= np; k++) {
246 if(MMG3D_Get_vertex(mmg, &cx, &cy, &cz,
nullptr,
nullptr,
nullptr) != 1)
247 Msg::Error(
"Mmg3d: unable to get vertex %d", k);
251 auto it = mmg2gmsh.find(k);
254 auto itv = LCS.find(it->second);
255 if(itv != LCS.end()) {
256 double LL = itv->second.first / itv->second.second;
269 if(MMG3D_Set_tensorSol(sol, m(0, 0), m(1, 0), m(2, 0), m(1, 1), m(2, 1),
271 Msg::Error(
"Mmg3d: unable to set solution %d", k);
277 MMG5_pMesh mmg =
nullptr;
278 MMG5_pSol sol =
nullptr;
280 std::map<int, MVertex *> mmg2gmsh;
283 MMG3D_Init_mesh(MMG5_ARG_start, MMG5_ARG_ppMesh, &mmg, MMG5_ARG_ppMet, &sol,
287 gmsh2MMG(gr, mmg, sol, mmg2gmsh);
293 char test0[] =
"init.mesh";
294 MMG3D_saveMesh(mmg, test0);
295 MMG3D_saveSol(mmg, sol, test0);
298 for(
int ITER = 0; ITER < iterMax; ITER++) {
301 MMG3D_Get_meshSize(mmg,
nullptr, &nT,
nullptr,
nullptr,
nullptr,
nullptr);
305 if(MMG3D_Set_iparameter(mmg, sol, MMG3D_IPARAM_verbose, verb_mmg) != 1)
306 Msg::Error(
"Mmsg3d: unable to set verbosity");
309 if(MMG3D_Set_iparameter(mmg, sol, MMG3D_IPARAM_nosurf, 1) != 1)
310 Msg::Error(
"Mmg3d: unable to preserve the boundaries");
313 double sqrt3Inv = 0.57735026919;
314 double hausd = 0.01 * sqrt3Inv * gr->
bounds().
diag();
316 if(MMG3D_Set_dparameter(mmg, sol, MMG3D_DPARAM_hausd, hausd) != 1) {
317 Msg::Error(
"Mmg3d: unable to set the hausdorff parameter");
320 if(MMG3D_mmg3dlib(mmg, sol) != MMG5_SUCCESS) {
321 Msg::Error(
"Mmg3d: failed (iteration %d)", ITER);
324 MMG3D_Get_meshSize(mmg, &np, &nTnow,
nullptr,
nullptr,
nullptr,
nullptr);
325 Msg::Info(
"Mmg3d: success (iteration %d) - %d nodes %d tetrahedra", ITER,
329 updateSizes(gr, mmg, sol, mmg2gmsh);
331 if(fabs((
double)(nTnow - nT)) < 0.05 * nT)
break;
336 char test[] =
"end.mesh";
337 MMG3D_saveMesh(mmg, test);
338 MMG3D_saveSol(mmg, sol, test);
342 for(
unsigned int i = 0; i < gr->
tetrahedra.size(); ++i)
350 MMG2gmsh(gr, mmg, mmg2gmsh);
353 MMG3D_Free_all(MMG5_ARG_start, MMG5_ARG_ppMesh, &mmg, MMG5_ARG_ppMet, &sol,
361 Msg::Warning(
"This version of Gmsh is not compiled with MMG support: "
362 "skipping refinement");