From 0e519f2d21d2a6be8122e03d38c532934937a2dc Mon Sep 17 00:00:00 2001
From: jf remacle <jean-francois.remacle@uclouvain.be>
Date: Mon, 19 Nov 2018 16:08:09 +0100
Subject: [PATCH] mesh size field in hxtMesh3D

---
 Mesh/meshGRegionHxt.cpp       |  9 ++++-
 contrib/hxt/hxt_mesh3d.c      | 72 +++++++++++++++++++++++++----------
 contrib/hxt/hxt_mesh3d.h      | 12 +++++-
 contrib/hxt/hxt_mesh3d_main.c | 22 +++++------
 contrib/hxt/hxt_mesh3d_main.h |  4 +-
 5 files changed, 83 insertions(+), 36 deletions(-)

diff --git a/Mesh/meshGRegionHxt.cpp b/Mesh/meshGRegionHxt.cpp
index 6409664fae..51be474549 100644
--- a/Mesh/meshGRegionHxt.cpp
+++ b/Mesh/meshGRegionHxt.cpp
@@ -15,6 +15,7 @@
 #include "MTriangle.h"
 #include "MLine.h"
 #include "GmshMessage.h"
+#include "BackgroundMeshTools.h"
 
 #ifdef HAVE_HXT
 extern "C" {
@@ -29,6 +30,11 @@ HXTStatus hxtGmshMsgCallback(HXTMessage* msg){
   return HXT_STATUS_OK;
 }
 
+static double hxtMeshSizeGmshCallBack (double x, double y, double z, void *userData) { 
+  GRegion *gr = (GRegion*)userData;
+  double lc2 = BGM_MeshSize(gr, 0, 0, x,y,z);
+}
+
 
 static HXTStatus getAllFacesOfAllRegions (std::vector<GRegion *> &regions, HXTMesh *m, std::vector<GFace *> &allFaces){
   std::set<GFace *, GEntityLessThan> allFacesSet;
@@ -334,7 +340,8 @@ static HXTStatus _meshGRegionHxt(std::vector<GRegion *> &regions)
 			 refine,
                          optimize,
 			 threshold,
-			 hxt_boundary_recovery));  
+			 hxt_boundary_recovery,
+			 hxtMeshSizeGmshCallBack, regions[0]));  
 
   
   //  HXT_CHECK(hxtMeshWriteGmsh(mesh, "hxt.msh"));
diff --git a/contrib/hxt/hxt_mesh3d.c b/contrib/hxt/hxt_mesh3d.c
index b1600ec122..dc446f92a2 100644
--- a/contrib/hxt/hxt_mesh3d.c
+++ b/contrib/hxt/hxt_mesh3d.c
@@ -15,6 +15,20 @@
 // }
 // #endif
 
+HXTStatus hxtCreateNodalSizeFromFunction(HXTMesh* mesh, HXTDelaunayOptions* delOptions,
+                                         double (*mesh_size)(double x, double y, double z, void* userData),
+                                         void* userData)
+{
+  HXT_CHECK(hxtAlignedMalloc(&delOptions->nodalSizes,mesh->vertices.num*sizeof(double)));
+
+  #pragma omp parallel for
+  for (uint32_t i=0; i<mesh->vertices.num; i++) {
+    double* coord = &mesh->vertices.coord[4*i];
+    delOptions->nodalSizes[i] = mesh_size(coord[0], coord[1], coord[2], userData);
+  }
+
+  return HXT_STATUS_OK;
+}
 
 
 HXTStatus hxtCreateNodalsizeFromTrianglesAndLines(HXTMesh* mesh, HXTDelaunayOptions* delOptions)
@@ -247,7 +261,9 @@ double hxtTetCircumcenter(double a[3], double b[3], double c[3], double d[3],
 }
 
 
-HXTStatus hxtRefineTetrahedraOneStep(HXTMesh* mesh, HXTDelaunayOptions* delOptions, HXTMeshSize* sizeField, int *nbAdd, int iter)
+static HXTStatus hxtRefineTetrahedraOneStep(HXTMesh* mesh, HXTDelaunayOptions* delOptions,
+                                            double (*mesh_size)(double x, double y, double z, void* userData),
+                                            void* userData , int *nbAdd, int iter)
 {
   double *newVertices;
   uint32_t *numCreated;
@@ -280,33 +296,46 @@ HXTStatus hxtRefineTetrahedraOneStep(HXTMesh* mesh, HXTDelaunayOptions* delOptio
         double circumradius2 = (a[0]-circumcenter[0])*(a[0]-circumcenter[0])+
                                (a[1]-circumcenter[1])*(a[1]-circumcenter[1])+
                                (a[2]-circumcenter[2])*(a[2]-circumcenter[2]);
+
+        setProcessedFlag(mesh, i); // we do not need to refine that tetrahedra anymore
+
         // all new edges will have a length equal to circumradius2
         double meshSize;
         //        HXTStatus status = hxtMeshSizeEvaluate ( sizeField, circumcenter, &meshSize);
 
-        double SIZES[4];
-        double AVG = 0;
-        int NN = 0;
-        for (int j=0;j<4;j++){
-          SIZES[j] = delOptions->nodalSizes[mesh->tetrahedra.node[4*i+j]];
-          if (SIZES[j] != DBL_MAX){
-            NN++;
-            AVG += SIZES[j];
-          }
+        if(u <= 0 || v <= 0 || w <= 0 || 1.-u-v-w <= 0)
+          continue;
+        
+        if(mesh_size!=NULL) {
+          meshSize = mesh_size(circumcenter[0], circumcenter[1], circumcenter[2], userData);
         }
-        if (NN != 4){
-          AVG /= NN;
+        else { // we suppose delOptions->nodalSize!=NULL
+          double SIZES[4];
+          double AVG = 0;
+          int NN = 0;
           for (int j=0;j<4;j++){
-            if (SIZES[j] == DBL_MAX){
-              // delOptions->nodalSizes[mesh->tetrahedra.node[4*i+j]] = AVG;
-              SIZES[j] = AVG;
+            SIZES[j] = delOptions->nodalSizes[mesh->tetrahedra.node[4*i+j]];
+            if (SIZES[j] != DBL_MAX){
+              NN++;
+              AVG += SIZES[j];
+            }
+          }
+          if (NN != 4){
+            AVG /= NN;
+            for (int j=0;j<4;j++){
+              if (SIZES[j] == DBL_MAX){
+                // delOptions->nodalSizes[mesh->tetrahedra.node[4*i+j]] = AVG;
+                SIZES[j] = AVG;
+              }
             }
           }
+
+          meshSize = SIZES[0] * (1-u-v-w) + SIZES[1] * u + SIZES[2] * v + SIZES[3] * w;
         }
   
-        meshSize = SIZES[0] * (1-u-v-w) + SIZES[1] * u + SIZES[2] * v + SIZES[3] * w;
+        
   
-        if (u > 0 && v > 0 && w > 0 && 1.-u-v-w > 0 && meshSize * meshSize * .49 < circumradius2) {
+        if (meshSize * meshSize /* .49*/ < circumradius2) {
           //    printf("%llu %g\n",i,sqrt(circumradius2),meshSize);
           newVertices[(size_t) 4*i  ] = circumcenter[0];
           newVertices[(size_t) 4*i+1] = circumcenter[1];
@@ -314,8 +343,6 @@ HXTStatus hxtRefineTetrahedraOneStep(HXTMesh* mesh, HXTDelaunayOptions* delOptio
           newVertices[(size_t) 4*i+3] = meshSize;
           localAdd++;
         }
-
-        setProcessedFlag(mesh, i); // we do not need to refine that tetrahedra anymore
       }
     }
 
@@ -375,11 +402,14 @@ HXTStatus hxtRefineTetrahedraOneStep(HXTMesh* mesh, HXTDelaunayOptions* delOptio
   return HXT_STATUS_OK;
 }
 
-HXTStatus hxtRefineTetrahedra(HXTMesh* mesh, HXTDelaunayOptions* delOptions, HXTMeshSize* sizeField) {
+HXTStatus hxtRefineTetrahedra(HXTMesh* mesh,
+                              HXTDelaunayOptions* delOptions,
+                              double (*mesh_size)(double x, double y, double z, void* userData),
+                              void* userData) {
   int iter = 0;
   while(iter++ < 40){
     int nbAdd=0;
-    HXT_CHECK(hxtRefineTetrahedraOneStep(mesh, delOptions, sizeField, &nbAdd, iter));
+    HXT_CHECK(hxtRefineTetrahedraOneStep(mesh, delOptions, mesh_size, userData, &nbAdd, iter));
     //    uint32_t nb;
     //    HXT_CHECK(hxtColorMesh(mesh,&nb));
     if (nbAdd == 0) break;
diff --git a/contrib/hxt/hxt_mesh3d.h b/contrib/hxt/hxt_mesh3d.h
index 61d5104a56..23afb959df 100644
--- a/contrib/hxt/hxt_mesh3d.h
+++ b/contrib/hxt/hxt_mesh3d.h
@@ -9,12 +9,20 @@ HXTStatus hxtCreateFaceSearchStructure(HXTMesh* mesh, uint32_t **pfaces);
 //// creates a mesh with all points of the surface mesh
 HXTStatus hxtEmptyMesh(HXTMesh* mesh, HXTDelaunayOptions* delOptions);
 
-/// Compute sizes at vertices of the mesh from existing edges of the tetrahera
+/// Compute sizes at vertices of the mesh from a mesh_size function
+HXTStatus hxtCreateNodalSizeFromFunction(HXTMesh* mesh, HXTDelaunayOptions* delOptions,
+                                         double (*mesh_size)(double x, double y, double z, void* userData),
+                                         void* userData);
+
+/// Compute sizes at vertices of the mesh from existing edges
 HXTStatus hxtCreateNodalsizeFromTrianglesAndLines(HXTMesh* mesh, HXTDelaunayOptions* delOptions);
 HXTStatus hxtCreateNodalsizeFromMesh(HXTMesh* mesh, HXTDelaunayOptions* delOptions);
 HXTStatus hxtDestroyNodalsize(HXTDelaunayOptions* delOptions);
 
 /// Add points at tets circumcenter in order to fullfill a mesh size constraint 
-HXTStatus hxtRefineTetrahedra(HXTMesh* mesh, HXTDelaunayOptions* delOptions, HXTMeshSize* meshsize);
+HXTStatus hxtRefineTetrahedra(HXTMesh* mesh,
+                              HXTDelaunayOptions* delOptions,
+                              double (*mesh_size)(double x, double y, double z, void* userData),
+                              void* userData);
 
 #endif
diff --git a/contrib/hxt/hxt_mesh3d_main.c b/contrib/hxt/hxt_mesh3d_main.c
index 52011b0012..a5f3df74ff 100644
--- a/contrib/hxt/hxt_mesh3d_main.c
+++ b/contrib/hxt/hxt_mesh3d_main.c
@@ -17,7 +17,9 @@ HXTStatus hxtTetMesh3d(HXTMesh* mesh,
                       int refine,
                       int optimize,
                       double qualityThreshold,
-                      HXTStatus (*bnd_recovery)(HXTMesh* mesh)) {
+                      HXTStatus (*bnd_recovery)(HXTMesh* mesh),
+                      double (*mesh_size)(double x, double y, double z, void* userData),
+                      void* userData) {
 
   if(defaulThreads>0) {
     omp_set_num_threads(defaulThreads);
@@ -100,7 +102,7 @@ HXTStatus hxtTetMesh3d(HXTMesh* mesh,
     HXT_CHECK( hxtConstrainLinesNotInTriangles(mesh, lines2TetMap, lines2TriMap) );
 
   HXT_CHECK( hxtColorMesh(mesh, &nbColors) );
- 
+
   HXT_CHECK( hxtMapColorsToBrep(mesh, nbColors, tri2TetMap) );
 
   HXT_CHECK( hxtAlignedFree(&tri2TetMap) );
@@ -111,20 +113,18 @@ HXTStatus hxtTetMesh3d(HXTMesh* mesh,
 
   if(refine){
     // HXT_CHECK(hxtComputeMeshSizeFromMesh(mesh, &delOptions));
-    HXT_CHECK(hxtCreateNodalsizeFromTrianglesAndLines(mesh, &delOptions));
-    
+    if(mesh_size==NULL)
+    	HXT_CHECK(hxtCreateNodalsizeFromTrianglesAndLines(mesh, &delOptions));
+    else
+    	HXT_CHECK(hxtCreateNodalSizeFromFunction(mesh, &delOptions, mesh_size, userData) );
+
     if(nbColors!=mesh->brep.numVolumes) {
       HXT_CHECK( setFlagsToProcessOnlyVolumesInBrep(mesh) );
     }
 
-    HXTMeshSize *meshSize = NULL;
-    // HXT_CHECK(hxtMeshSizeCreate (context,&meshSize));
-    // HXT_CHECK(hxtMeshSizeCompute (meshSize, bbox.min, bbox.max, mySize, NULL));
-    //    printf("time from empty mesh to first insertion: %f second\n", omp_get_wtime() - time);
-    HXT_CHECK(hxtRefineTetrahedra(mesh, &delOptions, meshSize));
-    // HXT_CHECK(hxtMeshSizeDelete (&meshSize));
+    HXT_CHECK(hxtRefineTetrahedra(mesh, &delOptions, mesh_size, userData));
+
     HXT_CHECK( hxtDestroyNodalsize(&delOptions) );
-    // #endif
   }
 
   t[5] = omp_get_wtime();
diff --git a/contrib/hxt/hxt_mesh3d_main.h b/contrib/hxt/hxt_mesh3d_main.h
index 320112d674..f54e9001c6 100644
--- a/contrib/hxt/hxt_mesh3d_main.h
+++ b/contrib/hxt/hxt_mesh3d_main.h
@@ -13,6 +13,8 @@ HXTStatus hxtTetMesh3d(HXTMesh* mesh,
                       int refine,
                       int optimize,
                       double qualityThreshold,
-                      HXTStatus (*bnd_recovery)(HXTMesh* mesh));
+                      HXTStatus (*bnd_recovery)(HXTMesh* mesh),
+                      double (*mesh_size)(double x, double y, double z, void* userData),
+                      void* userData);
 
 #endif
\ No newline at end of file
-- 
GitLab