26 #include "hxt_tools.h"
29 #include "hxt_tetMesh.h"
30 #include "hxt_tetUtils.h"
31 #include "hxt_tetFlag.h"
32 #include "hxt_tetDelaunay.h"
33 #include "hxt_tetRefine.h"
37 #if defined(HAVE_P4EST)
38 #include <p8est_search.h>
41 #if defined(HAVE_HXT) && defined(HAVE_P4EST)
42 static inline void norme2(
double v[3],
double *norme2)
44 *norme2 = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
47 static inline bool isPoint(
double x1,
double y1,
double z1,
double x2,
48 double y2,
double z2,
double tol)
50 return (fabs(x2 - x1) < tol && fabs(y2 - y1) < tol && fabs(z2 - z1) < tol);
53 void writeNodalCurvature(
double *nodalCurvature,
int size,
const char *filename)
55 FILE *
f = fopen(filename,
"w");
57 printf(
"Erreur : fileOutput == NULL\n");
61 for(
int i = 0; i < size; ++i) {
62 fprintf(
f,
"%f %f %f - %d\n", nodalCurvature[6 * i + 0],
63 nodalCurvature[6 * i + 1], nodalCurvature[6 * i + 2], i);
64 fprintf(
f,
"%f %f %f\n", nodalCurvature[6 * i + 3],
65 nodalCurvature[6 * i + 4], nodalCurvature[6 * i + 5]);
70 static HXTStatus getAllFacesOfAllRegions(std::vector<GRegion *> ®ions,
72 std::vector<GFace *> &allFaces)
74 std::set<GFace *, GEntityPtrLessThan> allFacesSet;
76 m->brep.numVolumes = regions.size();
77 HXT_CHECK(hxtAlignedMalloc(&m->brep.numSurfacesPerVolume,
78 m->brep.numVolumes *
sizeof(uint32_t)));
80 uint32_t to_alloc = 0;
81 for(std::size_t i = 0; i < regions.size(); i++) {
82 std::vector<GFace *>
const &
f = regions[i]->faces();
83 std::vector<GFace *>
const &f_e = regions[i]->embeddedFaces();
85 m->brep.numSurfacesPerVolume[i] =
f.size() + f_e.size();
86 to_alloc += m->brep.numSurfacesPerVolume[i];
88 allFacesSet.insert(
f.begin(),
f.end());
89 allFacesSet.insert(f_e.begin(), f_e.end());
91 allFaces.insert(allFaces.begin(), allFacesSet.begin(), allFacesSet.end());
93 if(!m)
return HXT_STATUS_OK;
96 hxtAlignedMalloc(&m->brep.surfacesPerVolume, to_alloc *
sizeof(uint32_t)));
99 for(std::size_t i = 0; i < regions.size(); i++) {
100 std::vector<GFace *>
const &
f = regions[i]->faces();
101 std::vector<GFace *>
const &f_e = regions[i]->embeddedFaces();
102 for(
size_t j = 0; j <
f.size(); j++)
103 m->brep.surfacesPerVolume[counter++] =
f[j]->tag();
104 for(
size_t j = 0; j < f_e.size(); j++)
105 m->brep.surfacesPerVolume[counter++] = f_e[j]->tag();
113 return HXT_STATUS_OK;
116 static HXTStatus getAllEdgesOfAllFaces(std::vector<GFace *> &
faces, HXTMesh *m,
117 std::vector<GEdge *> &allEdges)
120 m->brep.numSurfaces =
faces.size();
121 HXT_CHECK(hxtAlignedMalloc(&m->brep.numCurvesPerSurface,
122 m->brep.numSurfaces *
sizeof(uint32_t)));
124 uint32_t to_alloc = 0;
126 std::set<GEdge *, GEntityPtrLessThan> allEdgesSet;
127 for(std::size_t i = 0; i <
faces.size(); i++) {
128 std::vector<GEdge *>
const &
f =
faces[i]->edges();
129 std::vector<GEdge *>
const &f_e =
faces[i]->embeddedEdges();
131 m->brep.numCurvesPerSurface[i] =
f.size() + f_e.size();
132 to_alloc += m->brep.numCurvesPerSurface[i];
134 allEdgesSet.insert(
f.begin(),
f.end());
135 allEdgesSet.insert(f_e.begin(), f_e.end());
137 allEdges.insert(allEdges.begin(), allEdgesSet.begin(), allEdgesSet.end());
139 if(!m)
return HXT_STATUS_OK;
142 hxtAlignedMalloc(&m->brep.curvesPerSurface, to_alloc *
sizeof(uint32_t)));
144 uint32_t counter = 0;
145 for(std::size_t i = 0; i <
faces.size(); i++) {
146 std::vector<GEdge *>
const &
f =
faces[i]->edges();
147 std::vector<GEdge *>
const &f_e =
faces[i]->embeddedEdges();
148 for(
size_t j = 0; j <
f.size(); j++)
149 m->brep.curvesPerSurface[counter++] =
f[j]->tag();
150 for(
size_t j = 0; j < f_e.size(); j++)
151 m->brep.curvesPerSurface[counter++] = f_e[j]->tag();
153 return HXT_STATUS_OK;
156 HXTStatus Gmsh2Hxt(std::vector<GRegion *> ®ions, HXTMesh *m,
157 std::map<MVertex *, uint32_t> &v2c,
158 std::vector<MVertex *> &c2v);
160 HXTStatus Gmsh2Hxt(std::vector<GFace *> &
faces, HXTMesh *m,
161 std::map<MVertex *, uint32_t> &v2c,
162 std::vector<MVertex *> &c2v)
164 std::vector<GEdge *>
edges;
165 HXT_CHECK(getAllEdgesOfAllFaces(
faces, m,
edges));
166 std::set<MVertex *> all;
171 for(
size_t j = 0; j <
edges.size(); j++) {
173 nedg += ge->
lines.size();
174 for(
size_t i = 0; i < ge->
lines.size(); i++) {
175 all.insert(ge->
lines[i]->getVertex(0));
176 all.insert(ge->
lines[i]->getVertex(1));
180 for(
size_t j = 0; j <
faces.size(); j++) {
183 for(
size_t i = 0; i < gf->
triangles.size(); i++) {
184 all.insert(gf->
triangles[i]->getVertex(0));
185 all.insert(gf->
triangles[i]->getVertex(1));
186 all.insert(gf->
triangles[i]->getVertex(2));
190 m->vertices.num = m->vertices.size = all.size();
192 hxtAlignedMalloc(&m->vertices.coord, 4 * m->vertices.num *
sizeof(
double)));
195 c2v.resize(all.size());
206 m->vertices.coord[4 * count + 0] = v->x();
207 m->vertices.coord[4 * count + 1] = v->y();
208 m->vertices.coord[4 * count + 2] = v->z();
209 m->vertices.coord[4 * count + 3] = 0;
221 m->lines.num = m->lines.size = nedg;
225 hxtAlignedMalloc(&m->lines.node, (m->lines.num) * 2 *
sizeof(uint32_t)));
227 hxtAlignedMalloc(&m->lines.color, (m->lines.num) *
sizeof(uint32_t)));
229 for(
size_t j = 0; j <
edges.size(); j++) {
231 for(
size_t i = 0; i < ge->
lines.size(); i++) {
232 m->lines.node[2 * index + 0] = v2c[ge->
lines[i]->getVertex(0)];
233 m->lines.node[2 * index + 1] = v2c[ge->
lines[i]->getVertex(1)];
234 m->lines.color[index] = ge->
tag();
239 m->triangles.num = m->triangles.size = ntri;
240 HXT_CHECK(hxtAlignedMalloc(&m->triangles.node,
241 (m->triangles.num) * 3 *
sizeof(uint32_t)));
242 HXT_CHECK(hxtAlignedMalloc(&m->triangles.color,
243 (m->triangles.num) *
sizeof(uint32_t)));
246 for(
size_t j = 0; j <
faces.size(); j++) {
248 for(
size_t i = 0; i < gf->
triangles.size(); i++) {
249 m->triangles.node[3 * index + 0] = v2c[gf->
triangles[i]->getVertex(0)];
250 m->triangles.node[3 * index + 1] = v2c[gf->
triangles[i]->getVertex(1)];
251 m->triangles.node[3 * index + 2] = v2c[gf->
triangles[i]->getVertex(2)];
252 m->triangles.color[index] = gf->
tag();
256 return HXT_STATUS_OK;
265 HXTStatus Gmsh2HxtLocal(std::vector<GFace *> &
faces, HXTMesh *m,
266 std::map<MVertex *, uint32_t> &v2c,
267 std::vector<MVertex *> &c2v)
269 std::vector<GEdge *>
edges;
270 HXT_CHECK(getAllEdgesOfAllFaces(
faces, m,
edges));
271 std::set<MVertex *> all;
276 for(
size_t j = 0; j <
edges.size(); j++) {
278 nedg += ge->
lines.size();
279 for(
size_t i = 0; i < ge->
lines.size(); i++) {
285 for(
size_t j = 0; j <
faces.size(); j++) {
288 for(
size_t i = 0; i < gf->
triangles.size(); i++) {
289 all.insert(gf->
triangles[i]->getVertex(0));
290 all.insert(gf->
triangles[i]->getVertex(1));
291 all.insert(gf->
triangles[i]->getVertex(2));
297 m->vertices.num = m->vertices.size = all.size();
299 hxtAlignedMalloc(&m->vertices.coord, 4 * m->vertices.num *
sizeof(
double)));
302 c2v.resize(all.size());
303 for(
auto it = all.begin(); it != all.end(); it++) {
304 m->vertices.coord[4 * count + 0] = (*it)->x();
305 m->vertices.coord[4 * count + 1] = (*it)->y();
306 m->vertices.coord[4 * count + 2] = (*it)->z();
307 m->vertices.coord[4 * count + 3] = 0.0;
313 m->lines.num = m->lines.size = nedg;
317 hxtAlignedMalloc(&m->lines.node, (m->lines.num) * 2 *
sizeof(uint32_t)));
319 hxtAlignedMalloc(&m->lines.color, (m->lines.num) *
sizeof(uint32_t)));
321 for(
size_t j = 0; j <
edges.size(); j++) {
323 for(
size_t i = 0; i < ge->
lines.size(); i++) {
324 m->lines.node[2 * index + 0] = v2c[ge->
lines[i]->getVertex(0)];
325 m->lines.node[2 * index + 1] = v2c[ge->
lines[i]->getVertex(1)];
326 m->lines.color[index] = ge->
tag();
331 m->triangles.num = m->triangles.size = ntri;
332 HXT_CHECK(hxtAlignedMalloc(&m->triangles.node,
333 (m->triangles.num) * 3 *
sizeof(uint32_t)));
334 HXT_CHECK(hxtAlignedMalloc(&m->triangles.color,
335 (m->triangles.num) *
sizeof(uint32_t)));
338 for(
size_t j = 0; j <
faces.size(); j++) {
340 for(
size_t i = 0; i < gf->
triangles.size(); i++) {
341 m->triangles.node[3 * index + 0] = v2c[gf->
triangles[i]->getVertex(0)];
342 m->triangles.node[3 * index + 1] = v2c[gf->
triangles[i]->getVertex(1)];
343 m->triangles.node[3 * index + 2] = v2c[gf->
triangles[i]->getVertex(2)];
344 m->triangles.color[index] = gf->
tag();
348 return HXT_STATUS_OK;
351 HXTStatus Gmsh2HxtGlobal(std::vector<GFace *> &
faces, HXTMesh *m,
352 std::map<MVertex *, uint32_t> &v2c,
353 std::vector<MVertex *> &c2v)
355 std::vector<GEdge *>
edges;
356 HXT_CHECK(getAllEdgesOfAllFaces(
faces, m,
edges));
357 std::set<MVertex *> all;
360 uint64_t cumsumNoEdges = 0;
361 for(
size_t j = 0; j <
edges.size(); j++) {
363 cumsum += ge->
lines.size();
364 for(
size_t i = 0; i < ge->
lines.size(); i++) {
365 all.insert(ge->
lines[i]->getVertex(0));
366 all.insert(ge->
lines[i]->getVertex(1));
370 for(
size_t j = 0; j <
faces.size(); j++) {
374 for(
size_t i = 0; i < gf->
triangles.size(); i++) {
375 all.insert(gf->
triangles[i]->getVertex(0));
376 all.insert(gf->
triangles[i]->getVertex(1));
377 all.insert(gf->
triangles[i]->getVertex(2));
385 size_t count_c2v2 = 0;
386 for(
size_t j = 0; j <
faces.size(); ++j) {
390 for(
size_t i = 0; i < gf->
triangles.size(); i++) {
391 all.insert(gf->
triangles[i]->getVertex(0));
392 all.insert(gf->
triangles[i]->getVertex(1));
393 all.insert(gf->
triangles[i]->getVertex(2));
396 for(
auto it = all.begin(); it != all.end(); it++) {
398 c2v[count_c2v2++] = *it;
403 return HXT_STATUS_OK;
411 static bool rtreeCallback(uint64_t
id,
void *ctx)
413 std::vector<uint64_t> *vec =
reinterpret_cast<std::vector<uint64_t> *
>(ctx);
419 static p4est_connectivity_t *
422 const p4est_topidx_t num_vertices = 8;
423 const p4est_topidx_t num_trees = 1;
424 const p4est_topidx_t num_ett = 0;
425 const p4est_topidx_t num_ctt = 0;
427 double centreX = (forestOptions->
bbox[0] + forestOptions->
bbox[3]) / 2.0;
428 double centreY = (forestOptions->
bbox[1] + forestOptions->
bbox[4]) / 2.0;
429 double centreZ = (forestOptions->
bbox[2] + forestOptions->
bbox[5]) / 2.0;
430 double cX = (forestOptions->
bbox[3] - forestOptions->
bbox[0]) / 2.0;
431 double cY = (forestOptions->
bbox[4] - forestOptions->
bbox[1]) / 2.0;
432 double cZ = (forestOptions->
bbox[5] - forestOptions->
bbox[2]) / 2.0;
434 double scalingFactor =
436 double c = scalingFactor * fmax(fmax(cX, cY), cZ);
439 const double vertices[8 * 3] = {
440 centreX -
c, centreY -
c, centreZ -
c, centreX +
c, centreY -
c,
441 centreZ -
c, centreX -
c, centreY +
c, centreZ -
c, centreX +
c,
442 centreY +
c, centreZ -
c, centreX -
c, centreY -
c, centreZ +
c,
443 centreX +
c, centreY -
c, centreZ +
c, centreX -
c, centreY +
c,
444 centreZ +
c, centreX +
c, centreY +
c, centreZ +
c,
446 const p4est_topidx_t tree_to_vertex[1 * 8] = {0, 1, 2, 3, 4, 5, 6, 7};
447 const p4est_topidx_t tree_to_tree[1 * 6] = {0, 0, 0, 0, 0, 0};
448 const int8_t tree_to_face[1 * 6] = {0, 1, 2, 3, 4, 5};
450 return p4est_connectivity_new_copy(num_vertices, num_trees, 0, 0, vertices,
451 tree_to_vertex, tree_to_tree, tree_to_face,
452 nullptr, &num_ett,
nullptr,
nullptr,
453 nullptr, &num_ctt,
nullptr,
nullptr);
456 static p4est_connectivity_t *
459 const p4est_topidx_t num_vertices = 8;
460 const p4est_topidx_t num_trees = 1;
461 const p4est_topidx_t num_ett = 0;
462 const p4est_topidx_t num_ctt = 0;
464 double centreX = (forestOptions->
bbox[0] + forestOptions->
bbox[3]) / 2.0;
465 double centreY = (forestOptions->
bbox[1] + forestOptions->
bbox[4]) / 2.0;
466 double cX = (forestOptions->
bbox[3] - forestOptions->
bbox[0]) / 2.0;
467 double cY = (forestOptions->
bbox[4] - forestOptions->
bbox[1]) / 2.0;
469 double scalingFactor =
471 double c = scalingFactor * fmax(cX, cY);
474 const double vertices[8 * 3] = {
475 centreX -
c, centreY -
c, 0.0, centreX +
c, centreY -
c, 0.0,
476 centreX -
c, centreY +
c, 0.0, centreX +
c, centreY +
c, 0.0,
477 centreX -
c, centreY -
c, 0.0, centreX +
c, centreY -
c, 0.0,
478 centreX -
c, centreY +
c, 0.0, centreX +
c, centreY +
c, 0.0,
480 const p4est_topidx_t tree_to_vertex[1 * 8] = {0, 1, 2, 3, 4, 5, 6, 7};
481 const p4est_topidx_t tree_to_tree[1 * 6] = {0, 0, 0, 0, 0, 0};
482 const int8_t tree_to_face[1 * 6] = {0, 1, 2, 3, 4, 5};
484 return p4est_connectivity_new_copy(num_vertices, num_trees, 0, 0, vertices,
485 tree_to_vertex, tree_to_tree, tree_to_face,
486 nullptr, &num_ett,
nullptr,
nullptr,
487 nullptr, &num_ctt,
nullptr,
nullptr);
489 static inline double bulkSize(
double x,
double y,
double z,
double hBulk)
495 static inline void getCellCenter(p4est_t *p4est, p4est_topidx_t which_tree,
496 p4est_quadrant_t *q,
double xyz[3])
498 p4est_qcoord_t half_length = P4EST_QUADRANT_LEN(q->level) / 2;
499 p4est_qcoord_to_vertex(p4est->connectivity, which_tree, q->x + half_length,
500 q->y + half_length, q->z + half_length, xyz);
505 static inline void getCellBBox(p4est_t *p4est, p4est_topidx_t which_tree,
506 p4est_quadrant_t *q,
double min[3],
509 p4est_qcoord_t
length = P4EST_QUADRANT_LEN(q->level);
510 p4est_qcoord_to_vertex(p4est->connectivity, which_tree, q->x, q->y, q->z,
512 p4est_qcoord_to_vertex(p4est->connectivity, which_tree, q->x +
length,
517 static void getCellSize(p4est_t *p4est, p4est_topidx_t which_tree,
518 p4est_quadrant_t *q,
double *h)
520 double min[3], max[3];
521 p4est_qcoord_t
length = P4EST_QUADRANT_LEN(q->level);
522 p4est_qcoord_to_vertex(p4est->connectivity, which_tree, q->x, q->y, q->z,
524 p4est_qcoord_to_vertex(p4est->connectivity, which_tree, q->x +
length,
527 *h = fmax(max[0] - min[0], fmax(max[1] - min[1], max[2] - min[2]));
531 static inline void initializeCell(p4est_t *p4est, p4est_topidx_t which_tree,
538 getCellCenter(p4est, which_tree, q, center);
541 data->size = forestOptions->
sizeFunction(center[0], center[1], center[2],
542 forestOptions->
hbulk);
544 data->M =
SMetric3(1. / (0.4 * 0.4));
547 for(
int i = 0; i < P4EST_DIM; ++i) data->ds[i] = 0.0;
549 getCellSize(p4est, which_tree, q, &(data->h));
551 data->hasIntersection =
false;
557 HXT_CHECK(hxtAlignedMalloc(forestOptions,
sizeof(
ForestOptions)));
558 if(*forestOptions ==
nullptr)
return HXT_ERROR(HXT_STATUS_OUT_OF_MEMORY);
559 return HXT_STATUS_OK;
565 HXT_CHECK(hxtFree(forestOptions));
566 return HXT_STATUS_OK;
569 HXTStatus loadGlobalData(
ForestOptions *forestOptions,
const char *filename)
571 FILE *
f = fopen(filename,
"r");
572 char buf[BUFSIZ] = {
""};
573 if(fgets(buf, BUFSIZ,
f) ==
nullptr) {
574 return HXT_ERROR(HXT_STATUS_FILE_CANNOT_BE_OPENED);
576 sscanf(buf,
"%lf %lf", &forestOptions->
hmin, &forestOptions->
hmax);
578 Msg::Info(
"Loaded global data from %s", filename);
581 return HXT_STATUS_OK;
585 HXTStatus forestLoad(
Forest **forest,
const char *forestFile,
588 if(forestFile ==
nullptr)
return HXT_ERROR(HXT_STATUS_FILE_CANNOT_BE_OPENED);
590 HXT_CHECK(hxtMalloc(forest,
sizeof(
Forest)));
591 if(*forest ==
nullptr)
return HXT_ERROR(HXT_STATUS_OUT_OF_MEMORY);
593 HXT_CHECK(loadGlobalData(forestOptions, dataFile));
595 p4est_connectivity_t *connect;
596 sc_MPI_Comm mpicomm = sc_MPI_COMM_WORLD;
597 int load_data =
true;
598 int autopartition =
true;
599 int broadcasthead =
true;
601 (*forest)->p4est = p4est_load_ext(forestFile, mpicomm,
sizeof(
size_data_t),
602 load_data, autopartition, broadcasthead,
603 (
void *)forestOptions, &connect);
606 if(fO ==
nullptr)
return HXT_ERROR(HXT_STATUS_OUT_OF_MEMORY);
608 return HXT_STATUS_OK;
613 HXTStatus forestCreate(
int argc,
char **argv,
Forest **forest,
616 HXT_CHECK(hxtMalloc(forest,
sizeof(
Forest)));
617 if(*forest ==
nullptr)
return HXT_ERROR(HXT_STATUS_OUT_OF_MEMORY);
621 p4est_connectivity_t *connect;
626 mpiret = sc_MPI_Init(&argc, &argv);
627 SC_CHECK_MPI(mpiret);
628 mpicomm = sc_MPI_COMM_WORLD;
637 if(forestOptions->
dim == 3) {
638 connect = p8est_connectivity_new_cube(forestOptions);
641 connect = p8est_connectivity_new_square(forestOptions);
644 if(connect ==
nullptr)
return HXT_ERROR(HXT_STATUS_OUT_OF_MEMORY);
657 (*forest)->p4est = p4est_new(mpicomm, connect,
sizeof(
size_data_t),
658 initializeCell, (
void *)forestOptions);
659 (*forest)->forestOptions = forestOptions;
661 return HXT_STATUS_OK;
665 HXTStatus forestDelete(
Forest **forest)
668 p4est_connectivity_destroy((*forest)->p4est->connectivity);
669 p4est_destroy((*forest)->p4est);
674 int mpiret = sc_MPI_Finalize();
675 SC_CHECK_MPI(mpiret);
677 HXT_CHECK(hxtFree(forest));
679 return HXT_STATUS_OK;
689 static inline int refineToBulkSizeCallback(p4est_t *p4est,
690 p4est_topidx_t which_tree,
695 return data->
h > forestOptions->
hbulk;
700 static int curvatureRefineCallback(p4est_t *p4est, p4est_topidx_t which_tree,
705 getCellSize(p4est, which_tree, q, &h);
707 getCellCenter(p4est, which_tree, q, center);
709 if(forestOptions->
dim == 3) {
710 double min[3], max[3];
711 getCellBBox(p4est, which_tree, q, min, max);
713 std::vector<uint64_t> candidates;
714 forestOptions->
triRTree->
Search(min, max, rtreeCallback, &candidates);
716 if(!candidates.empty()) {
717 double kmax = -1.e22;
720 for(
auto tri = candidates.begin(); tri != candidates.end(); ++tri) {
721 for(
int i = 0; i < 3; ++i) {
723 forestOptions->mesh->triangles.node[(size_t)3 * (*tri) + i];
732 kmax = fmax(kmax, fmax(k1, k2));
733 kmin = fmin(kmin, fmin(k1, k2));
743 double hc = 2 * M_PI / (forestOptions->
nodePerTwoPi * kmax);
744 double nElemPerCell = 2;
746 if(h > fmin(hc / nElemPerCell, hf) && h >= forestOptions->
hmin) {
799 static int coarsenCallback(p4est_t *p4est, p4est_topidx_t which_tree,
800 p4est_quadrant_t *children[])
804 for(
int n = 0; n < P4EST_CHILDREN; ++n) {
807 double min[3], max[3];
808 getCellBBox(p4est, which_tree, children[n], min, max);
810 std::vector<uint64_t> candidates;
811 forestOptions->
triRTree->
Search(min, max, rtreeCallback, &candidates);
814 if(!candidates.empty())
return 0;
816 if(2.0 * data->
h > forestOptions->
hbulk)
return 0;
822 static void assignSizeAfterRefinement(p4est_iter_volume_info_t *info,
825 p4est_t *p4est = info->p4est;
826 p4est_quadrant_t *q = info->quad;
827 p4est_topidx_t which_tree = info->treeid;
832 getCellSize(p4est, which_tree, q, &h);
834 getCellCenter(p4est, which_tree, q, center);
836 if(forestOptions->
dim == 3) {
837 double min[3], max[3];
838 getCellBBox(p4est, which_tree, q, min, max);
840 std::vector<uint64_t> candidates;
841 forestOptions->
triRTree->
Search(min, max, rtreeCallback, &candidates);
843 if(!candidates.empty()) {
844 double kmax = -1.0e22;
846 for(
auto tri = candidates.begin(); tri != candidates.end(); ++tri) {
847 for(
int i = 0; i < 3; ++i) {
849 forestOptions->mesh->triangles.node[(size_t)3 * (*tri) + i];
855 kmax = fmax(kmax, fmax(k1, k2));
860 fmax(forestOptions->
hmin,
861 fmin(forestOptions->
hmax,
862 fmin(hf, 2 * M_PI / (forestOptions->
nodePerTwoPi * kmax))));
867 fmax(forestOptions->
hmin, fmin(forestOptions->
hmax, data->
size));
899 #if 0 // TODO remove once this is used
900 static void assignSizeAfterRefinementAniso(p4est_iter_volume_info_t * info,
void *user_data){
901 p4est_t *p4est = info->p4est;
902 p4est_quadrant_t *q = info->quad;
903 p4est_topidx_t which_tree = info->treeid;
908 getCellSize(p4est, which_tree, q, &h);
910 getCellCenter(p4est, which_tree, q, center);
920 if(forestOptions->
dim == 3){
921 double min[3], max[3];
922 getCellBBox(p4est, which_tree, q, min, max);
924 std::vector<uint64_t> candidates;
925 forestOptions->
triRTree->
Search(min, max, rtreeCallback, &candidates);
929 if(!candidates.empty()){
930 double kmax1 = -1.0e22;
931 double kmax2 = -1.0e22;
933 for(
auto tri = candidates.begin(); tri != candidates.end(); ++tri){
934 for(
int i = 0; i < 3; ++i){
935 int node = forestOptions->mesh->triangles.node[(size_t) 3*(*tri)+i];
964 kmax1 = fmax(kmax1,k1);
965 kmax2 = fmax(kmax2,k2);
969 double hc1 = fmax(forestOptions->
hmin, fmin(forestOptions->
hmax, 2*M_PI/(forestOptions->
nodePerTwoPi * kmax1)) );
970 double hc2 = fmax(forestOptions->
hmin, fmin(forestOptions->
hmax, 2*M_PI/(forestOptions->
nodePerTwoPi/4.0 * kmax2)) );
971 hf = fmax(forestOptions->
hmin, fmin(forestOptions->
hmax, hf));
973 SMetric3 m(1.0/(hf*hf), 1.0/(hc1*hc1), 1.0/(hc2*hc2), n, t1, t2);
975 data->
size = fmax(forestOptions->
hmin, fmin(forestOptions->
hmax, fmin(hf, 2*M_PI/(forestOptions->
nodePerTwoPi * fmax(kmax1,kmax2) )) ));
978 data->
size = fmax(forestOptions->
hmin, fmin(forestOptions->
hmax, data->
size));
1007 #endif // TODO remove once this is used
1009 HXTStatus forestRefine(
Forest *forest)
1012 p4est_refine_ext(forest->p4est, 1, P4EST_QMAXLEVEL, refineToBulkSizeCallback,
1013 initializeCell,
nullptr);
1015 p4est_refine_ext(forest->p4est, 1, P4EST_QMAXLEVEL, curvatureRefineCallback,
1016 initializeCell,
nullptr);
1018 p4est_coarsen_ext(forest->p4est, 1, 0, coarsenCallback, initializeCell,
1021 p4est_balance_ext(forest->p4est, P4EST_CONNECT_FACE, initializeCell,
nullptr);
1026 return HXT_ERROR(HXT_STATUS_FILE_CANNOT_BE_OPENED);
1029 return HXT_ERROR(HXT_STATUS_FILE_CANNOT_BE_OPENED);
1034 p4est_iterate(forest->p4est,
nullptr, forest->
forestOptions,
1035 assignSizeAfterRefinement,
nullptr,
nullptr,
nullptr);
1044 return HXT_STATUS_OK;
1051 static inline void resetCell(p4est_iter_volume_info_t *info,
void *user_data)
1060 static void computeGradientCenter(p4est_iter_face_info_t *info,
void *user_data)
1062 p4est_iter_face_side_t *side[2];
1063 sc_array_t *sides = &(info->sides);
1066 double s_avg, s_sum;
1072 side[0] = p4est_iter_fside_array_index_int(sides, 0);
1073 side[1] = p4est_iter_fside_array_index_int(sides, 1);
1075 if(sides->elem_count == 2) {
1076 for(
int i = 0; i < 2; i++) {
1085 if(side[i]->is_hanging) {
1086 for(
int j = 0; j < P4EST_HALF; j++) {
1087 data = (
size_data_t *)side[i]->is.hanging.quad[j]->p.user_data;
1088 s_avg += data->
size;
1091 s_avg /= P4EST_HALF;
1093 data_opp = (
size_data_t *)side[iOpp]->is.full.quad->p.user_data;
1095 switch(which_face_opp) {
1098 0.5 * (s_avg - data_opp->
size) / (data_opp->
h / 2. + data->
h / 2.);
1102 0.5 * (s_avg - data_opp->
size) / (data_opp->
h / 2. + data->
h / 2.);
1106 0.5 * (s_avg - data_opp->
size) / (data_opp->
h / 2. + data->
h / 2.);
1110 0.5 * (s_avg - data_opp->
size) / (data_opp->
h / 2. + data->
h / 2.);
1114 0.5 * (s_avg - data_opp->
size) / (data_opp->
h / 2. + data->
h / 2.);
1118 0.5 * (s_avg - data_opp->
size) / (data_opp->
h / 2. + data->
h / 2.);
1124 data = (
size_data_t *)side[i]->is.full.quad->p.user_data;
1125 if(side[iOpp]->is_hanging) {
1127 double s_avg_opp = 0;
1128 for(
int j = 0; j < P4EST_HALF; ++j) {
1130 (
size_data_t *)side[iOpp]->is.hanging.quad[j]->p.user_data;
1131 s_avg_opp += data_opp->
size;
1133 s_avg_opp /= P4EST_HALF;
1135 for(
int j = 0; j < P4EST_HALF; ++j) {
1137 (
size_data_t *)side[iOpp]->is.hanging.quad[j]->p.user_data;
1138 switch(which_face_opp) {
1140 data_opp->ds[0] -= 0.5 * (data->
size - data_opp->
size) /
1141 (data_opp->
h / 2. + data->
h / 2.);
1144 data_opp->ds[0] += 0.5 * (data->
size - data_opp->
size) /
1145 (data_opp->
h / 2. + data->
h / 2.);
1148 data_opp->ds[1] -= 0.5 * (data->
size - data_opp->
size) /
1149 (data_opp->
h / 2. + data->
h / 2.);
1152 data_opp->ds[1] += 0.5 * (data->
size - data_opp->
size) /
1153 (data_opp->
h / 2. + data->
h / 2.);
1156 data_opp->ds[2] -= 0.5 * (data->
size - data_opp->
size) /
1157 (data_opp->
h / 2. + data->
h / 2.);
1160 data_opp->ds[2] += 0.5 * (data->
size - data_opp->
size) /
1161 (data_opp->
h / 2. + data->
h / 2.);
1168 data_opp = (
size_data_t *)side[iOpp]->is.full.quad->p.user_data;
1169 switch(which_face_opp) {
1171 data_opp->ds[0] -= 0.5 * (data->
size - data_opp->
size) /
1172 (data_opp->
h / 2. + data->
h / 2.);
1175 data_opp->ds[0] += 0.5 * (data->
size - data_opp->
size) /
1176 (data_opp->
h / 2. + data->
h / 2.);
1179 data_opp->ds[1] -= 0.5 * (data->
size - data_opp->
size) /
1180 (data_opp->
h / 2. + data->
h / 2.);
1183 data_opp->ds[1] += 0.5 * (data->
size - data_opp->
size) /
1184 (data_opp->
h / 2. + data->
h / 2.);
1187 data_opp->ds[2] -= 0.5 * (data->
size - data_opp->
size) /
1188 (data_opp->
h / 2. + data->
h / 2.);
1191 data_opp->ds[2] += 0.5 * (data->
size - data_opp->
size) /
1192 (data_opp->
h / 2. + data->
h / 2.);
1202 HXTStatus forestComputeGradient(
Forest *forest)
1205 p4est_iterate(forest->p4est,
nullptr,
nullptr, resetCell,
nullptr,
nullptr,
1208 p4est_iterate(forest->p4est,
nullptr,
nullptr,
nullptr, computeGradientCenter,
1211 return HXT_STATUS_OK;
1214 static inline void getMaxGradient(p4est_iter_volume_info_t *info,
1217 p4est_quadrant_t *q = info->quad;
1219 double *gradMax =
static_cast<double *
>(user_data);
1220 gradMax[0] = SC_MAX(fabs(data->ds[0]), gradMax[0]);
1221 gradMax[1] = SC_MAX(fabs(data->ds[1]), gradMax[1]);
1222 gradMax[2] = SC_MAX(fabs(data->ds[2]), gradMax[2]);
1225 static inline void getMinSize(p4est_iter_volume_info_t *info,
void *user_data)
1227 p4est_quadrant_t *q = info->quad;
1229 double *minsize = (
double *)user_data;
1230 *minsize = fmin(*minsize, data->
size);
1233 HXTStatus forestGetMaxGradient(
Forest *forest,
double *gradMax)
1235 p4est_iterate(forest->p4est,
nullptr, (
void *)gradMax, getMaxGradient,
1236 nullptr,
nullptr,
nullptr);
1237 return HXT_STATUS_OK;
1240 HXTStatus forestGetMinSize(
Forest *forest,
double *minsize)
1242 double minSize = 1e22;
1243 p4est_iterate(forest->p4est,
nullptr, (
void *)&minSize, getMinSize,
nullptr,
1246 return HXT_STATUS_OK;
1249 static void limitSize(p4est_iter_face_info_t *info,
void *user_data)
1251 p4est_iter_face_side_t *side[2];
1252 sc_array_t *sides = &(info->sides);
1260 double alpha = forestOptions->
gradation - 1.0;
1263 side[0] = p4est_iter_fside_array_index_int(sides, 0);
1264 side[1] = p4est_iter_fside_array_index_int(sides, 1);
1266 if(sides->elem_count == 2) {
1267 for(
int i = 0; i < 2; ++i) {
1269 which_dir = side[i]->face / 2;
1270 which_face_opp = side[iOpp]->face;
1272 if(side[i]->is_hanging) {
1274 data_opp1 = (
size_data_t *)side[iOpp]->is.full.quad->p.user_data;
1276 for(
int j = 0; j < P4EST_HALF; ++j) {
1277 data = (
size_data_t *)side[i]->is.hanging.quad[j]->p.user_data;
1279 if(fabs(data->ds[which_dir]) > alpha + tol) {
1281 switch(which_face_opp) {
1285 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1290 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1295 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1300 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1305 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1310 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1315 switch(which_face_opp) {
1317 data_opp1->
size = fmin(
1319 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1322 data_opp1->
size = fmin(
1324 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1327 data_opp1->
size = fmin(
1329 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1332 data_opp1->
size = fmin(
1334 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1337 data_opp1->
size = fmin(
1339 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1342 data_opp1->
size = fmin(
1344 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1352 data = (
size_data_t *)side[i]->is.full.quad->p.user_data;
1354 if(fabs(data->ds[which_dir]) > alpha + tol) {
1355 if(side[iOpp]->is_hanging) {
1357 for(
int j = 0; j < P4EST_HALF; ++j) {
1359 (
size_data_t *)side[iOpp]->is.hanging.quad[j]->p.user_data;
1361 switch(which_face_opp) {
1365 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1370 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1375 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1380 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1385 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1390 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1395 switch(which_face_opp) {
1397 data_opp1->
size = fmin(
1399 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1402 data_opp1->
size = fmin(
1404 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1407 data_opp1->
size = fmin(
1409 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1412 data_opp1->
size = fmin(
1414 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1417 data_opp1->
size = fmin(
1419 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1422 data_opp1->
size = fmin(
1424 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1432 data_opp1 = (
size_data_t *)side[iOpp]->is.full.quad->p.user_data;
1434 switch(which_face_opp) {
1438 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1443 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1448 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1453 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1458 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1463 (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1468 switch(which_face_opp) {
1470 data_opp1->
size = fmin(
1472 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1475 data_opp1->
size = fmin(
1477 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1480 data_opp1->
size = fmin(
1482 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1485 data_opp1->
size = fmin(
1487 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1490 data_opp1->
size = fmin(
1492 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1495 data_opp1->
size = fmin(
1497 data->
size + (alpha) * (data_opp1->
h / 2. + data->
h / 2.));
1508 HXTStatus forestLimitSize(
Forest *forest)
1510 p4est_iterate(forest->p4est,
nullptr, (
void *)forest->
forestOptions,
nullptr,
1511 limitSize,
nullptr,
nullptr);
1512 return HXT_STATUS_OK;
1515 HXTStatus forestSizeSmoothing(
Forest *forest)
1517 double gradMax[3], tol = 1e-3, gradLinf = 1e22;
1519 int iter = 0, nmax = 100;
1524 while(iter++ < nmax &&
1526 HXT_CHECK(forestComputeGradient(forest));
1527 HXT_CHECK(forestLimitSize(
1529 for(
int i = 0; i < 3; ++i) gradMax[i] = -1e22;
1530 HXT_CHECK(forestGetMaxGradient(forest, gradMax));
1531 gradLinf = fmax(fabs(gradMax[0]), fmax(fabs(gradMax[1]), fabs(gradMax[2])));
1535 Msg::Info(
"Max gradient after smoothing : (%f - %f - %f)", fabs(gradMax[0]),
1536 fabs(gradMax[1]), fabs(gradMax[2]));
1537 return HXT_STATUS_OK;
1545 static int searchAndAssignConstant(p4est_t *p4est, p4est_topidx_t which_tree,
1546 p4est_quadrant_t *q,
1547 p4est_locidx_t local_num,
void *point)
1549 bool in_box, is_leaf = local_num >= 0;
1556 double h, center[3];
1558 getCellSize(p4est, which_tree, q, &h);
1561 getCellCenter(p4est, which_tree, q, center);
1568 in_box = (p->x <= center[0] + h / 2.) && (p->x >= center[0] - h / 2.);
1569 in_box &= (p->y <= center[1] + h / 2.) && (p->y >= center[1] - h / 2.);
1570 in_box &= (p->z <= center[2] + h / 2.) && (p->z >= center[2] - h / 2.);
1573 if(in_box && is_leaf) {
1574 p->size = fmin(p->size, data->
size);
1575 p->size = fmax(forestOptions->
hmin, fmin(forestOptions->
hmax, p->size));
1582 static int searchAndAssignConstantAniso(p4est_t *p4est,
1583 p4est_topidx_t which_tree,
1584 p4est_quadrant_t *q,
1585 p4est_locidx_t local_num,
void *point)
1587 bool in_box, is_leaf = local_num >= 0;
1594 double h, center[3];
1596 getCellSize(p4est, which_tree, q, &h);
1599 getCellCenter(p4est, which_tree, q, center);
1602 in_box = (p->x < center[0] + h / 2. +
epsilon) &&
1603 (p->x > center[0] - h / 2. -
epsilon);
1604 in_box &= (p->y < center[1] + h / 2. +
epsilon) &&
1605 (p->y > center[1] - h / 2. -
epsilon);
1606 in_box &= (p->z < center[2] + h / 2. +
epsilon) &&
1607 (p->z > center[2] - h / 2. -
epsilon);
1613 if(in_box && is_leaf) {
1624 static int searchAndAssignLinear(p4est_t *p4est, p4est_topidx_t which_tree,
1625 p4est_quadrant_t *q, p4est_locidx_t local_num,
1628 bool in_box =
false, is_leaf = local_num >= 0;
1635 double h, center[3];
1638 getCellSize(p4est, which_tree, q, &h);
1639 getCellCenter(p4est, which_tree, q, center);
1652 SPoint3 C(center), P(p->x, p->y, p->z);
1658 in_box = fabs(
dot(dir, dx)) <= (h / 2. +
epsilon) &&
1663 if(in_box && is_leaf) {
1664 p->size = fmin(p->size, data->
size + data->ds[0] * (p->x - center[0]) +
1665 data->ds[1] * (p->y - center[1]) +
1666 data->ds[2] * (p->z - center[2]));
1667 p->size = fmax(forestOptions->
hmin, fmin(forestOptions->
hmax, p->size));
1712 HXTStatus forestSearchOne(
Forest *forest,
double x,
double y,
double z,
1713 double *size,
int linear)
1715 sc_array_t *points = sc_array_new_size(
sizeof(
size_point_t), 1);
1726 p4est_search(forest->p4est,
nullptr, searchAndAssignLinear, points);
1729 p4est_search(forest->p4est,
nullptr, searchAndAssignConstant, points);
1733 Msg::Info(
"(%+.4f,%+.4f,%+.4f) was not found in the meshsize field 8-|", x,
1739 sc_array_destroy(points);
1741 return HXT_STATUS_OK;
1744 HXTStatus forestSearchOneAniso(
Forest *forest,
double x,
double y,
double z,
1747 sc_array_t *points = sc_array_new_size(
sizeof(
size_point_t), 1);
1756 p4est_search(forest->p4est,
nullptr, searchAndAssignConstantAniso, points);
1759 Msg::Info(
"Point (%f,%f,%f) n'a pas été trouvé dans l'octree 8-|", x, y,
z);
1765 sc_array_destroy(points);
1767 return HXT_STATUS_OK;
1771 HXTStatus hxtForestSearch(
Forest *forest, std::vector<double> *x,
1772 std::vector<double> *y, std::vector<double> *
z,
1773 std::vector<double> *size)
1776 sc_array_t *points = sc_array_new_size(
sizeof(
size_point_t), (*x).size());
1779 for(
size_t i = 0; i < (*x).size(); ++i) {
1788 p4est_search(forest->p4est,
nullptr, searchAndAssignLinear, points);
1791 for(
size_t i = 0; i < (*x).size(); ++i) {
1793 (*size)[i] = p->
size;
1797 sc_array_destroy(points);
1799 return HXT_STATUS_OK;
1808 static void sort4(
int *d)
1810 #define SWAP(x, y) \
1837 bool b0 = (t10 == t20) || (t10 == t21) || (t10 == t22) || (t10 == t23);
1838 bool b1 = (t11 == t20) || (t11 == t21) || (t11 == t22) || (t11 == t23);
1839 bool b2 = (t12 == t20) || (t12 == t21) || (t12 == t22) || (t12 == t23);
1840 bool b3 = (t13 == t20) || (t13 == t21) || (t13 == t22) || (t13 == t23);
1842 if(b0 +
b1 + b2 + b3 < 3) {
return -1; }
1844 int v1[4] = {t10, t11, t12, t13};
1845 int v1cpy[4] = {t10, t11, t12, t13};
1846 int v2[4] = {t20, t21, t22, t23};
1858 bool b00 = (t11 == t21) && (t12 == t22) && (t13 == t23);
1859 bool b01 = (t11 == t20) && (t12 == t22) && (t13 == t23);
1860 bool b02 = (t11 == t20) && (t12 == t21) && (t13 == t23);
1861 bool b03 = (t11 == t20) && (t12 == t21) && (t13 == t22);
1863 bool b10 = (t10 == t21) && (t12 == t22) && (t13 == t23);
1864 bool b11 = (t10 == t20) && (t12 == t22) && (t13 == t23);
1865 bool b12 = (t10 == t20) && (t12 == t21) && (t13 == t23);
1866 bool b13 = (t10 == t20) && (t12 == t21) && (t13 == t22);
1868 bool b20 = (t10 == t21) && (t11 == t22) && (t12 == t23);
1869 bool b21 = (t10 == t20) && (t11 == t22) && (t12 == t23);
1870 bool b22 = (t10 == t20) && (t11 == t21) && (t12 == t23);
1871 bool b23 = (t10 == t20) && (t11 == t21) && (t12 == t22);
1873 bool b30 = (t10 == t21) && (t11 == t22) && (t13 == t23);
1874 bool b31 = (t10 == t20) && (t11 == t22) && (t13 == t23);
1875 bool b32 = (t10 == t20) && (t11 == t21) && (t13 == t23);
1876 bool b33 = (t10 == t20) && (t11 == t21) && (t13 == t22);
1879 if(b00 || b01 || b02 || b03)
1881 else if(b10 || b11 || b12 || b13)
1883 else if(b20 || b21 || b22 || b23)
1885 else if(b30 || b31 || b32 || b33)
1889 if(v1cpy[0] == v1[missing])
1891 else if(v1cpy[1] == v1[missing])
1893 else if(v1cpy[2] == v1[missing])
1895 else if(v1cpy[3] == v1[missing])
1909 return dot(normal, tmp) <= 0;
1914 HXTStatus featureSize(
Forest *forest)
1921 std::vector<MVertex *> allVertices;
1922 std::vector<double> sizeAtVertices(mesh->vertices.num, DBL_MAX);
1923 for(
size_t i = 0; i < mesh->vertices.num; ++i) {
1924 allVertices.push_back(
new MVertex(mesh->vertices.coord[4 * i + 0],
1925 mesh->vertices.coord[4 * i + 1],
1926 mesh->vertices.coord[4 * i + 2]));
1929 int firstVertex = allVertices[0]->getNum();
1933 std::vector<MTetrahedron *> allTets;
1934 std::vector<std::vector<uint64_t> > tetIncidents;
1935 std::vector<std::vector<MEdge> > edgIncidents;
1936 for(uint32_t i = 0; i < mesh->vertices.num; ++i) {
1937 std::vector<uint64_t> vTet;
1938 tetIncidents.push_back(vTet);
1939 std::vector<MEdge> vEdg;
1940 edgIncidents.push_back(vEdg);
1943 for(
size_t i = 0; i < mesh->tetrahedra.num; ++i) {
1944 if(mesh->tetrahedra.node[4 * i + 3] != HXT_GHOST_VERTEX) {
1946 new MTetrahedron(allVertices[mesh->tetrahedra.node[4 * i + 0]],
1947 allVertices[mesh->tetrahedra.node[4 * i + 1]],
1948 allVertices[mesh->tetrahedra.node[4 * i + 2]],
1949 allVertices[mesh->tetrahedra.node[4 * i + 3]]));
1951 for(
size_t j = 0; j < 4; ++j) {
1952 tetIncidents[mesh->tetrahedra.node[4 * i + j]].push_back(count);
1954 for(
size_t j = 0; j < 6; ++j) {
1955 MEdge e = allTets[count]->getEdge(j);
1956 edgIncidents[allTets[count]->getEdge(j).getVertex(0)->getNum() -
1959 edgIncidents[allTets[count]->getEdge(j).getVertex(1)->getNum() -
1967 std::set<MEdge, MEdgeLessThan> axis;
1970 FILE *file = fopen(
"medialAxis_toDraw.pos",
"w");
1971 if(file ==
nullptr)
return HXT_ERROR(HXT_STATUS_FILE_CANNOT_BE_OPENED);
1972 FILE *file2 = fopen(
"keptEdges.pos",
"w");
1973 if(file2 ==
nullptr)
return HXT_ERROR(HXT_STATUS_FILE_CANNOT_BE_OPENED);
1977 fprintf(file,
"View \"medialAxis\" {\n");
1978 fprintf(file2,
"View \"keptEdges\" {\n");
1983 for(
size_t i = 0; i < mesh->vertices.num; ++i) {
1985 SPoint3 pole(0., 0., 0.), tmp(0., 0., 0.),
1986 p(mesh->vertices.coord[4 * i + 0], mesh->vertices.coord[4 * i + 1],
1987 mesh->vertices.coord[4 * i + 2]);
1990 for(
size_t j = 0; j < tetIncidents[i].size(); ++j) {
1991 tmp = allTets[tetIncidents[i][j]]->circumcenter();
1992 if(p.distance(tmp) > d) pole = tmp;
1993 d = fmax(d, p.distance(tmp));
1998 double D = -(vp[0] * p[0] + vp[1] * p[1] + vp[2] * p[2]);
2004 std::vector<MFace> up;
2006 double orientj, orientk;
2007 for(
size_t j = 0; j < tetIncidents[i].size(); ++j) {
2008 uint64_t tetj = tetIncidents[i][j];
2009 SPoint3 cj = allTets[tetj]->circumcenter();
2010 for(
size_t k = j; k < tetIncidents[i].size(); ++k) {
2011 uint64_t tetk = tetIncidents[i][k];
2013 indFace = commonFaceTetFast(allTets[tetj], allTets[tetk]);
2015 SPoint3 ck = allTets[tetk]->circumcenter();
2017 (
double *)p2, (
double *)cj);
2019 (
double *)p2, (
double *)ck);
2020 if(orientj * orientk < 0) {
2021 up.push_back(allTets[tetj]->getFace(indFace));
2029 double theta = M_PI / 8., rho = 8., maxAngle, minRatio, localAngle, alpha0,
2031 std::vector<MEdge> checkedEdges;
2033 for(
size_t j = 0; j < edgIncidents[i].size();
2036 MEdge e = edgIncidents[i][j];
2038 for(
size_t k = 0; k < checkedEdges.size(); ++k) {
2039 if(e == checkedEdges[k]) {
2045 if(checked) {
continue; }
2047 checkedEdges.push_back(e);
2055 if(v0 == i || v1 == i) {
2056 for(
size_t l = 0; l < up.size(); ++l) {
2059 localAngle = fmin(localAngle, fabs(M_PI - localAngle));
2060 maxAngle = fmax(maxAngle, localAngle);
2063 MTriangle tri(up[l].getVertex(0), up[l].getVertex(1),
2064 up[l].getVertex(2));
2065 minRatio = fmin(minRatio, e.
length() / tri.getOuterRadius());
2068 if(maxAngle < M_PI / 2. - theta || minRatio > rho) {
2074 if(fmin(alpha0, fabs(M_PI - alpha0)) < M_PI / 8. &&
2075 fmin(alpha1, fabs(M_PI - alpha1)) < M_PI / 8.) {
2078 auto ret = axis.insert(e);
2081 double h = e.
length() / nLayersPerGap;
2084 sizeAtVertices[v0] = fmin(h, sizeAtVertices[v0]);
2085 sizeAtVertices[v1] = fmin(h, sizeAtVertices[v1]);
2087 fprintf(file2,
"SL(%f,%f,%f, %f,%f,%f){%f,%f};\n",
2095 std::vector<SPoint3> centers;
2096 for(
size_t jj = 0; jj < tetIncidents[i].size(); ++jj) {
2097 uint64_t tetj = tetIncidents[i][jj];
2098 for(
size_t b = 0; b < 6; ++b) {
2099 if(allTets[tetj]->getEdge(b) == e)
2100 centers.push_back(allTets[tetj]->circumcenter());
2103 if(centers.size() > 2) {
2106 for(
size_t a = 0; a < centers.size(); ++a) {
2109 c /= centers.size();
2114 sort(centers.begin(), centers.end(),
2116 return sortClockwise(a, b, c, normal);
2119 for(
size_t a = 1; a < centers.size() - 1; ++a) {
2121 "ST(%f,%f,%f, %f,%f,%f, %f,%f,%f){%d,%d,%d};\n",
2122 centers[0][0], centers[0][1], centers[0][2],
2123 centers[a][0], centers[a][1], centers[a][2],
2124 centers[a + 1][0], centers[a + 1][1],
2125 centers[a + 1][2], 1, 1, 1);
2127 fprintf(file,
"ST(%f,%f,%f, %f,%f,%f, %f,%f,%f){%d,%d,%d};\n",
2128 centers[0][0], centers[0][1], centers[0][2],
2129 centers[centers.size() - 1][0],
2130 centers[centers.size() - 1][1],
2131 centers[centers.size() - 1][2], centers[1][0],
2132 centers[1][1], centers[1][2], 1, 1, 1);
2145 fprintf(file,
"};");
2161 for(
size_t i = 0; i < mesh->vertices.num; ++i) {
2165 return HXT_STATUS_OK;
2173 static void elementEstimate(p4est_iter_volume_info_t *info,
void *user_data)
2175 p4est_quadrant_t *q = info->quad;
2177 p4est_t *p4est = info->p4est;
2178 p4est_topidx_t which_tree = info->treeid;
2181 getCellCenter(p4est, which_tree, q, center);
2183 double octantVolume = data->
h * data->
h * data->
h;
2184 double tetVolume = data->
size * data->
size * data->
size * sqrt(2) / 12.0;
2186 *((
double *)user_data) += octantVolume / tetVolume;
2189 HXTStatus hxtOctreeElementEstimation(
Forest *forest,
double *elemEstimate)
2191 p4est_iterate(forest->p4est,
nullptr, (
void *)elemEstimate, elementEstimate,
2192 nullptr,
nullptr,
nullptr);
2193 return HXT_STATUS_OK;
2203 static void markIntersectingCells(p4est_iter_volume_info_t *info,
2208 if(forestOptions->
dim == 3) {
2209 double min[3], max[3];
2210 getCellBBox(info->p4est, info->treeid, info->quad, min, max);
2211 std::vector<uint64_t> candidates;
2212 forestOptions->
triRTree->
Search(min, max, rtreeCallback, &candidates);
2213 if(!candidates.empty()) {
2220 static void pushInterpolationData(p4est_iter_volume_info_t *info,
2225 p4est_quadrant_t *q = info->quad;
2226 p4est_t *p4est = info->p4est;
2227 p4est_topidx_t which_tree = info->treeid;
2229 std::vector<interpolation_data_t> *cellCenters =
2230 (std::vector<interpolation_data_t> *)user_data;
2233 getCellCenter(p4est, which_tree, q, center);
2236 (*cellCenters).push_back(intdata);
2242 static void addDistanceContribution(p4est_iter_volume_info_t *info,
2247 p4est_quadrant_t *q = info->quad;
2248 p4est_t *p4est = info->p4est;
2249 p4est_topidx_t which_tree = info->treeid;
2250 std::vector<interpolation_data_t> *cellCenters =
2251 (std::vector<interpolation_data_t> *)user_data;
2253 getCellCenter(p4est, which_tree, q, center);
2254 double dist, xc, yc, zc;
2255 printf(
"working at cell %d/%d\n", cellCounter++, intersections);
2257 for(
size_t i = 0; i < (*cellCenters).size(); ++i) {
2258 xc = (*cellCenters)[i].center[0];
2259 yc = (*cellCenters)[i].center[1];
2260 zc = (*cellCenters)[i].center[2];
2261 dist = sqrt((center[0] - xc) * (center[0] - xc) +
2262 (center[1] - yc) * (center[1] - yc) +
2263 (center[2] - zc) * (center[2] - zc));
2264 (*cellCenters)[i].denom += 1. / dist;
2265 (*cellCenters)[i].t1 += data->
t1 * (1. / dist);
2266 (*cellCenters)[i].t2 += data->
t2 * (1. / dist);
2271 static void assignDirections(p4est_iter_volume_info_t *info,
void *user_data)
2275 p4est_quadrant_t *q = info->quad;
2276 p4est_t *p4est = info->p4est;
2277 p4est_topidx_t which_tree = info->treeid;
2278 std::vector<interpolation_data_t> *cellCenters =
2279 (std::vector<interpolation_data_t> *)user_data;
2281 getCellCenter(p4est, which_tree, q, center);
2284 for(
size_t i = 0; i < (*cellCenters).size(); ++i) {
2285 xc = (*cellCenters)[i].center[0];
2286 yc = (*cellCenters)[i].center[1];
2287 zc = (*cellCenters)[i].center[2];
2288 if(fabs(center[0] - xc) < 1e-13 && fabs(center[1] - yc) < 1e-13 &&
2289 fabs(center[2] - zc) < 1e-13) {
2290 data->
t1 = (*cellCenters)[i].t1 * (1. / (*cellCenters)[i].denom);
2291 data->
t2 = (*cellCenters)[i].t2 * (1. / (*cellCenters)[i].denom);
2293 data->
n = data->
n.
unit();
2300 static void drawDirections(p4est_iter_volume_info_t *info,
void *user_data)
2304 p4est_quadrant_t *q = info->quad;
2305 p4est_t *p4est = info->p4est;
2306 p4est_topidx_t which_tree = info->treeid;
2309 getCellCenter(p4est, which_tree, q, center);
2311 double x = center[0];
2312 double y = center[1];
2313 double z = center[2];
2314 fprintf(forestOptions->
file3,
"SL(%f,%f,%f, %f,%f,%f){%f,%f};\n", x, y,
z,
2315 x + data->
t1[0], y + data->
t1[1],
z + data->
t1[2], 1.0, 1.0);
2316 fprintf(forestOptions->
file3,
"SL(%f,%f,%f, %f,%f,%f){%f,%f};\n", x, y,
z,
2317 x + data->
t2[0], y + data->
t2[1],
z + data->
t2[2], 1.0, 1.0);
2318 fprintf(forestOptions->
file3,
"SL(%f,%f,%f, %f,%f,%f){%f,%f};\n", x, y,
z,
2319 x + data->
n[0], y + data->
n[1],
z + data->
n[2], 1.0, 1.0);
2322 HXTStatus forestInterpolateDirections(
Forest *forest)
2325 p4est_iterate(forest->p4est,
nullptr,
nullptr, markIntersectingCells,
nullptr,
2328 std::vector<interpolation_data_t> cellCenters;
2330 p4est_iterate(forest->p4est,
nullptr, &cellCenters, pushInterpolationData,
2331 nullptr,
nullptr,
nullptr);
2332 p4est_iterate(forest->p4est,
nullptr, &cellCenters, addDistanceContribution,
2333 nullptr,
nullptr,
nullptr);
2334 p4est_iterate(forest->p4est,
nullptr, &cellCenters, assignDirections,
nullptr,
2339 return HXT_ERROR(HXT_STATUS_FILE_CANNOT_BE_OPENED);
2343 p4est_iterate(forest->p4est,
nullptr,
nullptr, drawDirections,
nullptr,
2349 return HXT_STATUS_OK;
2357 HXTStatus saveGlobalData(
Forest *forest,
const char *filename)
2359 FILE *
f = fopen(filename,
"w");
2360 if(
f ==
nullptr)
return HXT_ERROR(HXT_STATUS_FILE_CANNOT_BE_OPENED);
2364 Msg::Info(
"Saved global size field data to %s", filename);
2365 return HXT_STATUS_OK;
2368 static void exportToHexCallback(p4est_iter_volume_info_t *info,
void *user_data)
2370 p4est_quadrant_t *q = info->quad;
2372 p4est_t *p4est = info->p4est;
2373 p4est_topidx_t which_tree = info->treeid;
2375 FILE *
f = (FILE *)user_data;
2376 double center[3], x[8], y[8],
z[8];
2377 getCellCenter(p4est, which_tree, q, center);
2378 double h = data->
h / 2.0, s = data->
size,
epsilon = 1e-12;
2379 x[0] = x[3] = x[4] = x[7] = center[0] - h -
epsilon;
2380 x[1] = x[2] = x[5] = x[6] = center[0] + h +
epsilon;
2381 y[0] = y[1] = y[4] = y[5] = center[1] - h -
epsilon;
2382 y[2] = y[3] = y[6] = y[7] = center[1] + h +
epsilon;
2383 z[0] =
z[1] =
z[2] =
z[3] = center[2] - h -
epsilon;
2384 z[4] =
z[5] =
z[6] =
z[7] = center[2] + h +
epsilon;
2387 "SH(%f,%f,%f, %f,%f,%f, %f,%f,%f, %f,%f,%f,%f,%f,%f, %f,%f,%f, "
2388 "%f,%f,%f, %f,%f,%f){%f,%f,%f,%f,%f,%f,%f,%f};\n",
2389 x[0], y[0],
z[0], x[1], y[1],
z[1], x[2], y[2],
z[2], x[3], y[3],
2390 z[3], x[4], y[4],
z[4], x[5], y[5],
z[5], x[6], y[6],
z[6], x[7],
2391 y[7],
z[7], s, s, s, s, s, s, s, s);
2401 static void exportToQuadCallback(p4est_iter_volume_info_t *info,
2404 p4est_quadrant_t *q = info->quad;
2407 p4est_t *p4est = info->p4est;
2408 p4est_topidx_t which_tree = info->treeid;
2410 FILE *
f = (FILE *)user_data;
2412 double center[3], x[8], y[8],
z[8];
2413 getCellCenter(p4est, which_tree, q, center);
2415 double h = data->
h / 2.0, s = data->
size,
epsilon = 1e-12;
2416 x[0] = x[3] = center[0] - h -
epsilon;
2417 x[1] = x[2] = center[0] + h +
epsilon;
2418 y[0] = y[1] = center[1] - h -
epsilon;
2419 y[2] = y[3] = center[1] + h +
epsilon;
2423 fprintf(
f,
"SQ(%f,%f,%f, %f,%f,%f, %f,%f,%f, %f,%f,%f){%f,%f,%f,%f};\n", x[0],
2424 y[0],
z[0], x[1], y[1],
z[1], x[2], y[2],
z[2], x[3], y[3],
z[3], s,
2428 HXTStatus forestExport(
Forest *forest,
const char *forestFile)
2430 FILE *
f = fopen(forestFile,
"w");
2431 if(
f ==
nullptr)
return HXT_ERROR(HXT_STATUS_FILE_CANNOT_BE_OPENED);
2433 fprintf(
f,
"View \"sizeField\" {\n");
2435 p4est_iterate(forest->p4est,
nullptr, (
void *)
f, exportToHexCallback,
2436 nullptr,
nullptr,
nullptr);
2439 p4est_iterate(forest->p4est,
nullptr, (
void *)
f, exportToQuadCallback,
2440 nullptr,
nullptr,
nullptr);
2444 return HXT_STATUS_OK;
2447 HXTStatus forestSave(
Forest *forest,
const char *forestFile,
2448 const char *dataFile)
2450 HXT_CHECK(saveGlobalData(forest, dataFile));
2451 p4est_save_ext(forestFile, forest->p4est,
true,
false);
2452 return HXT_STATUS_OK;
2466 #if defined(HAVE_HXT) && defined(HAVE_P4EST)
2467 HXTStatus s = forestSearchOne(forest, X, Y, Z, &val,
true);
2468 if(s == HXT_STATUS_OK) {
return val; }
2470 Msg::Error(
"Cannot find point %g %g %g in the octree", X, Y, Z);
2472 Msg::Error(
"Gmsh has to be compiled with HXT and P4EST for using "
2473 "automaticMeshSizeField");
2481 #if defined(HAVE_HXT) && defined(HAVE_P4EST)
2482 HXTStatus s = forestSearchOneAniso(forest, X, Y, Z, m,
false);
2485 if(s != HXT_STATUS_OK)
2486 Msg::Error(
"Cannot find point %g %g %g in the octree", X, Y, Z);
2488 Msg::Error(
"Gmsh has to be compiled with HXT and P4EST for using "
2489 "automaticMeshSizeField");
2495 #if defined(HAVE_HXT) && defined(HAVE_P4EST)
2496 if(forest) forestDelete(&forest);
2497 if(forestOptions) forestOptionsDelete(&forestOptions);
2501 #if defined(HAVE_HXT) && defined(HAVE_P4EST)
2502 HXTStatus automaticMeshSizeField::updateHXT()
2506 if(forestOptions) HXT_CHECK(forestOptionsDelete(&forestOptions));
2507 if(forest) HXT_CHECK(forestDelete(&forest));
2514 HXT_CHECK(forestOptionsCreate(&forestOptions));
2516 std::string root =
_forestFile.substr(0, lastindex);
2517 std::string forestFile = root +
".p4est";
2518 std::string dataFile = root +
".data";
2520 forestLoad(&forest, forestFile.c_str(), dataFile.c_str(), forestOptions));
2526 HXT_CHECK(forestOptionsCreate(&forestOptions));
2535 Msg::Info(
"Layers per gap = %d : not detecting features.\n",
2541 double bbox_vertices[6];
2545 double *nodalCurvature;
2556 HXT_CHECK(hxtMalloc(&nodalCurvature, 6 * numVertices *
sizeof(
double)));
2557 std::vector<double> nodeNormals;
2558 for(
size_t i = 0; i < 6 * numVertices; ++i) { nodalCurvature[i] = NAN; }
2562 std::vector<GFace *>
faces;
2563 std::vector<GRegion *> regions;
2566 regions.push_back(*it);
2568 if(!regions.empty()) {
2569 HXT_CHECK(getAllFacesOfAllRegions(regions,
nullptr,
faces));
2572 Msg::Info(
"No volume in the model : looping over faces instead.");
2575 faces.push_back(*it);
2579 if(regions.empty()) {
2580 Msg::Error(
"Erreur : Pas de volume dans le modèle.");
2584 HXT_CHECK(hxtMeshCreate(&mesh));
2585 std::map<MVertex *, uint32_t> v2c;
2586 std::vector<MVertex *> c2v;
2587 Gmsh2Hxt(
faces, mesh, v2c, c2v);
2610 if(mesh->vertices.num == 0) {
2612 HXT_CHECK(hxtMeshDelete(&mesh));
2621 std::vector<HXTMesh *> faceMeshes;
2622 for(
size_t i = 0; i <
faces.size(); ++i) {
2624 HXT_CHECK(hxtMeshCreate(&meshFace));
2625 std::vector<GFace *> oneFace;
2626 oneFace.push_back(
faces[i]);
2627 std::map<MVertex *, uint32_t> v2cLoc;
2628 std::vector<MVertex *> c2vLoc;
2629 Gmsh2HxtLocal(oneFace, meshFace, v2cLoc, c2vLoc);
2630 faceMeshes.push_back(meshFace);
2633 std::map<MVertex *, uint32_t> v2c2;
2634 std::vector<MVertex *> c2v2;
2635 Gmsh2HxtGlobal(
faces,
nullptr, v2c2, c2v2);
2637 size_t nVertices = 0;
2639 assert(
faces.size() == faceMeshes.size());
2644 HXTMesh *meshFace = faceMeshes[counter++];
2646 if(meshFace ==
nullptr) {
Msg::Error(
"meshFace == NULL"); }
2649 std::map<MVertex *, int> nodeIndex;
2650 std::vector<SPoint3> nodes;
2651 std::vector<int> tris;
2652 std::vector<std::pair<SVector3, SVector3> > curv;
2653 for(std::size_t i = 0; i < gf->
triangles.size(); i++) {
2655 for(
int j = 0; j < 3; j++) {
2657 if(nodeIndex.find(v) == nodeIndex.end()) {
2658 int idx = nodes.size();
2660 nodes.push_back(v->
point());
2661 tris.push_back(idx);
2664 tris.push_back(nodeIndex[v]);
2669 for(
size_t i = 0; i < meshFace->vertices.num; ++i) {
2670 nodes[i] =
SPoint3(meshFace->vertices.coord[(
size_t)4 * i + 0],
2671 meshFace->vertices.coord[(
size_t)4 * i + 1],
2672 meshFace->vertices.coord[(
size_t)4 * i + 2]);
2676 for(
size_t i = 0; i < meshFace->triangles.num; ++i) {
2677 tris[3 * i + 0] = meshFace->triangles.node[3 * i + 0];
2678 tris[3 * i + 1] = meshFace->triangles.node[3 * i + 1];
2679 tris[3 * i + 2] = meshFace->triangles.node[3 * i + 2];
2683 Msg::Info(
"Skipping curvature computation on face %d with 0 element",
2692 for(uint64_t i = 0; i < meshFace->vertices.num; ++i) {
2693 uint64_t nodeGlobal = v2c[c2v2[nVertices + i]];
2698 double x1, y1, z1, x2, y2, z2;
2699 x1 = meshFace->vertices.coord[(size_t)4 * i + 0];
2700 y1 = meshFace->vertices.coord[(size_t)4 * i + 1];
2701 z1 = meshFace->vertices.coord[(size_t)4 * i + 2];
2702 x2 = mesh->vertices.coord[(size_t)4 * nodeGlobal + 0];
2703 y2 = mesh->vertices.coord[(size_t)4 * nodeGlobal + 1];
2704 z2 = mesh->vertices.coord[(size_t)4 * nodeGlobal + 2];
2705 if(!isPoint(x1, y1, z1, x2, y2, z2, 1e-12)) {
2706 printf(
"Mismatch : (%10.12e,%10.12e,%10.12e) - "
2707 "(%10.12e,%10.12e,%10.12e)\n",
2708 x1, y1, z1, x2, y2, z2);
2710 assert(isPoint(x1, y1, z1, x2, y2, z2, 1e-15));
2713 nodalCurvature[6 * nodeGlobal + 0] = curv[i].first[0];
2714 nodalCurvature[6 * nodeGlobal + 1] = curv[i].first[1];
2715 nodalCurvature[6 * nodeGlobal + 2] = curv[i].first[2];
2716 nodalCurvature[6 * nodeGlobal + 3] = curv[i].second[0];
2717 nodalCurvature[6 * nodeGlobal + 4] = curv[i].second[1];
2718 nodalCurvature[6 * nodeGlobal + 5] = curv[i].second[2];
2721 nVertices += meshFace->vertices.num;
2727 writeNodalCurvature(nodalCurvature, mesh->vertices.num,
2728 "nodalCurvature.txt");
2731 HXTDelaunayOptions delaunayOptions = {
nullptr,
nullptr, 0, 0, 0, 2, 1, 0};
2732 HXT_CHECK(hxtEmptyMesh(mesh, &delaunayOptions));
2735 std::vector<int> tris(3 * mesh->triangles.num, 0);
2736 for(std::size_t i = 0; i < mesh->triangles.num; ++i) {
2737 tris[3 * i + 0] = mesh->triangles.node[3 * i + 0];
2738 tris[3 * i + 1] = mesh->triangles.node[3 * i + 1];
2739 tris[3 * i + 2] = mesh->triangles.node[3 * i + 2];
2742 std::vector<SPoint3> nodes(mesh->vertices.num);
2743 for(
size_t i = 0; i < mesh->vertices.num; ++i) {
2744 nodes[i] =
SPoint3(mesh->vertices.coord[(
size_t)4 * i + 0],
2745 mesh->vertices.coord[(
size_t)4 * i + 1],
2746 mesh->vertices.coord[(
size_t)4 * i + 2]);
2749 std::vector<std::pair<SVector3, SVector3> > curv;
2750 nodeNormals.reserve(3 * mesh->vertices.num);
2756 HXTBbox bbox_triangle;
2757 for(uint64_t i = 0; i < mesh->triangles.num; ++i) {
2758 hxtBboxInit(&bbox_triangle);
2759 for(uint64_t j = 0; j < 3; ++j) {
2761 uint32_t node = mesh->triangles.node[3 * i + j];
2762 for(uint32_t k = 0; k < 3; ++k) {
2763 coord[k] = mesh->vertices.coord[(size_t)4 * node + k];
2765 hxtBboxAddOne(&bbox_triangle, coord);
2767 SBoundingBox3d cube_bbox(bbox_triangle.min[0], bbox_triangle.min[1],
2768 bbox_triangle.min[2], bbox_triangle.max[0],
2769 bbox_triangle.max[1], bbox_triangle.max[2]);
2771 triRTree.
Insert((
double *)(cube_bbox.min()),
2772 (
double *)(cube_bbox.max()), i);
2777 hxtBboxInit(&bbox_mesh);
2778 hxtBboxAdd(&bbox_mesh, mesh->vertices.coord, mesh->vertices.num);
2779 for(
int i = 0; i < 3; ++i) {
2780 bbox_vertices[i] = bbox_mesh.min[i];
2781 bbox_vertices[i + 3] = bbox_mesh.max[i];
2785 bool exportRTree =
false;
2788 FILE *
f = fopen(
"rtree.pos",
"w");
2789 fprintf(
f,
"View \"sizeField\" {\n");
2792 double x[8], y[8],
z[8];
2796 int value = triRTree.
GetAt(it);
2797 double boundsMin[3] = {0, 0, 0};
2798 double boundsMax[3] = {0, 0, 0};
2799 it.GetBounds(boundsMin, boundsMax);
2800 std::cout <<
"it[" << itIndex++ <<
"] " << value <<
" = ("
2801 << boundsMin[0] <<
"," << boundsMin[1] <<
","
2802 << boundsMin[2] <<
"," << boundsMax[0] <<
","
2803 << boundsMax[1] <<
"," << boundsMax[2] <<
")\n";
2804 x[0] = x[3] = x[4] = x[7] = boundsMin[0];
2805 x[1] = x[2] = x[5] = x[6] = boundsMax[0];
2806 y[0] = y[1] = y[4] = y[5] = boundsMin[1];
2807 y[2] = y[3] = y[6] = y[7] = boundsMax[1];
2808 z[0] =
z[1] =
z[2] =
z[3] = boundsMin[2];
2809 z[4] =
z[5] =
z[6] =
z[7] = boundsMax[2];
2811 "SH(%f,%f,%f, %f,%f,%f, %f,%f,%f, %f,%f,%f, %f,%f,%f, "
2812 "%f,%f,%f, %f,%f,%f, %f,%f,%f){%f,%f,%f,%f,%f,%f,%f,%f};\n",
2813 x[0], y[0],
z[0], x[1], y[1],
z[1], x[2], y[2],
z[2], x[3],
2814 y[3],
z[3], x[4], y[4],
z[4], x[5], y[5],
z[5], x[6], y[6],
2815 z[6], x[7], y[7],
z[7], s, s, s, s, s, s, s, s);
2818 x[0] = x[3] = x[4] = x[7] = bbox_mesh.min[0];
2819 x[1] = x[2] = x[5] = x[6] = bbox_mesh.max[0];
2820 y[0] = y[1] = y[4] = y[5] = bbox_mesh.min[1];
2821 y[2] = y[3] = y[6] = y[7] = bbox_mesh.max[1];
2822 z[0] =
z[1] =
z[2] =
z[3] = bbox_mesh.min[2];
2823 z[4] =
z[5] =
z[6] =
z[7] = bbox_mesh.max[2];
2825 "SH(%f,%f,%f, %f,%f,%f, %f,%f,%f, %f,%f,%f, %f,%f,%f, "
2826 "%f,%f,%f, %f,%f,%f, %f,%f,%f){%f,%f,%f,%f,%f,%f,%f,%f};\n",
2827 x[0], y[0],
z[0], x[1], y[1],
z[1], x[2], y[2],
z[2], x[3],
2828 y[3],
z[3], x[4], y[4],
z[4], x[5], y[5],
z[5], x[6], y[6],
2829 z[6], x[7], y[7],
z[7], s, s, s, s, s, s, s, s);
2836 Msg::Error(
"2D size field is not yet operational");
2839 for(
int i = 0; i < 3; ++i) {
2840 bbox_vertices[i] = bbox.
min()[i];
2841 bbox_vertices[i + 3] = bbox.
max()[i];
2863 for(
int i = 0; i < 3; ++i) {
2864 L = fmax(L, bbox_vertices[i + 3] - bbox_vertices[i]);
2874 std::vector<double> sizeAtVertices(mesh->vertices.num, DBL_MAX);
2876 forestOptions->
dim = dim;
2883 forestOptions->
bbox = bbox_vertices;
2888 forestOptions->
triRTree = (dim == 3) ? &triRTree :
nullptr;
2889 forestOptions->mesh = mesh;
2891 HXT_CHECK(forestCreate(0,
nullptr, &forest,
nullptr, forestOptions));
2896 HXT_CHECK(featureSize(forest));
2901 HXT_CHECK(forestRefine(forest));
2905 Msg::Info(
"Smoothing size gradient...");
2906 HXT_CHECK(forestSizeSmoothing(forest));
2909 double elemEstimation;
2910 HXT_CHECK(hxtOctreeElementEstimation(forest, &elemEstimation));
2911 Msg::Info(
"Estimated number of tetrahedra in the bounding box : %ld",
2912 (uint64_t)ceil(elemEstimation));
2915 HXT_CHECK(forestRefine(forest));
2917 Msg::Info(
"Smoothing size gradient...");
2918 HXT_CHECK(forestSizeSmoothing(forest));
2927 Msg::Info(
"Saving size field in %s", forestFile.c_str());
2928 HXT_CHECK(forestSave(forest, forestFile.c_str(), dataFile.c_str()));
2934 HXT_CHECK(forestExport(forest, forestFile.c_str()));
2938 if(nodalCurvature) HXT_CHECK(hxtFree(&nodalCurvature));
2940 HXT_CHECK(hxtMeshDelete(&mesh));
2944 return HXT_STATUS_OK;
2951 #if defined(HAVE_HXT) && defined(HAVE_P4EST)
2952 HXTStatus s = updateHXT();
2953 if(s != HXT_STATUS_OK)
2954 Msg::Error(
"Something went wrong when computing the octree");
2957 "Gmsh has to be compiled with HXT and P4EST to use automaticMeshSizeField");