gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
meshGRegionMMG.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 //
6 // Contributor(s):
7 // Algiane Froehly
8 //
9 
10 #include "GmshConfig.h"
11 #include "GmshMessage.h"
12 #include "meshGRegionMMG.h"
13 
14 #if defined(HAVE_MMG)
15 
16 #include <set>
17 #include "GRegion.h"
18 #include "GFace.h"
19 #include "MTetrahedron.h"
20 #include "MTriangle.h"
21 #include "MVertex.h"
22 #include "BackgroundMeshTools.h"
23 #include "Context.h"
24 
25 extern "C" {
26 #include <mmg/libmmg.h>
27 }
28 
29 static void MMG2gmsh(GRegion *gr, MMG5_pMesh mmg,
30  std::map<int, MVertex *> &mmg2gmsh)
31 {
32  std::map<int, MVertex *> kToMVertex;
33  int np, ne, nt, na, ref;
34  double cx, cy, cz;
35 
36  if(MMG3D_Get_meshSize(mmg, &np, &ne, nullptr, &nt, nullptr, &na) != 1)
37  Msg::Error("Mmg3d: unable to get mesh size");
38 
39  // Store the nodes from the Mmg structures into the gmsh structures
40 
41  // TODO: when MMG is allowed to modify the surface mesh, reclassify nodes
42  // accordingly
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);
46 
47  auto it = mmg2gmsh.find(ref);
48 
49  if(it == mmg2gmsh.end()) {
50  MVertex *v = new MVertex(cx, cy, cz, gr);
51  gr->mesh_vertices.push_back(v);
52  kToMVertex[k] = v;
53  }
54  else
55  kToMVertex[k] = it->second;
56  }
57 
58  // Store the tets from the Mmg structures into the Gmsh structures
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,
62  nullptr) != 1)
63  Msg::Error("Mmg3d: unable to get tetrahedron %d", k);
64 
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);
71  }
72  else {
73  gr->tetrahedra.push_back(new MTetrahedron(v1, v2, v3, v4));
74  }
75  }
76 
77 #if 0
78  // Store the triangles from the Mmg structures into the Gmsh structures
79 
80  // TODO: allow MMG to remesh (some of the) input surfaces; then store the new
81  // mesh
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);
86 
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);
92  }
93  else{
94  // ...
95  }
96  }
97 #endif
98 }
99 
100 static void gmsh2MMG(GRegion *gr, MMG5_pMesh mmg, MMG5_pSol sol,
101  std::map<int, MVertex *> &mmg2gmsh)
102 {
103  // Count mesh vertices
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));
110  }
111  int np = allVertices.size();
112 
113  // Count boundary triangles
114  std::vector<GFace *> f = gr->faces();
115  int nt = 0;
116  for(auto it = f.begin(); it != f.end(); ++it) {
117  nt += (*it)->triangles.size();
118  }
119 
120  // TODO: also import mesh lines
121 
122  // Get mesh tetrahedra
123  int ne = gr->tetrahedra.size();
124 
125  if(MMG3D_Set_meshSize(mmg, np, ne, 0, nt, 0, 0) != 1)
126  Msg::Error("Mmg3d: unable to set mesh size");
127 
128  if(MMG3D_Set_solSize(mmg, sol, MMG5_Vertex, np, MMG5_Tensor) != 1)
129  Msg::Error("Mmg3d: unable to set metric size");
130 
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++) {
134  MTriangle *t = (*it)->triangles[i];
135  double L = t->maxEdge();
136  for(int k = 0; k < 3; k++) {
137  MVertex *v = t->getVertex(k);
138  auto itv = LCS.find(v);
139  if(itv != LCS.end()) {
140  itv->second.first += L;
141  itv->second.second++;
142  }
143  else {
144  LCS[v] = std::make_pair(L, 1);
145  }
146  }
147  }
148  }
149 
150  int k = 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);
156 
157  gmsh2mmg_num[(*it)->getNum()] = k;
158 
159  MVertex *v = *it;
160  double U = 0, V = 0;
161  if(!v->onWhat()) continue;
162 
163  if(v->onWhat()->dim() == 1) { v->getParameter(0, U); }
164  else if(v->onWhat()->dim() == 2) {
165  v->getParameter(0, U);
166  v->getParameter(1, V);
167  }
168 
169  // double lc = BGM_MeshSize(v->onWhat(), U, V, v->x(), v->y(), v->z());
170  SMetric3 m = BGM_MeshMetric(v->onWhat(), U, V, v->x(), v->y(), v->z());
171 
172  auto itv = LCS.find(v);
173  if(itv != LCS.end()) {
174  mmg2gmsh[(*it)->getNum()] = *it;
175  // if (Extend2dMeshIn3dVolumes()){
176  double LL = itv->second.first / itv->second.second;
177  SMetric3 l4(1. / (LL * LL));
179  m = MM;
180  // lc = std::min(LL,lc);
181  // }
182  }
183 
184  if(MMG3D_Set_tensorSol(sol, m(0, 0), m(1, 0), m(2, 0), m(1, 1), m(2, 1),
185  m(2, 2), k) != 1) {
186  Msg::Error("Mmg3d: unable to set solution %d", k);
187  }
188  k++;
189  }
190 
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(),
197  k) != 1)
198  Msg::Error("Mmg3d: unable to set tetrahedron %d", k);
199  }
200 
201  k = 1;
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);
210  k++;
211  }
212  }
213 }
214 
215 static void updateSizes(GRegion *gr, MMG5_pMesh mmg, MMG5_pSol sol,
216  std::map<int, MVertex *> &mmg2gmsh)
217 {
218  std::vector<GFace *> f = gr->faces();
219 
220  std::map<MVertex *, std::pair<double, int> > LCS;
221  // if (Extend2dMeshIn3dVolumes()){
222  for(auto it = f.begin(); it != f.end(); ++it) {
223  for(unsigned int i = 0; i < (*it)->triangles.size(); i++) {
224  MTriangle *t = (*it)->triangles[i];
225  double L = t->maxEdge();
226  for(int k = 0; k < 3; k++) {
227  MVertex *v = t->getVertex(k);
228  auto itv = LCS.find(v);
229  if(itv != LCS.end()) {
230  itv->second.first += L;
231  itv->second.second++;
232  }
233  else {
234  LCS[v] = std::make_pair(L, 1);
235  }
236  }
237  }
238  }
239  // }
240 
241  int np;
242 
243  MMG3D_Get_meshSize(mmg, &np, nullptr, nullptr, nullptr, nullptr, nullptr);
244  for(int k = 1; k <= np; k++) {
245  double cx, cy, cz;
246  if(MMG3D_Get_vertex(mmg, &cx, &cy, &cz, nullptr, nullptr, nullptr) != 1)
247  Msg::Error("Mmg3d: unable to get vertex %d", k);
248 
249  SMetric3 m = BGM_MeshMetric(gr, 0, 0, cx, cy, cz);
250 
251  auto it = mmg2gmsh.find(k);
252 
253  if(it != mmg2gmsh.end() && Extend2dMeshIn3dVolumes()) {
254  auto itv = LCS.find(it->second);
255  if(itv != LCS.end()) {
256  double LL = itv->second.first / itv->second.second;
257  SMetric3 l4(1. / (LL * LL));
258  // printf("adding a size %g\n",LL);
260  m = MM;
261  }
262  }
263  if(m.determinant() < 1.e-30) {
264  m(0, 0) += 1.e-12;
265  m(1, 1) += 1.e-12;
266  m(2, 2) += 1.e-12;
267  }
268 
269  if(MMG3D_Set_tensorSol(sol, m(0, 0), m(1, 0), m(2, 0), m(1, 1), m(2, 1),
270  m(2, 2), k) != 1)
271  Msg::Error("Mmg3d: unable to set solution %d", k);
272  }
273 }
274 
275 void refineMeshMMG(GRegion *gr)
276 {
277  MMG5_pMesh mmg = nullptr;
278  MMG5_pSol sol = nullptr;
279 
280  std::map<int, MVertex *> mmg2gmsh;
281 
282  // Mmg structures allocations
283  MMG3D_Init_mesh(MMG5_ARG_start, MMG5_ARG_ppMesh, &mmg, MMG5_ARG_ppMet, &sol,
284  MMG5_ARG_end);
285 
286  // Store the Gmsh mesh into the Mmg structures
287  gmsh2MMG(gr, mmg, sol, mmg2gmsh);
288 
289  int iterMax = 10;
290 
291 // #define DEBUG
292 #ifdef DEBUG
293  char test0[] = "init.mesh";
294  MMG3D_saveMesh(mmg, test0);
295  MMG3D_saveSol(mmg, sol, test0);
296 #endif
297 
298  for(int ITER = 0; ITER < iterMax; ITER++) {
299  int nT, nTnow, np;
300 
301  MMG3D_Get_meshSize(mmg, nullptr, &nT, nullptr, nullptr, nullptr, nullptr);
302 
303  // Mmg parameters : verbosity + nosurf option
304  int verb_mmg = (Msg::GetVerbosity() < 2) ? -1 : Msg::GetVerbosity() - 4;
305  if(MMG3D_Set_iparameter(mmg, sol, MMG3D_IPARAM_verbose, verb_mmg) != 1)
306  Msg::Error("Mmsg3d: unable to set verbosity");
307 
308  // Set the nosurf parameter to 1 to preserve the boundaries
309  if(MMG3D_Set_iparameter(mmg, sol, MMG3D_IPARAM_nosurf, 1) != 1)
310  Msg::Error("Mmg3d: unable to preserve the boundaries");
311 
312  // Set the hausdorff parameter
313  double sqrt3Inv = 0.57735026919;
314  double hausd = 0.01 * sqrt3Inv * gr->bounds().diag();
315 
316  if(MMG3D_Set_dparameter(mmg, sol, MMG3D_DPARAM_hausd, hausd) != 1) {
317  Msg::Error("Mmg3d: unable to set the hausdorff parameter");
318  }
319 
320  if(MMG3D_mmg3dlib(mmg, sol) != MMG5_SUCCESS) {
321  Msg::Error("Mmg3d: failed (iteration %d)", ITER);
322  }
323  else {
324  MMG3D_Get_meshSize(mmg, &np, &nTnow, nullptr, nullptr, nullptr, nullptr);
325  Msg::Info("Mmg3d: success (iteration %d) - %d nodes %d tetrahedra", ITER,
326  np, nTnow);
327 
328  // Here we should interact with BGM
329  updateSizes(gr, mmg, sol, mmg2gmsh);
330 
331  if(fabs((double)(nTnow - nT)) < 0.05 * nT) break;
332  }
333  }
334 
335 #ifdef DEBUG
336  char test[] = "end.mesh";
337  MMG3D_saveMesh(mmg, test);
338  MMG3D_saveSol(mmg, sol, test);
339 #endif
340 
341  gr->deleteVertexArrays();
342  for(unsigned int i = 0; i < gr->tetrahedra.size(); ++i)
343  delete gr->tetrahedra[i];
344  gr->tetrahedra.clear();
345  for(unsigned int i = 0; i < gr->mesh_vertices.size(); ++i)
346  delete gr->mesh_vertices[i];
347  gr->mesh_vertices.clear();
348 
349  // Store the Mmg mesh into the Gmsh structures
350  MMG2gmsh(gr, mmg, mmg2gmsh);
351 
352  // Free the Mmg structure
353  MMG3D_Free_all(MMG5_ARG_start, MMG5_ARG_ppMesh, &mmg, MMG5_ARG_ppMet, &sol,
354  MMG5_ARG_end);
355 }
356 
357 #else
358 
360 {
361  Msg::Warning("This version of Gmsh is not compiled with MMG support: "
362  "skipping refinement");
363 }
364 
365 #endif
MTriangle.h
SBoundingBox3d::diag
double diag() const
Definition: SBoundingBox3d.h:93
SMetric3
Definition: STensor3.h:17
Msg::GetVerbosity
static int GetVerbosity()
Definition: GmshMessage.cpp:254
GFace.h
MTetrahedron
Definition: MTetrahedron.h:34
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
MVertex
Definition: MVertex.h:24
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
MVertex::z
double z() const
Definition: MVertex.h:62
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
MTriangle::getVertex
virtual MVertex * getVertex(int num)
Definition: MTriangle.h:62
MVertex::onWhat
GEntity * onWhat() const
Definition: MVertex.h:82
GmshMessage.h
SMetric3::determinant
double determinant() const
Definition: STensor3.cpp:74
refineMeshMMG
void refineMeshMMG(GRegion *gr)
Definition: meshGRegionMMG.cpp:359
meshGRegionMMG.h
GRegion::faces
virtual std::vector< GFace * > faces() const
Definition: GRegion.h:64
GRegion.h
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
MVertex.h
Extend2dMeshIn3dVolumes
bool Extend2dMeshIn3dVolumes()
Definition: BackgroundMeshTools.cpp:345
intersection_conserve_mostaniso
SMetric3 intersection_conserve_mostaniso(const SMetric3 &m1, const SMetric3 &m2)
Definition: STensor3.cpp:216
GEntity::tag
int tag() const
Definition: GEntity.h:280
GRegion
Definition: GRegion.h:28
MTriangle
Definition: MTriangle.h:26
MVertex::getParameter
virtual bool getParameter(int i, double &par) const
Definition: MVertex.h:97
Context.h
MTetrahedron.h
BGM_MeshMetric
SMetric3 BGM_MeshMetric(GEntity *ge, double U, double V, double X, double Y, double Z)
Definition: BackgroundMeshTools.cpp:284
MElement::maxEdge
virtual double maxEdge()
Definition: MElement.cpp:246
BackgroundMeshTools.h
MVertex::y
double y() const
Definition: MVertex.h:61
GEntity::dim
virtual int dim() const
Definition: GEntity.h:196
GEntity::deleteVertexArrays
void deleteVertexArrays()
Definition: GEntity.cpp:27
GRegion::bounds
virtual SBoundingBox3d bounds(bool fast=false)
Definition: GRegion.cpp:179
GRegion::tetrahedra
std::vector< MTetrahedron * > tetrahedra
Definition: GRegion.h:163
MVertex::x
double x() const
Definition: MVertex.h:60