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");