From 9c6ea9bdce0a8d29cf6340d466ae2587a4b80ea1 Mon Sep 17 00:00:00 2001
From: Jean-Francois Remacle <jean-francois.remacle@uclouvain.be>
Date: Fri, 2 Apr 2010 09:49:34 +0000
Subject: [PATCH]

---
 Common/LuaBindings.cpp       |  2 ++
 Geo/GFaceCompound.cpp        |  3 ++
 Geo/MElement.cpp             | 20 ++++++++++++
 Geo/MElement.h               |  1 +
 Mesh/highOrderSmoother.cpp   | 33 ++++++++------------
 Solver/CMakeLists.txt        |  1 +
 Solver/dofManager.h          |  2 +-
 Solver/helmholtzTerm.h       |  2 ++
 Solver/linearSystem.cpp      | 41 +++++++++++++++++++++++++
 Solver/linearSystem.h        |  3 ++
 Solver/multiscaleLaplace.cpp | 59 ++++++++++++++++++++++++++++++++++--
 11 files changed, 142 insertions(+), 25 deletions(-)
 create mode 100644 Solver/linearSystem.cpp

diff --git a/Common/LuaBindings.cpp b/Common/LuaBindings.cpp
index 4451e9bbc1..48a0b7a5dd 100644
--- a/Common/LuaBindings.cpp
+++ b/Common/LuaBindings.cpp
@@ -25,6 +25,7 @@
 #include "Bindings.h"
 #include "drawContext.h"
 #include "GmshMessage.h"
+#include "linearSystem.h"
 
 #if defined(HAVE_SOLVER)
 #include "linearSystemCSR.h"
@@ -379,6 +380,7 @@ binding::binding()
   fullMatrix<double>::registerBindings(this);
   gmshOptions::registerBindings(this);
   Msg::registerBindings(this);
+  linearSystem<double>::registerBindings(this);
 #if defined(HAVE_SOLVER)
   function::registerBindings(this);
   linearSystemCSRGmm<double>::registerBindings(this);
diff --git a/Geo/GFaceCompound.cpp b/Geo/GFaceCompound.cpp
index 3e61adc6e4..14d50896f1 100644
--- a/Geo/GFaceCompound.cpp
+++ b/Geo/GFaceCompound.cpp
@@ -349,6 +349,8 @@ bool GFaceCompound::trivial() const
   if(_compound.size() == 1 && 
      (*(_compound.begin()))->getNativeType() == GEntity::OpenCascadeModel &&
      (*(_compound.begin()))->geomType() != GEntity::DiscreteSurface){
+    if ((*(_compound.begin()))->periodic(0) || 
+	(*(_compound.begin()))->periodic(1) )return false; 
     return true;
   }
   return false;
@@ -798,6 +800,7 @@ GFaceCompound::GFaceCompound(GModel *m, int tag, std::list<GFace*> &compound,
     _lsys = _lsysb;
 #elif defined(HAVE_TAUCS) 
     _lsys = new linearSystemCSRTaucs<double>;
+    printf("compound with taucs\n");
 #else
     _lsys = new linearSystemFull<double>;
 #endif
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index e58e1fe5be..8d055784ee 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -258,6 +258,26 @@ double MElement::getJacobian(double u, double v, double w, double jac[3][3])
   return _computeDeterminantAndRegularize(this, jac);
 }
 
+
+double MElement::getJacobian(double gsf[][3], double jac[3][3])
+{
+  jac[0][0] = jac[0][1] = jac[0][2] = 0.;
+  jac[1][0] = jac[1][1] = jac[1][2] = 0.;
+  jac[2][0] = jac[2][1] = jac[2][2] = 0.;
+
+  for (int i = 0; i < getNumVertices(); i++) {
+    const MVertex* v = getVertex(i);
+    double* gg = gsf[i];
+    for (int j = 0; j < 3; j++) {
+      jac[j][0] += v->x() * gg[j];
+      jac[j][1] += v->y() * gg[j];
+      jac[j][2] += v->z() * gg[j];
+    }
+  }
+
+  return _computeDeterminantAndRegularize(this, jac);
+}
+
 double MElement::getPrimaryJacobian(double u, double v, double w, double jac[3][3])
 {
   jac[0][0] = jac[0][1] = jac[0][2] = 0.;
diff --git a/Geo/MElement.h b/Geo/MElement.h
index e903ec9c6d..d13f59b206 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -217,6 +217,7 @@ class MElement
                                      int order=-1);
   // return the Jacobian of the element evaluated at point (u,v,w) in
   // parametric coordinates
+  double getJacobian(double gsf[][3], double jac[3][3]);
   double getJacobian(double u, double v, double w, double jac[3][3]);
   double getPrimaryJacobian(double u, double v, double w, double jac[3][3]);
 
diff --git a/Mesh/highOrderSmoother.cpp b/Mesh/highOrderSmoother.cpp
index cf41201773..7bdc487374 100644
--- a/Mesh/highOrderSmoother.cpp
+++ b/Mesh/highOrderSmoother.cpp
@@ -377,13 +377,13 @@ void highOrderSmoother::optimize(GFace * gf,
 
     smooth(gf, true);
     
-    /*
+    
     for (int i=0;i<100;i++){
       int nbSwap = 
 	swapHighOrderTriangles(gf,edgeVertices,faceVertices,this);
       printf("%d swaps\n",nbSwap);
     }
-    */
+    
     // smooth(gf,true);
     // smooth(gf,true);
     // smooth(gf,true);
@@ -1382,15 +1382,11 @@ static int swapHighOrderTriangles(GFace *gf,
 	  }
 	    
       
-      for (edgeContainer::iterator ecit = edgeVertices.begin(); ecit != edgeVertices.end(); ecit++) {
-	if (((*ecit).first.first == common_vertices[0] && 
-             (*ecit).first.second == common_vertices[1]) ||
-            ((*ecit).first.first == common_vertices[1] && 
-             (*ecit).first.second == common_vertices[0])) {
-	  //printf ("Hehe, gotcha !\n");
-	  edgeVertices.erase(ecit);
-	}
-      }
+      std::vector<std::pair<MVertex*,MVertex*> > toDelete;
+      MEdge _temp(common_vertices[0],common_vertices[1]);
+      std::pair<MVertex*, MVertex*> _temp2(_temp.getMinVertex(), _temp.getMaxVertex());
+      edgeVertices.erase(_temp2);
+
       /*
       for (faceContainer::iterator fcit = faceVertices.begin(); fcit != faceVertices.end(); fcit++) {
 	bool remove_this = true;
@@ -1460,16 +1456,11 @@ static int swapHighOrderTriangles(GFace *gf,
 	    break;
 	  }
 	    
-      
-      for (edgeContainer::iterator ecit = edgeVertices.begin(); ecit != edgeVertices.end(); ecit++) {
-        if (((*ecit).first.first == common_vertices[0] && 
-             (*ecit).first.second == common_vertices[1]) ||
-            ((*ecit).first.first == common_vertices[1] && 
-             (*ecit).first.second == common_vertices[0])) {	
-	  //printf ("Hehe, gotcha !\n");
-	  edgeVertices.erase(ecit);
-	}
-      }
+      // delete the edge inside the edgeContainer
+      std::vector<std::pair<MVertex*,MVertex*> > toDelete;
+      MEdge _temp(common_vertices[0],common_vertices[1]);
+      std::pair<MVertex*, MVertex*> _temp2(_temp.getMinVertex(), _temp.getMaxVertex());
+      edgeVertices.erase(_temp2);
 
       /*
       for (faceContainer::iterator fcit = faceVertices.begin(); fcit != faceVertices.end(); fcit++) {
diff --git a/Solver/CMakeLists.txt b/Solver/CMakeLists.txt
index 7194342b31..fbeea2c22e 100644
--- a/Solver/CMakeLists.txt
+++ b/Solver/CMakeLists.txt
@@ -4,6 +4,7 @@
 # bugs and problems to <gmsh@geuz.org>.
 
 set(SRC
+  linearSystem.cpp
   linearSystemCSR.cpp
   groupOfElements.cpp
   elasticityTerm.cpp
diff --git a/Solver/dofManager.h b/Solver/dofManager.h
index 49fa8f527d..9df7b57f88 100644
--- a/Solver/dofManager.h
+++ b/Solver/dofManager.h
@@ -108,7 +108,7 @@ class dofManager{
     _linearSystems.insert(std::make_pair("B", l2));
   }
   inline void fixDof(Dof key, const dataVec &value)
-  {
+  {    
     fixed[key] = value;
   }
   inline void fixDof(long int ent, int type, const dataVec &value)
diff --git a/Solver/helmholtzTerm.h b/Solver/helmholtzTerm.h
index 7bda156be0..cd2516c68e 100644
--- a/Solver/helmholtzTerm.h
+++ b/Solver/helmholtzTerm.h
@@ -52,6 +52,8 @@ class helmholtzTerm : public femTerm<scalar> {
     // compute integration rule
     const int integrationOrder = (_a) ? 2 * e->getPolynomialOrder() : 
       2 * (e->getPolynomialOrder() - 1);
+    //    const int integrationOrder = 2 * e->getPolynomialOrder() + 1; 
+
     int npts; IntPt *GP;
     e->getIntegrationPoints(integrationOrder, &npts, &GP);
     // get the number of nodes
diff --git a/Solver/linearSystem.cpp b/Solver/linearSystem.cpp
new file mode 100644
index 0000000000..fa6c3f239b
--- /dev/null
+++ b/Solver/linearSystem.cpp
@@ -0,0 +1,41 @@
+#include "GmshConfig.h"
+#include "linearSystemFull.h"
+#include "linearSystemCSR.h"
+#include "linearSystemGmm.h"
+#include "linearSystemPETSc.h"
+
+#include "Bindings.h"
+
+template<>
+void linearSystem<double>::registerBindings(binding *b){
+  classBinding *cb = b->addClass<linearSystem<double> >("linearSystem");
+  cb->setDescription("An abstraction of a linear system Ax = b.");
+  methodBinding *cm;
+  cm = cb->addMethod("systemSolve", &linearSystem<double>::systemSolve);
+  cm->setDescription("compute x = A^{-1}b");
+  
+#ifdef HAVE_TAUCS
+  cb = b->addClass<linearSystemCSRTaucs<double> >("linearSystemCSRTaucs");
+  cb->setDescription("A linear system solver, based on TAUCS, and that is ok for SDP sparse matrices.");
+  cm = cb->setConstructor<linearSystemCSRTaucs<double> >();
+  cm->setDescription ("A new TAUCS<double> solver");
+  cm->setArgNames(NULL);
+  cb->setParentClass<linearSystem<double> >();
+#endif
+
+#ifdef HAVE_PETSC
+  cb = b->addClass<linearSystemPETSc<double> >("linearSystemPETSc");
+  cb->setDescription("A linear system solver, based on PETSc");
+  cm = cb->setConstructor<linearSystemPETSc<double> >();
+  cm->setDescription ("A new PETSc<double> solver");
+  cm->setArgNames(NULL);
+  cb->setParentClass<linearSystem<double> >();
+#endif
+
+  cb = b->addClass<linearSystemFull<double> >("linearSystemFull");
+  cb->setDescription("A linear system solver, based on LAPACK (full matrices)");
+  cm = cb->setConstructor<linearSystemFull<double> >();
+  cm->setDescription ("A new Lapack based <double> solver");
+  cm->setArgNames(NULL);
+  cb->setParentClass<linearSystem<double> >();
+}
diff --git a/Solver/linearSystem.h b/Solver/linearSystem.h
index c3e860aa05..3b6f9982ed 100644
--- a/Solver/linearSystem.h
+++ b/Solver/linearSystem.h
@@ -8,6 +8,8 @@
 
 // A class that encapsulates a linear system solver interface :
 // building a sparse matrix, solving a linear system
+class binding;
+
 template <class scalar>
 class linearSystem {
  public :
@@ -24,6 +26,7 @@ class linearSystem {
   virtual void zeroMatrix() = 0;
   virtual void zeroRightHandSide() = 0;
   virtual int systemSolve() = 0;
+  static void registerBindings (binding*);
 };
 
 #endif
diff --git a/Solver/multiscaleLaplace.cpp b/Solver/multiscaleLaplace.cpp
index 1ea041f29f..1da275c77e 100644
--- a/Solver/multiscaleLaplace.cpp
+++ b/Solver/multiscaleLaplace.cpp
@@ -627,7 +627,8 @@ static void connected_left_right (std::vector<MElement *> &left,
 static void printLevel(const char* fn,
                        std::vector<MElement *> &elements,
                        std::map<MVertex*,SPoint2> *coordinates,
-                       double version)
+                       double version,
+		       double *dx = 0)
 {
   if(!CTX::instance()->mesh.saveAll) return;  
 
@@ -648,7 +649,10 @@ static void printLevel(const char* fn,
   for (; it != vs.end() ; ++it){
     (*it)->setIndex(index++);
     SPoint2 p = (coordinates) ? (*coordinates)[*it] : SPoint2(0,0);
-    if (coordinates) fprintf(fp, "%d %g %g 0\n", (*it)->getIndex(), p.x(), p.y());
+    if (coordinates) {
+      if (dx)fprintf(fp, "%d %22.15E %22.15E 0\n", (*it)->getIndex(), dx[2]*(p.x()-dx[0]), dx[2]*(p.y()-dx[1]));
+      else   fprintf(fp, "%d %22.15E %22.15E 0\n", (*it)->getIndex(), p.x(), p.y());
+    }
     else fprintf(fp, "%d %g %g %g\n", (*it)->getIndex(),
                  (*it)->x(), (*it)->y(), (*it)->z());
   }
@@ -663,6 +667,10 @@ static void printLevel(const char* fn,
   fclose(fp);
 }
 //--------------------------------------------------------------
+
+
+
+
 static double localSize(MElement *e,  std::map<MVertex*,SPoint2> &solution){
 
   SBoundingBox3d local;
@@ -691,6 +699,35 @@ static double localSize(MElement *e,  std::map<MVertex*,SPoint2> &solution){
  
    
 }
+
+
+//--------------------------------------------------------------
+static void printLevel_onlysmall(const char* fn,
+				 std::vector<MElement *> &elements,
+				 std::map<MVertex*,SPoint2> *coordinates,
+				 double version,
+				 double tolerance){
+  std::vector<MElement *> small;
+  double dx[3] = {0,0,0};
+  int COUNT = 0;
+  for (int i=0;i<elements.size();i++){
+    double local_size = localSize(elements[i],*coordinates);
+    if (local_size < tolerance){
+      small.push_back(elements[i]);
+      for (int j=0;j<3;j++){
+	SPoint2 p = (*coordinates)[elements[i]->getVertex(j)];
+	dx[0] += p.x();
+	dx[1] += p.y();
+	COUNT++;
+      }
+    }
+  }
+  dx[0] /= COUNT;
+  dx[1] /= COUNT;
+  dx[2] = 1./tolerance;
+  printLevel(fn,small,coordinates,version,dx);
+}
+
 //-------------------------------------------------------------
 static void one2OneMap(std::vector<MElement *> &elements, std::map<MVertex*,SPoint2> &solution) {
 
@@ -790,6 +827,7 @@ multiscaleLaplace::multiscaleLaplace (std::vector<MElement *> &elements,
 
 #if defined(HAVE_TAUCS)
   _lsys = new linearSystemCSRTaucs<double>;
+  printf("taucs again\n");
 #elif defined(HAVE_GMM)
   linearSystemGmm<double> *_lsysb = new linearSystemGmm<double>;
   _lsysb->setGmres(1);
@@ -947,7 +985,7 @@ void multiscaleLaplace::parametrize (multiscaleLaplaceLevel & level){
     std::vector<SPoint2> localCoord;
     double local_size = localSize(e,solution);
     if (local_size < 1.e-5*global_size) //1.e-5
-        tooSmall.push_back(e);
+      tooSmall.push_back(e);
     else  goodSize.push_back(e);
   }
 
@@ -1068,8 +1106,10 @@ void multiscaleLaplace::parametrize (multiscaleLaplaceLevel & level){
   //Save multiscale meshes
   std::string name1(level._name+"real.msh");
   std::string name2(level._name+"param.msh");
+  std::string name3(level._name+"param_small.msh");
   printLevel (name1.c_str(),level.elements,0,2.2);
   printLevel (name2.c_str(),level.elements,&level.coordinates,2.2);
+  printLevel_onlysmall (name3.c_str(),level.elements,&level.coordinates,2.2,1.e-15);
 
   //For every small region compute a new parametrization
   Msg::Info("Level (%d-%d): %d connected small regions",level.recur, level.region, regions.size());
@@ -1181,6 +1221,19 @@ void multiscaleLaplace::cut (std::vector<MElement *> &elements)
   printLevel ("Rootcut-right.msh",right,0,2.2);  
   printLevel ("Rootcut-all.msh",elements, 0,2.2);  
 
+  printLevel ("Rootcut-left-param.msh",left,&root->coordinates,2.2);
+  printLevel_onlysmall ("Rootcut-left-param10.msh",left,&root->coordinates,2.2,1.e-10);
+  printLevel_onlysmall ("Rootcut-left-param12.msh",left,&root->coordinates,2.2,1.e-12);
+  printLevel_onlysmall ("Rootcut-left-param15.msh",left,&root->coordinates,2.2,1.e-15);
+
+  printLevel ("Rootcut-right-param.msh",right,&root->coordinates,2.2);
+  printLevel_onlysmall ("Rootcut-right-param10.msh",right,&root->coordinates,2.2,1.e-10);
+  printLevel_onlysmall ("Rootcut-right-param12.msh",right,&root->coordinates,2.2,1.e-12);
+  printLevel_onlysmall ("Rootcut-right-param15.msh",right,&root->coordinates,2.2,1.e-15);
+
+  printLevel_onlysmall ("Rootcut-all-param12.msh",elements,&root->coordinates,2.2,1.e-12);
+  printLevel_onlysmall ("Rootcut-all-param15.msh",elements,&root->coordinates,2.2,1.e-15);
+
   if ( elements.size() != left.size()+right.size()) {
     Msg::Error("Cutting laplace wrong nb elements (%d) != left + right (%d)",  elements.size(), left.size()+right.size());
     exit(1);
-- 
GitLab