From 52ecae224ce07c05015238dbf14c5f482861526b Mon Sep 17 00:00:00 2001
From: Thomas Toulorge <thomas.toulorge@mines-paristech.fr>
Date: Sat, 4 May 2013 19:19:35 +0000
Subject: [PATCH] Changed "most aniso" mesh metric intersection

---
 Geo/STensor3.cpp    | 62 ++++++++++++++++++++++++++++++++++++++++++---
 Geo/STensor3.h      |  1 +
 Mesh/meshMetric.cpp | 43 +++++++++++++++++++++----------
 3 files changed, 89 insertions(+), 17 deletions(-)

diff --git a/Geo/STensor3.cpp b/Geo/STensor3.cpp
index 4a61ce2f6b..a282ad4f04 100644
--- a/Geo/STensor3.cpp
+++ b/Geo/STensor3.cpp
@@ -64,22 +64,76 @@ SMetric3 intersection_conserveM1 (const SMetric3 &m1, const SMetric3 &m2)
   return iv;
 }
 
+namespace {
+
+double anisoRatio2D (double v0x, double v0y, double v0z,
+                     double v1x, double v1y, double v1z,
+                     double v2x, double v2y, double v2z,
+                     double s0, double s1, double s2) {
+
+  static const double eps = 1.e-8;
+
+  double ratio;
+  if (v0x*v0x+v0y*v0y+(v0z-1.)*(v0z-1.) < eps)        // If 1st eigenvect corresponds to z dir. ...
+    ratio = std::min(fabs(s1/s2),fabs(s2/s1));        // ... consider ratio of 2nd and 3rd eigenval.
+  else if (v1x*v1x+v1y*v1y+(v1z-1.)*(v1z-1.) < eps)   // If 2nd eigenvect corresponds to z dir. ...
+    ratio = std::min(fabs(s0/s2),fabs(s2/s0));        // ... consider ratio of 1st and 3rd eigenval.
+  else if (v2x*v2x+v2y*v2y+(v2z-1.)*(v2z-1.) < eps)   // If 3rd eigenvect corresponds to z dir. ...
+    ratio = std::min(fabs(s0/s1),fabs(s1/s0));        // ... consider ratio of 1st and 2nd eigenval.
+  else {
+    printf("Error in anisoRatio2D: z direction not found!\n");
+    ratio = 0.;
+  }
+
+  return ratio;
+
+}
+
+}
+
 // preserve orientation of the most anisotropic metric !!!
 SMetric3 intersection_conserve_mostaniso (const SMetric3 &m1, const SMetric3 &m2)
 {
   fullMatrix<double> V1(3,3);
   fullVector<double> S1(3);
   m1.eig(V1,S1,true);
-  double lambda1_min = std::min(std::min(fabs(S1(0)),fabs(S1(1))),fabs(S1(2)));
+  double ratio1 = fabs(S1(0)/S1(2));  // Minimum ratio because we take sorted eigenvalues
   fullMatrix<double> V2(3,3);
   fullVector<double> S2(3);
   m2.eig(V2,S2,true);
-  double lambda2_min = std::min(std::min(fabs(S2(0)),fabs(S2(1))),fabs(S2(2)));
-  
-  if (lambda1_min < lambda2_min)
+  double ratio2 = fabs(S2(0)/S2(2));  // Minimum ratio because we take sorted eigenvalues
+
+  if (ratio1 < ratio2)
+    return intersection_conserveM1(m1, m2);
+  else
+    return intersection_conserveM1(m2, m1);
+}
+
+// preserve orientation of the most anisotropic metric in 2D!!!
+SMetric3 intersection_conserve_mostaniso_2d (const SMetric3 &m1, const SMetric3 &m2)
+{
+
+  fullMatrix<double> V1(3,3);
+  fullVector<double> S1(3);
+  m1.eig(V1,S1,false);
+  double ratio1 = anisoRatio2D(V1(0,0),V1(1,0),V1(2,0),
+                               V1(0,1),V1(1,1),V1(2,1),
+                               V1(0,2),V1(1,2),V1(2,2),
+                               S1(0),S1(1),S1(2));
+
+  fullMatrix<double> V2(3,3);
+  fullVector<double> S2(3);
+  m2.eig(V2,S2,false);
+  double ratio2 = anisoRatio2D(V2(0,0),V2(1,0),V2(2,0),
+                               V2(0,1),V2(1,1),V2(2,1),
+                               V2(0,2),V2(1,2),V2(2,2),
+                               S2(0),S2(1),S2(2));
+
+  if (ratio1 < ratio2)
     return intersection_conserveM1(m1, m2);
   else
     return intersection_conserveM1(m2, m1);
+
 }
 
 // (1-t) * m1 + t * m2
diff --git a/Geo/STensor3.h b/Geo/STensor3.h
index d54a2b8c95..cb427ab811 100644
--- a/Geo/STensor3.h
+++ b/Geo/STensor3.h
@@ -169,6 +169,7 @@ SMetric3 intersection_conserveM1 (const SMetric3 &m1,
 
 // preserve orientation of the most anisotropic metric
 SMetric3 intersection_conserve_mostaniso (const SMetric3 &m1, const SMetric3 &m2);
+SMetric3 intersection_conserve_mostaniso_2d (const SMetric3 &m1, const SMetric3 &m2);
 // compute the largest inscribed ellipsoid...
 SMetric3 intersection (const SMetric3 &m1,
                        const SMetric3 &m2);
diff --git a/Mesh/meshMetric.cpp b/Mesh/meshMetric.cpp
index f07ac65360..4a41e97ec2 100644
--- a/Mesh/meshMetric.cpp
+++ b/Mesh/meshMetric.cpp
@@ -95,7 +95,9 @@ void meshMetric::updateMetrics()
 
     if (setOfMetrics.size() > 1)
       for (unsigned int i=1;i<setOfMetrics.size();i++){
-        _nodalMetrics[ver] = intersection_conserve_mostaniso(_nodalMetrics[ver],setOfMetrics[i][ver]);
+        _nodalMetrics[ver] = (_dim == 3) ?
+          intersection_conserve_mostaniso(_nodalMetrics[ver],setOfMetrics[i][ver]) :
+          intersection_conserve_mostaniso_2d(_nodalMetrics[ver],setOfMetrics[i][ver]);
         _nodalSizes[ver] = std::min(_nodalSizes[ver],setOfSizes[i][ver]);
       }
   }
@@ -105,19 +107,22 @@ void meshMetric::updateMetrics()
 void meshMetric::exportInfo(const char * fileendname)
 {
   if (needMetricUpdate) updateMetrics();
-  std::stringstream sg,sm,sl,sh;
+  std::stringstream sg,sm,sl,sh,shm;
   sg << "meshmetric_gradients_" << fileendname;
   sm << "meshmetric_metric_" << fileendname;
   sl << "meshmetric_levelset_" << fileendname;
   sh << "meshmetric_hessian_" << fileendname;
+  shm << "meshmetric_hessianmat_" << fileendname;
   std::ofstream out_grad(sg.str().c_str());
   std::ofstream out_metric(sm.str().c_str());
   std::ofstream out_ls(sl.str().c_str());
   std::ofstream out_hess(sh.str().c_str());
+  std::ofstream out_hessmat(shm.str().c_str());
   out_grad << "View \"ls_gradient\"{" << std::endl;
   out_metric << "View \"metric\"{" << std::endl;
   out_ls << "View \"ls\"{" << std::endl;
   out_hess << "View \"hessian\"{" << std::endl;
+  out_hessmat << "View \"hessian_mat\"{" << std::endl;
   std::vector<MElement*>::iterator itelem = _elements.begin();
   std::vector<MElement*>::iterator itelemen = _elements.end();
   for (;itelem!=itelemen;itelem++){
@@ -127,12 +132,14 @@ void meshMetric::exportInfo(const char * fileendname)
       out_grad << "VT(";
       out_ls << "ST(";
       out_hess << "ST(";
+      out_hessmat << "TT(";
     }
     else {
       out_metric << "TS(";
       out_grad << "VS(";
       out_ls << "SS(";
       out_hess << "SS(";
+      out_hessmat << "TS(";
     }
     for ( int i = 0; i < e->getNumVertices(); i++) {
       MVertex *ver = e->getVertex(i);
@@ -140,17 +147,20 @@ void meshMetric::exportInfo(const char * fileendname)
       out_grad << ver->x() << "," << ver->y() << "," << ver->z();
       out_ls << ver->x() << "," << ver->y() << "," << ver->z();
       out_hess << ver->x() << "," << ver->y() << "," << ver->z();
+      out_hessmat << ver->x() << "," << ver->y() << "," << ver->z();
       if (i!=e->getNumVertices()-1){
         out_metric << ",";
         out_grad << ",";
         out_ls << ",";
         out_hess << ",";
+        out_hessmat << ",";
       }
       else{
         out_metric << "){";
         out_grad << "){";
         out_ls << "){";
-	out_hess << "){";
+        out_hess << "){";
+        out_hessmat << "){";
       }
     }
     for ( int i = 0; i < e->getNumVertices(); i++) {
@@ -161,12 +171,12 @@ void meshMetric::exportInfo(const char * fileendname)
       SVector3 gradudz = dgrads[2][ver];
       out_hess << (gradudx(0) + gradudy(1) + gradudz(2));
       if (i == (e->getNumVertices() - 1)){
-	out_ls << "};" << std::endl;
-	out_hess << "};" << std::endl;
+        out_ls << "};" << std::endl;
+        out_hess << "};" << std::endl;
       }
       else {
-	out_ls << ",";
-	out_hess << ",";
+        out_ls << ",";
+        out_hess << ",";
       }
       for (int k=0;k<3;k++){
         out_grad << grads[ver](k);
@@ -174,8 +184,15 @@ void meshMetric::exportInfo(const char * fileendname)
         else out_grad << ",";
         for (int l=0;l<3;l++){
           out_metric << _nodalMetrics[ver](k,l);
-          if ((k == 2) && (l == 2) && (i == (e->getNumVertices() - 1))) out_metric << "};" << std::endl;
-          else out_metric << ",";
+          out_hessmat << dgrads[k][ver](l);
+          if ((k == 2) && (l == 2) && (i == (e->getNumVertices() - 1))) {
+            out_metric << "};" << std::endl;
+            out_hessmat << "};" << std::endl;
+          }
+          else {
+            out_metric << ",";
+            out_hessmat << ",";
+          }
         }
       }
     }
@@ -184,10 +201,12 @@ void meshMetric::exportInfo(const char * fileendname)
   out_metric << "};" << std::endl;
   out_ls << "};" << std::endl;
   out_hess << "};" << std::endl;
+  out_hessmat << "};" << std::endl;
   out_grad.close();
   out_metric.close();
   out_ls.close();
   out_hess.close();
+  out_hessmat.close();
 }
 
 meshMetric::~meshMetric()
@@ -360,10 +379,9 @@ void meshMetric::computeMetricLevelSet(MVertex *ver, SMetric3 &hessian,  SMetric
 
 void meshMetric::computeMetricHessian(MVertex *ver, SMetric3 &hessian,  SMetric3 &metric, double &size, double x, double y, double z)
 {
-  double signed_dist;
+
   SVector3 gradudx, gradudy,gradudz,gr;
   if(ver != NULL){
-    signed_dist = vals[ver];
     gr = grads[ver];
     gradudx = dgrads[0][ver];
     gradudy = dgrads[1][ver];
@@ -373,7 +391,6 @@ void meshMetric::computeMetricHessian(MVertex *ver, SMetric3 &hessian,  SMetric3
     hessian(2,0) = gradudz(0); hessian(2,1) = gradudz(1); hessian(2,2) = gradudz(2);
   }
   else if (ver == NULL){
-    signed_dist = (*_fct)(x,y,z); 
     _fct->gradient(x,y,z,gr(0),gr(1),gr(2));
     _fct->hessian(x,y,z, hessian(0,0),hessian(0,1),hessian(0,2),
 		  hessian(1,0),hessian(1,1),hessian(1,2),
@@ -394,7 +411,7 @@ void meshMetric::computeMetricHessian(MVertex *ver, SMetric3 &hessian,  SMetric3
   
   SVector3 t1 (V(0,0),V(1,0),V(2,0));
   SVector3 t2 (V(0,1),V(1,1),V(2,1));
-  SVector3 t3 (V(0,2),V(1,2),V(2,2));
+  SVector3 t3  = (_dim == 3) ? SVector3(V(0,2),V(1,2),V(2,2)) : SVector3(0.,0.,1.);
   
   size =  std::min(std::min(1/sqrt(lambda1),1/sqrt(lambda2)),1/sqrt(lambda3));
   metric = SMetric3(lambda1,lambda2,lambda3,t1,t2,t3);
-- 
GitLab