gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
meshGRegionHxt.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 #include <map>
7 #include <set>
8 #include <stdexcept>
9 
10 #include "GmshConfig.h"
11 #include "meshGRegionHxt.h"
12 #include "Context.h"
13 #include "MVertex.h"
14 #include "GRegion.h"
15 #include "discreteRegion.h"
16 #include "GFace.h"
17 #include "MTetrahedron.h"
18 #include "MTriangle.h"
19 #include "MLine.h"
20 #include "MPoint.h"
21 #include "GmshMessage.h"
22 #include "BackgroundMeshTools.h"
23 #include "OS.h"
24 
25 #if defined(HAVE_HXT)
26 
27 extern "C" {
28 #include "hxt_omp.h"
29 #include "hxt_tetMesh.h"
30 #include "hxt_tetDelaunay.h"
31 }
32 
33 static int getNumThreads()
34 {
35  int nthreads = CTX::instance()->numThreads;
36  if(CTX::instance()->mesh.maxNumThreads3D > 0)
37  nthreads = CTX::instance()->mesh.maxNumThreads3D;
38  if(!nthreads) nthreads = Msg::GetMaxThreads();
39  return nthreads;
40 }
41 
42 static HXTStatus messageCallback(HXTMessage *msg)
43 {
44  if(msg) Msg::Info("%s", msg->string);
45  return HXT_STATUS_OK;
46 }
47 
48 static HXTStatus nodalSizesCallBack(double *pts, uint32_t *volume,
49  size_t numPts, void *userData)
50 {
51  std::vector<GRegion *> *allGR = (std::vector<GRegion *> *)userData;
52 
53  double lcGlob = CTX::instance()->lc;
54  int useInterpolatedSize = Extend2dMeshIn3dVolumes();
55 
56  HXT_INFO("Computing %smesh sizes...", useInterpolatedSize ? "interpolated " : "");
57 
58  int nthreads = getNumThreads();
59  bool exceptions = false;
60 #pragma omp parallel for schedule(dynamic) num_threads(nthreads)
61  for(size_t i = 0; i < numPts; i++) {
62  if(exceptions) continue;
63  if(volume[i] < 0 || volume[i] >= allGR->size()) {
64  Msg::Error("Invalid volume tag %d in mesh size calculation", volume[i]);
65  continue;
66  }
67  GRegion *gr = (*allGR)[volume[i]];
68  try{ // OpenMP forbids leaving block via exception
69  double lc = BGM_MeshSizeWithoutScaling(gr, 0, 0, pts[4 * i + 0],
70  pts[4 * i + 1], pts[4 * i + 2]);
71  if(useInterpolatedSize && pts[4 * i + 3] > 0.0)
72  pts[4 * i + 3] = std::min(pts[4 * i + 3], std::min(lcGlob, lc));
73  else
74  pts[4 * i + 3] = std::min(lcGlob, lc);
75  }
76  catch(...) {
77  exceptions = true;
78  }
79  }
80 
81  if(exceptions) throw std::runtime_error(Msg::GetLastError());
82 
83  HXT_INFO("Done computing %smesh sizes", useInterpolatedSize ? "interpolated " : "");
84 
85  return HXT_STATUS_OK;
86 }
87 
88 static HXTStatus getAllSurfaces(std::vector<GRegion *> &regions, HXTMesh *m,
89  std::vector<GFace *> &allSurfaces)
90 {
91  std::set<GFace *, GEntityPtrLessThan> allSurfacesSet;
92  if(m) {
93  m->brep.numVolumes = regions.size();
94  HXT_CHECK(hxtAlignedMalloc(&m->brep.numSurfacesPerVolume,
95  m->brep.numVolumes * sizeof(uint32_t)));
96  }
97  uint32_t to_alloc = 0;
98  for(std::size_t i = 0; i < regions.size(); i++) {
99  std::vector<GFace *> const &f = regions[i]->faces();
100  std::vector<GFace *> const &f_e = regions[i]->embeddedFaces();
101  if(m) {
102  m->brep.numSurfacesPerVolume[i] = f.size() + f_e.size();
103  to_alloc += m->brep.numSurfacesPerVolume[i];
104  }
105  allSurfacesSet.insert(f.begin(), f.end());
106  allSurfacesSet.insert(f_e.begin(), f_e.end());
107  }
108 
109  // verify that all elements are triangles
110  for (auto const &gf: allSurfacesSet) {
111  if (gf->quadrangles.size() != 0 || gf->polygons.size() != 0) {
112  size_t num = gf->quadrangles.size() + gf->polygons.size();
113  Msg::Error("Surface %d contains %zu elements which are not triangles. "
114  "The HXT 3D meshing algorithm only supports triangles.",
115  gf->tag(), num);
116  return HXT_STATUS_ERROR;
117  }
118  }
119 
120  allSurfaces.insert(allSurfaces.end(), allSurfacesSet.begin(),
121  allSurfacesSet.end());
122 
123  if(!m) return HXT_STATUS_OK;
124 
125  HXT_CHECK(
126  hxtAlignedMalloc(&m->brep.surfacesPerVolume, to_alloc * sizeof(uint32_t)));
127 
128  uint32_t counter = 0;
129  for(std::size_t i = 0; i < regions.size(); i++) {
130  std::vector<GFace *> const &f = regions[i]->faces();
131  std::vector<GFace *> const &f_e = regions[i]->embeddedFaces();
132  for(size_t j = 0; j < f.size(); j++)
133  m->brep.surfacesPerVolume[counter++] = f[j]->tag();
134  for(size_t j = 0; j < f_e.size(); j++)
135  m->brep.surfacesPerVolume[counter++] = f_e[j]->tag();
136  }
137 
138  return HXT_STATUS_OK;
139 }
140 
141 static HXTStatus getAllCurves(std::vector<GRegion *> &regions,
142  std::vector<GFace *> &surfaces, HXTMesh *m,
143  std::vector<GEdge *> &allCurves)
144 {
145  if(m) {
146  m->brep.numSurfaces = surfaces.size();
147  HXT_CHECK(hxtAlignedMalloc(&m->brep.numCurvesPerSurface,
148  m->brep.numSurfaces * sizeof(uint32_t)));
149  }
150  uint32_t to_alloc = 0;
151 
152  std::set<GEdge *, GEntityPtrLessThan> allCurvesSet;
153 
154  for(std::size_t i = 0; i < surfaces.size(); i++) {
155  std::vector<GEdge *> const &f = surfaces[i]->edges();
156  std::vector<GEdge *> const &f_e = surfaces[i]->embeddedEdges();
157  if(m) {
158  m->brep.numCurvesPerSurface[i] = f.size() + f_e.size();
159  to_alloc += m->brep.numCurvesPerSurface[i];
160  }
161  allCurvesSet.insert(f.begin(), f.end());
162  allCurvesSet.insert(f_e.begin(), f_e.end());
163  }
164  for(std::size_t i = 0; i < regions.size(); i++) {
165  std::vector<GEdge *> const &r_e = regions[i]->embeddedEdges();
166  allCurvesSet.insert(r_e.begin(), r_e.end());
167  }
168  allCurves.insert(allCurves.end(), allCurvesSet.begin(), allCurvesSet.end());
169 
170  if(!m) return HXT_STATUS_OK;
171 
172  HXT_CHECK(
173  hxtAlignedMalloc(&m->brep.curvesPerSurface, to_alloc * sizeof(uint32_t)));
174 
175  uint32_t counter = 0;
176  for(std::size_t i = 0; i < surfaces.size(); i++) {
177  std::vector<GEdge *> const &f = surfaces[i]->edges();
178  std::vector<GEdge *> const &f_e = surfaces[i]->embeddedEdges();
179  for(size_t j = 0; j < f.size(); j++)
180  m->brep.curvesPerSurface[counter++] = f[j]->tag();
181  for(size_t j = 0; j < f_e.size(); j++)
182  m->brep.curvesPerSurface[counter++] = f_e[j]->tag();
183  }
184 
185  return HXT_STATUS_OK;
186 }
187 
188 static HXTStatus Hxt2Gmsh(std::vector<GRegion *> &regions, HXTMesh *m,
189  std::map<MVertex *, uint32_t> &v2c,
190  std::vector<MVertex *> &c2v)
191 {
192  Msg::Debug("Start Hxt2Gmsh");
193 
194  HXT_CHECK( hxtAlignedFree(&m->tetrahedra.neigh) );
195  HXT_CHECK( hxtAlignedFree(&m->tetrahedra.flag) );
196  HXT_CHECK( hxtAlignedFree(&m->points.node) );
197  HXT_CHECK( hxtAlignedFree(&m->points.color) );
198 
199  std::map<uint32_t, GEdge *> i2e;
200  std::map<uint32_t, GFace *> i2f;
201  { // deleting old faces and edges, and filling i2e
202  std::vector<GFace *> allSurfaces;
203  std::vector<GEdge *> allCurves;
204  HXT_CHECK(getAllSurfaces(regions, nullptr, allSurfaces));
205  HXT_CHECK(getAllCurves(regions, allSurfaces, nullptr, allCurves));
206 
207  for(size_t j = 0; j < allCurves.size(); j++) {
208  i2e[allCurves[j]->tag()] = allCurves[j];
209  GEdge *ge = allCurves[j];
210  for(size_t i = 0; i < ge->lines.size(); i++) { delete ge->lines[i]; }
211  ge->lines.clear();
212  }
213 
214  for(size_t j = 0; j < allSurfaces.size(); j++) {
215  i2f[allSurfaces[j]->tag()] = allSurfaces[j];
216  GFace *gf = allSurfaces[j];
217  for(size_t i = 0; i < gf->triangles.size(); i++) { delete gf->triangles[i]; }
218  gf->triangles.clear();
219  }
220  }
221 
222  c2v.resize(m->vertices.num, nullptr);
223 
224  uint32_t warning = 0;
225  for(size_t i = 0; i < m->lines.num; i++) {
226  uint32_t c = m->lines.color[i];
227  auto ge = i2e.find(c);
228  if(ge == i2e.end()) {
229  if(warning != c) {
230  warning = c;
231  Msg::Warning("Could not find curve for HXT color %d", c);
232  }
233  continue;
234  }
235 
236  uint32_t i0 = m->lines.node[2 * i + 0];
237  uint32_t i1 = m->lines.node[2 * i + 1];
238  if(!c2v[i0]) {
239  double *x = &m->vertices.coord[4 * i0];
240  // FIXME compute true coordinates
241  c2v[i0] = new MEdgeVertex(x[0], x[1], x[2], ge->second, 0);
242  }
243  if(!c2v[i1]) {
244  // FIXME compute true coordinates
245  double *x = &m->vertices.coord[4 * i1];
246  c2v[i1] = new MEdgeVertex(x[0], x[1], x[2], ge->second, 0);
247  }
248  ge->second->lines.push_back(new MLine(c2v[i0], c2v[i1]));
249  }
250  HXT_CHECK( hxtAlignedFree(&m->lines.node) );
251  HXT_CHECK( hxtAlignedFree(&m->lines.color) );
252 
253  for(size_t i = 0; i < m->triangles.num; i++) {
254  uint32_t c = m->triangles.color[i];
255  auto gf = i2f.find(c);
256  if(gf == i2f.end()) {
257  if(warning != c) {
258  warning = c;
259  Msg::Warning("Could not find surface for HXT color %d", c);
260  }
261  continue;
262  }
263 
264  uint32_t i0 = m->triangles.node[3 * i + 0];
265  uint32_t i1 = m->triangles.node[3 * i + 1];
266  uint32_t i2 = m->triangles.node[3 * i + 2];
267  if(!c2v[i0]) {
268  // FIXME compute true coordinates
269  double *x = &m->vertices.coord[4 * i0];
270  c2v[i0] = new MFaceVertex(x[0], x[1], x[2], gf->second, 0, 0);
271  }
272  if(!c2v[i1]) {
273  // FIXME compute true coordinates
274  double *x = &m->vertices.coord[4 * i1];
275  c2v[i1] = new MFaceVertex(x[0], x[1], x[2], gf->second, 0, 0);
276  }
277  if(!c2v[i2]) {
278  // FIXME compute true coordinates
279  double *x = &m->vertices.coord[4 * i2];
280  c2v[i2] = new MFaceVertex(x[0], x[1], x[2], gf->second, 0, 0);
281  }
282  gf->second->triangles.push_back(new MTriangle(c2v[i0], c2v[i1], c2v[i2]));
283  }
284  HXT_CHECK( hxtAlignedFree(&m->triangles.node) );
285  HXT_CHECK( hxtAlignedFree(&m->triangles.color) );
286 
287 #if defined(_OPENMP)
288  int nthreads = getNumThreads();
289  if(nthreads > 1) {
290  const uint32_t nR = regions.size();
291  const uint32_t nV = m->vertices.num;
292 
293  size_t* ht_all, *ht_tot; // histograms for tets
294  HXT_CHECK( hxtCalloc(&ht_all, nR * (nthreads + 1), sizeof(size_t)) );
295  uint32_t* hp_all, *hp_tot; // histograms for points
296  HXT_CHECK( hxtCalloc(&hp_all, nR * (nthreads + 1) * 3 + (size_t) nV * nthreads,
297  sizeof(uint32_t)) );
298  uint32_t* vR_all = hp_all + nR * (nthreads + 1); // color per point and per thread
299 
300  #pragma omp parallel num_threads(nthreads)
301  {
302  #pragma omp single
303  {
304  nthreads = omp_get_num_threads(); /* the real number of threads */
305  ht_tot = ht_all + nR * nthreads;
306  hp_tot = hp_all + nR * nthreads;
307  }
308 
309  int threadID = omp_get_thread_num();
310  size_t* ht_this = ht_all + nR * threadID;
311  uint32_t* hp_this = hp_all + nR * threadID;
312  uint32_t* vR_this = vR_all + nV * threadID;
313 
314  // count the number of tetrahedra in each region in parallel
315  #pragma omp for schedule(static)
316  for(size_t i = 0; i < m->tetrahedra.num; i++) {
317  uint32_t c = m->tetrahedra.color[i];
318  if(c >= nR) continue;
319 
320  ht_this[c]++;
321  uint32_t *nodes = &m->tetrahedra.node[4 * i];
322  for(int j = 0; j < 4; j++) {
323  uint32_t pt = nodes[j];
324  if(!c2v[pt])
325  vR_this[pt] = c + 1;
326  }
327  }
328 
329  #pragma omp for schedule(static)
330  for(uint32_t pt = 0; pt < nV; pt++) {
331  if(c2v[pt]) continue;
332 
333  uint32_t color = 0;
334  for(int thrd = 0; thrd < nthreads; thrd++) {
335  if(vR_all[thrd * nV + pt]) {
336  color = vR_all[thrd * nV + pt];
337  break;
338  }
339  }
340  color--;
341  #ifdef DEBUG
342  if(color >= nR)
343  exit(HXT_ERROR_MSG(HXT_STATUS_ERROR, "no volume or color for pt %u", pt));
344  #endif
345  vR_all[pt] = color;
346  hp_this[color]++;
347  }
348 
349  #pragma omp for
350  for(uint32_t c2 = 0; c2 < 2 * nR; c2++) { // parallelism x 2 :p
351  uint32_t c = c2 >> 1;
352  if(c2 & 1) {
353  size_t sumt = 0;
354  for(int j = 0; j < nthreads + 1; j++) {
355  size_t tsumt = ht_all[j * nR + c] + sumt;
356  ht_all[j * nR + c] = sumt;
357  sumt = tsumt;
358  }
359  regions[c]->tetrahedra.resize(ht_tot[c], nullptr);
360  }
361  else {
362  uint32_t sump = 0;
363  for(int j = 0; j < nthreads + 1; j++) {
364  uint32_t tsump = hp_all[j * nR + c] + sump;
365  hp_all[j * nR + c] = sump;
366  sump = tsump;
367  }
368  regions[c]->mesh_vertices.resize(hp_tot[c], nullptr);
369  }
370  }
371 
372  #pragma omp for schedule(static)
373  for(uint32_t pt = 0; pt < nV; pt++) {
374  if(c2v[pt]) continue;
375 
376  uint32_t c = vR_all[pt];
377  GRegion *gr = regions[c];
378  double *x = &m->vertices.coord[4 * pt];
379  c2v[pt] = new MVertex(x[0], x[1], x[2], gr);
380  gr->mesh_vertices[hp_this[c]++] = c2v[pt];
381  }
382 
383 
384  #pragma omp for schedule(static)
385  for(size_t i = 0; i < m->tetrahedra.num; i++) {
386  uint32_t c = m->tetrahedra.color[i];
387  if(c >= nR) continue;
388 
389  uint32_t *nodes = &m->tetrahedra.node[4 * i];
390  regions[c]->tetrahedra[ht_this[c]++] = new MTetrahedron
391  (c2v[nodes[0]], c2v[nodes[1]], c2v[nodes[2]], c2v[nodes[3]]);
392  }
393  }
394 
395  HXT_CHECK( hxtFree(&ht_all) );
396  HXT_CHECK( hxtFree(&hp_all) );
397  }
398  else
399 #endif
400  {
401  for(size_t i = 0; i < m->tetrahedra.num; i++) {
402  uint16_t c = m->tetrahedra.color[i];
403  if(c >= regions.size())
404  continue;
405 
406  GRegion *gr = regions[c];
407  MVertex *vv[4];
408  uint32_t *nodes = &m->tetrahedra.node[4 * i];
409  for(int j = 0; j < 4; j++) {
410  if(c2v[nodes[j]]){
411  vv[j] = c2v[nodes[j]];
412  continue;
413  }
414 
415  double *x = &m->vertices.coord[4 * nodes[j]];
416  vv[j] = new MVertex(x[0], x[1], x[2], gr);
417  gr->mesh_vertices.push_back(vv[j]);
418  c2v[nodes[j]] = vv[j];
419  }
420 
421  gr->tetrahedra.push_back(new MTetrahedron(vv[0], vv[1], vv[2], vv[3]));
422  }
423  }
424 
425  Msg::Debug("End Hxt2Gmsh");
426  return HXT_STATUS_OK;
427 }
428 
429 HXTStatus Gmsh2Hxt(std::vector<GRegion *> &regions, HXTMesh *m,
430  std::map<MVertex *, uint32_t> &v2c,
431  std::vector<MVertex *> &c2v)
432 {
433  std::set<MVertex *> all;
434  std::vector<GFace *> surfaces;
435  std::vector<GEdge *> curves;
436  std::vector<GVertex *> points;
437  std::map<MVertex *, double> vlc;
438 
439  HXT_CHECK(getAllSurfaces(regions, m, surfaces));
440  HXT_CHECK(getAllCurves(regions, surfaces, m, curves));
441 
442  uint64_t index = 0, ntri = 0, nedg = 0, npts = 0;
443 
444  // embedded points in volumes (all other embedded points will be in the
445  // curve/surface meshes already)
446  for(GRegion *gr : regions) {
447  for(GVertex *gv : gr->embeddedVertices()) {
448  points.push_back(gv);
449  npts += gv->points.size();
450  for(size_t i = 0; i < gv->points.size(); i++) {
451  MVertex *v = gv->points[i]->getVertex(0);
452  all.insert(v);
453  if(gv->prescribedMeshSizeAtVertex() != MAX_LC)
454  vlc[v] = gv->prescribedMeshSizeAtVertex();
455  }
456  }
457  }
458 
459  for(size_t j = 0; j < curves.size(); j++) {
460  GEdge *ge = curves[j];
461  nedg += ge->lines.size();
462  for(size_t i = 0; i < ge->lines.size(); i++) {
463  all.insert(ge->lines[i]->getVertex(0));
464  all.insert(ge->lines[i]->getVertex(1));
465  }
466  }
467 
468  for(size_t j = 0; j < surfaces.size(); j++) {
469  GFace *gf = surfaces[j];
470  ntri += gf->triangles.size();
471  for(size_t i = 0; i < gf->triangles.size(); i++) {
472  all.insert(gf->triangles[i]->getVertex(0));
473  all.insert(gf->triangles[i]->getVertex(1));
474  all.insert(gf->triangles[i]->getVertex(2));
475  }
476  }
477 
478  m->vertices.num = m->vertices.size = all.size();
479  HXT_CHECK(
480  hxtAlignedMalloc(&m->vertices.coord, 4 * m->vertices.num * sizeof(double)));
481 
482  size_t count = 0;
483  c2v.resize(all.size());
484  for(MVertex *v : all) {
485  m->vertices.coord[4 * count + 0] = v->x();
486  m->vertices.coord[4 * count + 1] = v->y();
487  m->vertices.coord[4 * count + 2] = v->z();
488  m->vertices.coord[4 * count + 3] = 0;
489  if(CTX::instance()
490  ->mesh.lcFromPoints) { // size on embedded points in volume
491  auto it = vlc.find(v);
492  if(it != vlc.end()) m->vertices.coord[4 * count + 3] = it->second;
493  }
494  v2c[v] = count;
495  c2v[count++] = v;
496  }
497  all.clear();
498 
499  m->points.num = m->points.size = npts;
500  HXT_CHECK(
501  hxtAlignedMalloc(&m->points.node, (m->points.num) * sizeof(uint32_t)));
502  HXT_CHECK(
503  hxtAlignedMalloc(&m->points.color, (m->points.num) * sizeof(uint32_t)));
504  index = 0;
505  for(size_t j = 0; j < points.size(); j++) {
506  GVertex *gv = points[j];
507  for(size_t i = 0; i < gv->points.size(); i++) {
508  m->points.node[index] = v2c[gv->points[i]->getVertex(0)];
509  m->points.color[index] = gv->tag();
510  index++;
511  }
512  }
513 
514  m->lines.num = m->lines.size = nedg;
515  HXT_CHECK(
516  hxtAlignedMalloc(&m->lines.node, (m->lines.num) * 2 * sizeof(uint32_t)));
517  HXT_CHECK(
518  hxtAlignedMalloc(&m->lines.color, (m->lines.num) * sizeof(uint32_t)));
519  index = 0;
520  for(size_t j = 0; j < curves.size(); j++) {
521  GEdge *ge = curves[j];
522  for(size_t i = 0; i < ge->lines.size(); i++) {
523  m->lines.node[2 * index + 0] = v2c[ge->lines[i]->getVertex(0)];
524  m->lines.node[2 * index + 1] = v2c[ge->lines[i]->getVertex(1)];
525  m->lines.color[index] = ge->tag();
526  index++;
527  }
528  }
529 
530  m->triangles.num = m->triangles.size = ntri;
531  HXT_CHECK(hxtAlignedMalloc(&m->triangles.node,
532  (m->triangles.num) * 3 * sizeof(uint32_t)));
533  HXT_CHECK(hxtAlignedMalloc(&m->triangles.color,
534  (m->triangles.num) * sizeof(uint32_t)));
535  index = 0;
536  for(size_t j = 0; j < surfaces.size(); j++) {
537  GFace *gf = surfaces[j];
538  for(size_t i = 0; i < gf->triangles.size(); i++) {
539  m->triangles.node[3 * index + 0] = v2c[gf->triangles[i]->getVertex(0)];
540  m->triangles.node[3 * index + 1] = v2c[gf->triangles[i]->getVertex(1)];
541  m->triangles.node[3 * index + 2] = v2c[gf->triangles[i]->getVertex(2)];
542  m->triangles.color[index] = gf->tag();
543  index++;
544  }
545  }
546  return HXT_STATUS_OK;
547 }
548 
549 static HXTStatus _meshGRegionHxt(std::vector<GRegion *> &regions)
550 {
551  HXT_CHECK(hxtSetMessageCallback(messageCallback));
552 
553  HXTMesh *mesh;
554  HXT_CHECK(hxtMeshCreate(&mesh));
555 
556  std::map<MVertex *, uint32_t> v2c;
557  std::vector<MVertex *> c2v;
558  Gmsh2Hxt(regions, mesh, v2c, c2v);
559 
560  int nthreads = getNumThreads();
561 
562  HXTTetMeshOptions options = {
563  nthreads, // int defaultThreads;
564  nthreads, // int delaunayThreads;
565  nthreads, // int improveThreads;
566  1, // int reproducible;
567  (Msg::GetVerbosity() > 5) ? 2 : 1, // int verbosity;
568  1, // int stat;
569  1, // int refine;
570  CTX::instance()->mesh.optimize, // int optimize;
571  CTX::instance()->mesh.toleranceInitialDelaunay,// tolerance for tetgen
572  {
573  // quality
574  nullptr, // double (*callback)(.., userData)
575  nullptr, // void* userData;
576  CTX::instance()->mesh.optimizeThreshold // double qualityMin;
577  },
578  {// nodalSize
579 
580  // FIXME: put NULL when the callback is not needed (when we use the
581  // interpolated point size anyway)
582  nodalSizesCallBack, // HXTStatus (*callback)(double*, size_t, void*
583  // userData)
584  &regions, // void* meshSizeData;
586  CTX::instance()->mesh.lcFactor * regions[0]->getMeshSizeFactor()}};
587 
588  HXT_CHECK(hxtTetMesh(mesh, &options));
589 
590  HXT_CHECK(Hxt2Gmsh(regions, mesh, v2c, c2v));
591  HXT_CHECK(hxtMeshDelete(&mesh));
592  return HXT_STATUS_OK;
593 }
594 
595 int meshGRegionHxt(std::vector<GRegion *> &regions)
596 {
597  HXTStatus status = _meshGRegionHxt(regions);
598  if(status == HXT_STATUS_OK) return 0;
599  return 1;
600 }
601 
602 static HXTStatus _delaunayMeshIn3DHxt(std::vector<MVertex *> &verts,
603  std::vector<MTetrahedron *> &tets)
604 {
605  HXTMesh *mesh;
606  HXT_CHECK(hxtMeshCreate(&mesh));
607 
608  size_t nvert = verts.size();
609  HXT_CHECK(
610  hxtAlignedMalloc(&mesh->vertices.coord, nvert * 4 * sizeof(double)));
611  for(size_t i = 0; i < nvert; i++) {
612  mesh->vertices.coord[4 * i + 0] = verts[i]->x();
613  mesh->vertices.coord[4 * i + 1] = verts[i]->y();
614  mesh->vertices.coord[4 * i + 2] = verts[i]->z();
615  mesh->vertices.coord[4 * i + 3] = 0.;
616  }
617  mesh->vertices.num = nvert;
618  mesh->vertices.size = nvert;
619 
620  int nthreads = getNumThreads();
621 
622  HXTDelaunayOptions delOptions = {
623  nullptr, // bbox
624  nullptr, // nodalSizes
625  0, // numVertcesInMesh
626  0, // insertionFirst
627  0, // partitionability
628  1, // perfectDelaunay
629  0, // verbosity
630  0, // reproducible
631  nthreads // delaunayThreads (0 = omp_get_max_threads)
632  };
633 
634  // HXT_CHECK(hxtDelaunay(mesh, &delOptions));
635  HXTNodeInfo *nodeInfo;
636  HXT_CHECK(
637  hxtAlignedMalloc(&nodeInfo, sizeof(HXTNodeInfo) * mesh->vertices.num));
638  for(uint32_t i = 0; i < mesh->vertices.num; i++) {
639  nodeInfo[i].node = i;
640  nodeInfo[i].status = HXT_STATUS_TRYAGAIN;
641  }
642  HXT_CHECK(
643  hxtDelaunaySteadyVertices(mesh, &delOptions, nodeInfo, mesh->vertices.num));
644  HXT_CHECK(hxtAlignedFree(&nodeInfo));
645 
646  for(size_t i = 0; i < mesh->tetrahedra.num; i++) {
647  if(mesh->tetrahedra.node[i * 4 + 3] != UINT32_MAX) {
648  uint32_t myColor = mesh->tetrahedra.color ? mesh->tetrahedra.color[i] : 0;
649  if(myColor != HXT_COLOR_OUT) {
650  uint32_t *n = &mesh->tetrahedra.node[4 * i];
651  tets.push_back(
652  new MTetrahedron(verts[n[0]], verts[n[1]], verts[n[2]], verts[n[3]]));
653  }
654  }
655  }
656 
657  HXT_CHECK(hxtMeshDelete(&mesh));
658  return HXT_STATUS_OK;
659 }
660 
661 void delaunayMeshIn3DHxt(std::vector<MVertex *> &v,
662  std::vector<MTetrahedron *> &tets)
663 {
664  Msg::Info("Tetrahedrizing %d nodes...", v.size());
665  double t1 = Cpu(), w1 = TimeOfDay();
666  _delaunayMeshIn3DHxt(v, tets);
667  double t2 = Cpu(), w2 = TimeOfDay();
668  Msg::Info("Done tetrahedrizing %d nodes (Wall %gs, CPU %gs)", v.size(),
669  w2 - w1, t2 - t1);
670 }
671 
672 #else
673 
674 int meshGRegionHxt(std::vector<GRegion *> &regions)
675 {
676  Msg::Error("Gmsh should be compiled with Hxt to enable this option");
677  return -1;
678 }
679 
680 void delaunayMeshIn3DHxt(std::vector<MVertex *> &v,
681  std::vector<MTetrahedron *> &tets)
682 {
683  Msg::Error("Gmsh should be compiled with Hxt to enable this option");
684 }
685 
686 #endif
MTriangle.h
TimeOfDay
double TimeOfDay()
Definition: OS.cpp:399
Msg::GetVerbosity
static int GetVerbosity()
Definition: GmshMessage.cpp:254
GFace.h
MTetrahedron
Definition: MTetrahedron.h:34
GFace
Definition: GFace.h:33
GFace::triangles
std::vector< MTriangle * > triangles
Definition: GFace.h:428
contextMeshOptions::optimize
int optimize
Definition: Context.h:19
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
GEdge::lines
std::vector< MLine * > lines
Definition: GEdge.h:42
discreteRegion.h
OS.h
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
c
static double c(int i, int j, fullMatrix< double > &CA, const std::vector< SPoint3 > &P, const std::vector< SPoint3 > &Q)
Definition: discreteFrechetDistance.cpp:15
meshGRegionHxt.h
MVertex
Definition: MVertex.h:24
CTX::numThreads
int numThreads
Definition: Context.h:169
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
contextMeshOptions::lcMin
double lcMin
Definition: Context.h:25
MPoint.h
GmshMessage.h
MLine.h
MAX_LC
#define MAX_LC
Definition: GEntity.h:19
w1
const double w1
Definition: GaussQuadratureHex.cpp:18
BGM_MeshSizeWithoutScaling
double BGM_MeshSizeWithoutScaling(GEntity *ge, double U, double V, double X, double Y, double Z)
Definition: BackgroundMeshTools.cpp:211
contextMeshOptions::lcMax
double lcMax
Definition: Context.h:25
contextMeshOptions::toleranceInitialDelaunay
double toleranceInitialDelaunay
Definition: Context.h:25
contextMeshOptions::maxNumThreads3D
int maxNumThreads3D
Definition: Context.h:46
MLine
Definition: MLine.h:21
GVertex::points
std::vector< MPoint * > points
Definition: GVertex.h:120
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
GRegion.h
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
delaunayMeshIn3DHxt
void delaunayMeshIn3DHxt(std::vector< MVertex * > &v, std::vector< MTetrahedron * > &tets)
Definition: meshGRegionHxt.cpp:680
MEdgeVertex
Definition: MVertex.h:137
GVertex
Definition: GVertex.h:23
CTX::lc
double lc
Definition: Context.h:234
MVertex.h
Cpu
double Cpu()
Definition: OS.cpp:366
Msg::GetMaxThreads
static int GetMaxThreads()
Definition: GmshMessage.cpp:1637
GRegion::vertices
virtual std::vector< GVertex * > vertices() const
Definition: GRegion.cpp:603
Extend2dMeshIn3dVolumes
bool Extend2dMeshIn3dVolumes()
Definition: BackgroundMeshTools.cpp:345
CTX::mesh
contextMeshOptions mesh
Definition: Context.h:313
GEntity::tag
int tag() const
Definition: GEntity.h:280
MFaceVertex
Definition: MVertex.h:168
GRegion
Definition: GRegion.h:28
contextMeshOptions::optimizeThreshold
double optimizeThreshold
Definition: Context.h:22
MTriangle
Definition: MTriangle.h:26
Msg::GetLastError
static std::string GetLastError()
Definition: GmshMessage.cpp:362
Context.h
MTetrahedron.h
UINT32_MAX
#define UINT32_MAX
Definition: Gmsh.yy.cpp:344
contextMeshOptions::lcFactor
double lcFactor
Definition: Context.h:21
meshGRegionHxt
int meshGRegionHxt(std::vector< GRegion * > &regions)
Definition: meshGRegionHxt.cpp:674
GEdge
Definition: GEdge.h:26
BackgroundMeshTools.h
MVertex::y
double y() const
Definition: MVertex.h:61
GRegion::tetrahedra
std::vector< MTetrahedron * > tetrahedra
Definition: GRegion.h:163
GRegion::embeddedVertices
std::vector< GVertex * > & embeddedVertices()
Definition: GRegion.h:79
MVertex::x
double x() const
Definition: MVertex.h:60