From 0ec057eacb9b8bd1efa91f02dddb34b538dfd190 Mon Sep 17 00:00:00 2001
From: Tristan Carrier Baudouin <tristan.carrier@uclouvain.be>
Date: Wed, 3 Oct 2012 08:44:19 +0000
Subject: [PATCH] size field

---
 Mesh/directions3D.cpp | 274 +++++++++++++++++++++++++++++++++++++-----
 Mesh/directions3D.h   |  22 +++-
 2 files changed, 263 insertions(+), 33 deletions(-)

diff --git a/Mesh/directions3D.cpp b/Mesh/directions3D.cpp
index f739a3d386..3619d29074 100644
--- a/Mesh/directions3D.cpp
+++ b/Mesh/directions3D.cpp
@@ -11,6 +11,14 @@
 #include "BackgroundMesh.h"
 #include "meshGFaceDelaunayInsertion.h"
 #include <fstream>
+#include "MTetrahedron.h"
+
+#if defined(HAVE_PETSC)
+#include "dofManager.h"
+#include "laplaceTerm.h"
+#include "linearSystemPETSc.h"
+#include "linearSystemFull.h"
+#endif
 
 /****************class Matrix****************/
 
@@ -120,7 +128,9 @@ void Frame_field::init_model(){
   for(it=model->firstFace();it!=model->lastFace();it++)
   {
     gf = *it;
-	init_face(gf);
+	if(gf->geomType()==GEntity::CompoundSurface){
+	  init_face(gf);
+	}
   }
 
   duplicate = annAllocPts(field.size(),3);
@@ -144,6 +154,8 @@ void Frame_field::init_face(GFace* gf){
   unsigned int i;
   int j;
   bool ok;
+  double average_x,average_y;
+  SPoint2 point;
   SVector3 v1,v2,v3;
   MVertex* vertex;
   MElement* element;
@@ -155,9 +167,23 @@ void Frame_field::init_face(GFace* gf){
 
   for(i=0;i<gf->getNumMeshElements();i++){
     element = gf->getMeshElement(i);
+	  
+	average_x = 0.0;
+	average_y = 0.0;
+	  
 	for(j=0;j<element->getNumVertices();j++){
 	  vertex = element->getVertex(j);
-	  ok = translate(gf,octree,vertex,v1,v2);
+	  reparamMeshVertexOnFace(vertex,gf,point);
+	  average_x = average_x + point.x();
+	  average_y = average_y + point.y();
+	}	
+	  
+	average_x = average_x/element->getNumVertices();
+	average_y = average_y/element->getNumVertices();
+	  
+	for(j=0;j<element->getNumVertices();j++){
+	  vertex = element->getVertex(j);
+	  ok = translate(gf,octree,vertex,SPoint2(average_x,average_y),v1,v2);
 	  if(ok){
 	    v3 = crossprod(v1,v2);
 	    v1.normalize();
@@ -178,27 +204,7 @@ void Frame_field::init_face(GFace* gf){
   }
 }
 
-bool Frame_field::inside_domain(MElementOctree* octree,double x,double y){
-  MElement* element;
-  element = (MElement*)octree->find(x,y,0.0,2,true);
-  if(element!=NULL) return 1;
-  else return 0;
-}
-
-double Frame_field::get_size(GFace* gf,double x,double y){
-  double ratio;
-  double uv[2];
-  double tab[3];
-
-  uv[0] = x;
-  uv[1] = y;
-  buildMetric(gf,uv,tab);
-  ratio = 1.0/pow(tab[0]*tab[2]-tab[1]*tab[1],0.25);
-
-  return ratio*backgroundMesh::current()->operator()(x,y,0.0);
-}
-
-bool Frame_field::translate(GFace* gf,MElementOctree* octree,MVertex* vertex,SVector3& v1,SVector3& v2){
+bool Frame_field::translate(GFace* gf,MElementOctree* octree,MVertex* vertex,SPoint2 corr,SVector3& v1,SVector3& v2){
   bool ok;
   double k;
   double size;
@@ -217,7 +223,7 @@ bool Frame_field::translate(GFace* gf,MElementOctree* octree,MVertex* vertex,SVe
   reparamMeshVertexOnFace(vertex,gf,point);
   x = point.x();
   y = point.y();
-  size = get_size(gf,x,y);
+  size = backgroundMesh::current()->operator()(x,y,0.0)*get_ratio(gf,corr);
   angle = backgroundMesh::current()->getAngle(x,y,0.0);
 
   delta_x = k*size*cos(angle);
@@ -281,11 +287,23 @@ Matrix Frame_field::search(double x,double y,double z){
   return random[val].second;
 }
 
-void Frame_field::print_segment(SPoint3 p1,SPoint3 p2,std::ofstream& file){
-  file << "SL ("
-  << p1.x() << ", " << p1.y() << ", " << p1.z() << ", "
-  << p2.x() << ", " << p2.y() << ", " << p2.z() << ")"
-  << "{10, 20};\n";
+bool Frame_field::inside_domain(MElementOctree* octree,double x,double y){
+  MElement* element;
+  element = (MElement*)octree->find(x,y,0.0,2,true);
+  if(element!=NULL) return 1;
+  else return 0;
+}
+
+double Frame_field::get_ratio(GFace* gf,SPoint2 point){
+  double val;
+  double uv[2];
+  double tab[3];
+	
+  uv[0] = point.x();
+  uv[1] = point.y();
+  buildMetric(gf,uv,tab);
+  val = 1.0/pow(tab[0]*tab[2]-tab[1]*tab[1],0.25);
+  return val;
 }
 
 void Frame_field::print_field1(){
@@ -372,6 +390,13 @@ void Frame_field::print_field2(){
   file << "};\n";
 }
 
+void Frame_field::print_segment(SPoint3 p1,SPoint3 p2,std::ofstream& file){
+  file << "SL ("
+  << p1.x() << ", " << p1.y() << ", " << p1.z() << ", "
+  << p2.x() << ", " << p2.y() << ", " << p2.z() << ")"
+  << "{10, 20};\n";
+}
+
 void Frame_field::clear(){
   field.clear();
   random.clear();
@@ -382,6 +407,195 @@ void Frame_field::clear(){
   #endif
 }
 
+/****************class Size_field****************/
+
+Size_field::Size_field(){}
+
+void Size_field::init_model(){
+  size_t i;
+  int j;
+  double local_size;
+  double average_x,average_y;
+  SPoint2 point;
+  MElement* element;
+  MVertex* vertex;
+  GFace* gf;
+  GModel* model = GModel::current();
+  GModel::fiter it;
+  
+  boundary.clear();	
+	
+  for(it=model->firstFace();it!=model->lastFace();it++){
+    gf = *it;
+	if(gf->geomType()==GEntity::CompoundSurface){
+	  backgroundMesh::set(gf);
+	  for(i=0;i<gf->getNumMeshElements();i++){
+	    element = gf->getMeshElement(i);
+		
+	    average_x = 0.0;
+	    average_y = 0.0;
+		
+	    for(j=0;j<element->getNumVertices();j++){
+	      vertex = element->getVertex(j);
+		  reparamMeshVertexOnFace(vertex,gf,point);
+		  average_x = average_x + point.x();
+		  average_y = average_y + point.y();
+	    }	
+		
+	    average_x = average_x/element->getNumVertices();
+	    average_y = average_y/element->getNumVertices();
+		
+	    for(j=0;j<element->getNumVertices();j++){
+	      vertex = element->getVertex(j);
+		  reparamMeshVertexOnFace(vertex,gf,point);
+		  local_size = backgroundMesh::current()->operator()(point.x(),point.y(),0.0);
+		  boundary.insert(std::pair<MVertex*,double>(vertex,/*local_size*/0.2));
+	    }
+	  }
+	}
+  }
+
+  octree = new MElementOctree(model);
+}
+
+void Size_field::solve(){
+#if defined(HAVE_PETSC)
+  linearSystem<double>* system = 0;
+  //system = new linearSystemPETSc<double>;
+  system = new linearSystemFull<double>;
+
+  size_t i;
+  int j;
+  double val;
+  MElement* element;
+  MVertex* vertex;
+  MTetrahedron* temp;
+  GRegion* gr;
+  GModel* model = GModel::current();
+  GModel::riter it;
+  std::map<MVertex*,double>::iterator it2;
+  std::set<MVertex*>::iterator it3;
+  std::set<MVertex*> interior;
+	
+  interior.clear();
+	
+  dofManager<double> assembler(system);
+	
+  for(it2=boundary.begin();it2!=boundary.end();it2++){
+    assembler.fixVertex(it2->first,0,1,it2->second);
+  }
+	
+  for(it=model->firstRegion();it!=model->lastRegion();it++){
+    gr = *it;
+	for(i=0;i<gr->getNumMeshElements();i++){
+	  element = gr->getMeshElement(i);
+	  for(j=0;j<element->getNumVertices();j++){
+	    vertex = element->getVertex(j);
+	    interior.insert(vertex);
+	  }
+	}
+  }	
+		
+  for(it3=interior.begin();it3!=interior.end();it3++){
+    it2 = boundary.find(*it3);
+	if(it2==boundary.end()){
+	  assembler.numberVertex(*it3,0,1);
+	}
+  }
+	
+  simpleFunction<double> ONE(1.0);
+  laplaceTerm term(0,1,&ONE);
+  for(it=model->firstRegion();it!=model->lastRegion();it++){
+    gr = *it;
+	for(i=0;i<gr->getNumMeshElements();i++){
+      element = gr->getMeshElement(i);
+	  temp = (MTetrahedron*)element;
+	  SElement se(temp);
+	  term.addToMatrix(assembler,&se);
+	}
+  }
+	
+  system->systemSolve();
+	
+  for(it3=interior.begin();it3!=interior.end();it3++){
+    assembler.getDofValue(*it3,0,1,val);
+    boundary.insert(std::pair<MVertex*,double>(*it3,val));
+  }
+	
+  delete system;
+#endif	
+}
+
+double Size_field::search(double x,double y,double z){
+  double u,v,w;
+  double val;
+  MElement* element;
+  double temp1[3];
+  double temp2[3];
+  std::map<MVertex*,double>::iterator it1;
+  std::map<MVertex*,double>::iterator it2;
+  std::map<MVertex*,double>::iterator it3;
+  std::map<MVertex*,double>::iterator it4;
+	
+  val = 1.0;	
+	
+  element = (MElement*)octree->find(x,y,z,3,true);
+	
+  if(element!=NULL){
+	temp1[0] = x;
+	temp1[1] = y;
+	temp1[2] = z;
+	
+	element->xyz2uvw(temp1,temp2);
+	  
+	u = temp2[0];
+    v = temp2[1];
+	w = temp2[2];
+	
+	it1 = boundary.find(element->getVertex(0)); 
+	it2 = boundary.find(element->getVertex(1));
+	it3 = boundary.find(element->getVertex(2));
+	it4 = boundary.find(element->getVertex(3));
+	  
+	if(it1!=boundary.end() && it2!=boundary.end() && it3!=boundary.end() && it4!=boundary.end()){
+	  val = (it1->second)*(1.0-u-v-w) + (it2->second)*u + (it3->second)*v + (it4->second)*w;
+	}
+  }
+	
+  return val;
+}
+
+double Size_field::get_ratio(GFace* gf,SPoint2 point){
+  double val;
+  double uv[2];
+  double tab[3];
+	
+  uv[0] = point.x();
+  uv[1] = point.y();
+  buildMetric(gf,uv,tab);
+  val = 1.0/pow(tab[0]*tab[2]-tab[1]*tab[1],0.25);
+  return val;
+}
+
+void Size_field::print_field(){
+  double x,y,z;
+  std::map<MVertex*,double>::iterator it;
+		
+  for(it=boundary.begin();it!=boundary.end();it++){
+	x = (it->first)->x();
+	y = (it->first)->y();
+	z = (it->first)->z();
+    printf("(%f,%f,%f) -> %f\n",x,y,z,it->second);
+  }
+
+  printf("%zu\n",boundary.size());
+}
+
+void Size_field::clear(){
+  delete octree;
+  boundary.clear();
+}
+
 /****************static declarations****************/
 
 std::map<MVertex*,Matrix> Frame_field::field;
@@ -390,3 +604,5 @@ std::vector<std::pair<MVertex*,Matrix> > Frame_field::random;
 ANNpointArray Frame_field::duplicate;
 ANNkd_tree* Frame_field::kd_tree;
 #endif
+std::map<MVertex*,double> Size_field::boundary;
+MElementOctree* Size_field::octree;
\ No newline at end of file
diff --git a/Mesh/directions3D.h b/Mesh/directions3D.h
index 9dee86a7aa..59c4a65e3d 100644
--- a/Mesh/directions3D.h
+++ b/Mesh/directions3D.h
@@ -50,12 +50,26 @@ class Frame_field{
  public:
   static void init_model();
   static void init_face(GFace*);
-  static bool inside_domain(MElementOctree*,double,double);
-  static double get_size(GFace*,double,double);
-  static bool translate(GFace*,MElementOctree*,MVertex*,SVector3&,SVector3&);
+  static bool translate(GFace*,MElementOctree*,MVertex*,SPoint2,SVector3&,SVector3&);
   static Matrix search(double,double,double);
-  static void print_segment(SPoint3,SPoint3,std::ofstream&);
+  static bool inside_domain(MElementOctree*,double,double);
+  static double get_ratio(GFace*,SPoint2);
   static void print_field1();
   static void print_field2();
+  static void print_segment(SPoint3,SPoint3,std::ofstream&);
+  static void clear();
+};
+
+class Size_field{
+ private:
+  static std::map<MVertex*,double> boundary;
+  static MElementOctree* octree;
+  Size_field();
+ public:
+  static void init_model();
+  static void solve();
+  static double search(double,double,double);
+  static double get_ratio(GFace*,SPoint2);
+  static void print_field();
   static void clear();
 };
-- 
GitLab