From 9bf05e3921a7907a165a2a6d1c3f5b6e9df9f727 Mon Sep 17 00:00:00 2001
From: Samuel Melchior <samuel.melchior@uclouvain.be>
Date: Tue, 8 Dec 2009 07:55:31 +0000
Subject: [PATCH] 1D

---
 CMakeLists.txt               |  2 +
 Geo/MElement.cpp             |  9 +++--
 Geo/MElement.h               |  3 ++
 Geo/MLine.h                  |  1 +
 Geo/MPoint.h                 | 12 ++++++
 Numeric/polynomialBasis.cpp  | 24 ++++++++++--
 Numeric/polynomialBasis.h    |  5 +++
 Solver/dgAlgorithm.cpp       |  5 +--
 Solver/dgGroupOfElements.cpp | 73 ++++++++++++++++++++++++++++++------
 Solver/dgGroupOfElements.h   |  2 +
 10 files changed, 115 insertions(+), 21 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 716c8f82b8..8fca86e060 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1016,3 +1016,5 @@ target_link_libraries(gmshdgsw ${LINK_LIBRARIES})
 add_executable(gmshdgwave EXCLUDE_FROM_ALL Solver/dgMainWaveEquation.cpp ${GMSH_SRC})
 target_link_libraries(gmshdgwave ${LINK_LIBRARIES})
 
+add_executable(gmshdgsam EXCLUDE_FROM_ALL Solver/dgMainSam.cpp ${GMSH_SRC})
+target_link_libraries(gmshdgsam ${LINK_LIBRARIES})
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index ca3ba8a384..2d475aaff1 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -154,6 +154,7 @@ static double _computeDeterminantAndRegularize(MElement *ele, double jac[3][3])
 
   case 0:
     {
+      dJ = 1.0;
       jac[0][0] = jac[1][1] = jac[2][2] = 1.0;
       jac[0][1] = jac[1][0] = jac[2][0] = 0.0;
       jac[0][2] = jac[1][2] = jac[2][1] = 0.0;    
@@ -165,9 +166,9 @@ static double _computeDeterminantAndRegularize(MElement *ele, double jac[3][3])
 
       // regularize matrix
       double a[3], b[3], c[3];
-      a[0] = ele->getVertex(1)->x() - ele->getVertex(0)->x(); 
-      a[1] = ele->getVertex(1)->y() - ele->getVertex(0)->y();
-      a[2] = ele->getVertex(1)->z() - ele->getVertex(0)->z();     
+      a[0] = jac[0][0];
+      a[1] = jac[0][1];
+      a[2] = jac[0][2];
       if((fabs(a[0]) >= fabs(a[1]) && fabs(a[0]) >= fabs(a[2])) ||
          (fabs(a[1]) >= fabs(a[0]) && fabs(a[1]) >= fabs(a[2]))) {
         b[0] = a[1]; b[1] = -a[0]; b[2] = 0.;
@@ -175,7 +176,9 @@ static double _computeDeterminantAndRegularize(MElement *ele, double jac[3][3])
       else {
         b[0] = 0.; b[1] = a[2]; b[2] = -a[1];
       }
+      norme(b);
       prodve(a, b, c);
+      norme(c);
       jac[0][1] = b[0]; jac[1][1] = b[1]; jac[2][1] = b[2]; 
       jac[0][2] = c[0]; jac[1][2] = c[1]; jac[2][2] = c[2]; 
       break;
diff --git a/Geo/MElement.h b/Geo/MElement.h
index 44f6c2b73c..90de79149e 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -73,6 +73,9 @@ class MElement
   // get the vertices
   virtual int getNumVertices() const = 0;
   virtual MVertex *getVertex(int num) = 0;
+  // give an MVertex as input and get its local number
+  virtual void getVertexInfo (const MVertex * vertex, int &ithVertex) const 
+  {throw;}
 
   // get the vertex using the I-deas UNV ordering
   virtual MVertex *getVertexUNV(int num){ return getVertex(num); }
diff --git a/Geo/MLine.h b/Geo/MLine.h
index 74542824aa..7266b32e38 100644
--- a/Geo/MLine.h
+++ b/Geo/MLine.h
@@ -37,6 +37,7 @@ class MLine : public MElement {
   virtual int getDim(){ return 1; }
   virtual int getNumVertices() const { return 2; }
   virtual MVertex *getVertex(int num){ return _v[num]; }
+  virtual void getVertexInfo (const MVertex * vertex, int &ithVertex) const { ithVertex = _v[0] == vertex ? 0 : 1; }
   virtual int getNumEdges(){ return 1; }
   virtual MEdge getEdge(int num){ return MEdge(_v[0], _v[1]); }
   virtual int getNumEdgesRep(){ return 1; }
diff --git a/Geo/MPoint.h b/Geo/MPoint.h
index 55ed9c2c69..3098159e06 100644
--- a/Geo/MPoint.h
+++ b/Geo/MPoint.h
@@ -50,10 +50,22 @@ class MPoint : public MElement {
   {
     s[0][0] = s[0][1] = s[0][2] = 0.;
   }
+
+  virtual const polynomialBasis* getFunctionSpace(int o) const { return &polynomialBases::find(MSH_PNT); }
   virtual bool isInside(double u, double v, double w)
   {
     return true;
   }
+  virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
+  {
+  static IntPt GQL[1]; 
+  GQL[0].pt[0] = 0;
+  GQL[0].pt[1] = 0;
+  GQL[0].pt[2] = 0;
+  GQL[0].weight = 1;
+  *npts = 1;
+  *pts = GQL;
+  }
 };
 
 #endif
diff --git a/Numeric/polynomialBasis.cpp b/Numeric/polynomialBasis.cpp
index 46f7c9e38e..69c28525df 100644
--- a/Numeric/polynomialBasis.cpp
+++ b/Numeric/polynomialBasis.cpp
@@ -21,10 +21,13 @@ static fullMatrix<double> generate1DMonomials(int order)
 static fullMatrix<double> generate1DPoints(int order)
 {
   fullMatrix<double> line(order + 1, 1);
-  line(0, 0) = -1.;
-  line(1, 0) =  1.;
-  double dd = 2. / order;
-  for (int i = 2; i < order + 1; i++) line(i, 0) = -1. + dd * (i - 1);
+  line(0,0) = 0;
+  if (order > 0) {
+    line(0, 0) = -1.;
+    line(1, 0) =  1.;
+    double dd = 2. / order;
+    for (int i = 2; i < order + 1; i++) line(i, 0) = -1. + dd * (i - 1);
+  }
   return line;
 }
 
@@ -762,6 +765,14 @@ static void generate2dEdgeClosure(polynomialBasis::clCont &closure, int order)
   }
 }
 
+
+static void generate1dVertexClosure(polynomialBasis::clCont &closure)
+{
+  closure.clear();
+  closure.resize(2);
+  closure[0].push_back(0);
+  closure[1].push_back(1);
+  }
 std::map<int, polynomialBasis> polynomialBases::fs;
 
 const polynomialBasis &polynomialBases::find(int tag) 
@@ -779,22 +790,27 @@ const polynomialBasis &polynomialBases::find(int tag)
   case MSH_LIN_2 :
     F.monomials = generate1DMonomials(1);
     F.points    = generate1DPoints(1);
+    generate1dVertexClosure(F.vertexClosure);
     break;
   case MSH_LIN_3 :
     F.monomials = generate1DMonomials(2);
     F.points    = generate1DPoints(2);
+    generate1dVertexClosure(F.vertexClosure);
     break;
   case MSH_LIN_4:
     F.monomials = generate1DMonomials(3);
     F.points    = generate1DPoints(3);
+    generate1dVertexClosure(F.vertexClosure);
     break;
   case MSH_LIN_5:
     F.monomials = generate1DMonomials(4);
     F.points    = generate1DPoints(4);
+    generate1dVertexClosure(F.vertexClosure);
     break;
   case MSH_LIN_6:
     F.monomials = generate1DMonomials(5);
     F.points    = generate1DPoints(5);
+    generate1dVertexClosure(F.vertexClosure);
     break;  
   case MSH_TRI_3 :
     F.monomials = generatePascalTriangle(1);
diff --git a/Numeric/polynomialBasis.h b/Numeric/polynomialBasis.h
index 01b8f846c3..9abcf5549e 100644
--- a/Numeric/polynomialBasis.h
+++ b/Numeric/polynomialBasis.h
@@ -18,6 +18,7 @@ struct polynomialBasis
   typedef std::vector<std::vector<int> > clCont;
   clCont faceClosure;
   clCont edgeClosure;
+  clCont vertexClosure;
   fullMatrix<double> points;
   fullMatrix<double> monomials;
   fullMatrix<double> coefficients;
@@ -31,6 +32,10 @@ struct polynomialBasis
   {
     return edgeClosure[iSign == 1 ? iEdge : 3 + iEdge];
   }
+  inline const std::vector<int> &getVertexClosure(int iVertex) const
+  {
+    return vertexClosure[iVertex];
+  }
   inline void evaluateMonomials(double u, double v, double w, double p[]) const 
   {
     for (int j = 0; j < monomials.size1(); j++) {
diff --git a/Solver/dgAlgorithm.cpp b/Solver/dgAlgorithm.cpp
index 9a1345a569..9d24b82703 100644
--- a/Solver/dgAlgorithm.cpp
+++ b/Solver/dgAlgorithm.cpp
@@ -364,10 +364,9 @@ void dgAlgorithm::buildGroups(GModel *model, int dim, int order,
   switch(dim) {
     case 1 : {
       std::map<const std::string, std::set<MVertex*> >::iterator mapIt;
-      /*for(mapIt=boundaryVertices.begin(); mapIt!=boundaryVertices.end(); mapIt++) {
+      for(mapIt=boundaryVertices.begin(); mapIt!=boundaryVertices.end(); mapIt++) {
         bGroups.push_back(new dgGroupOfFaces(*eGroups[0],mapIt->first,order,mapIt->second));
-      }*/
-      throw;
+      }
       break;
     }
     case 2 : {
diff --git a/Solver/dgGroupOfElements.cpp b/Solver/dgGroupOfElements.cpp
index 7694e1c065..315b037103 100644
--- a/Solver/dgGroupOfElements.cpp
+++ b/Solver/dgGroupOfElements.cpp
@@ -4,6 +4,7 @@
 #include "Numeric.h"
 #include "MTriangle.h"
 #include "MLine.h"
+#include "MPoint.h"
 #include "GModel.h"
 
 static fullMatrix<double> * dgGetIntegrationRule (MElement *e, int p){
@@ -68,16 +69,15 @@ dgGroupOfElements::dgGroupOfElements(const std::vector<MElement*> &e, int polyOr
         e->getJacobian ((*_integration)(j,0), (*_integration)(j,1), (*_integration)(j,2), jac);
       const double weight = (*_integration)(j,3);
       detjac=inv3x3(jac,ijac);
-      (*_mapping)(i,10*j + 0) = ijac[0][0]; 
-      (*_mapping)(i,10*j + 1) = ijac[0][1]; 
-      (*_mapping)(i,10*j + 2) = ijac[0][2]; 
-      (*_mapping)(i,10*j + 3) = ijac[1][0]; 
-      (*_mapping)(i,10*j + 4) = ijac[1][1]; 
-      (*_mapping)(i,10*j + 5) = ijac[1][2]; 
-      (*_mapping)(i,10*j + 6) = ijac[2][0]; 
-      (*_mapping)(i,10*j + 7) = ijac[2][1]; 
-      (*_mapping)(i,10*j + 8) = ijac[2][2]; 
-      (*_mapping)(i,10*j + 9) = detjac; 
+      (*_mapping)(i,10*j + 0) = ijac[0][0];
+      (*_mapping)(i,10*j + 1) = ijac[0][1];
+      (*_mapping)(i,10*j + 2) = ijac[0][2];
+      (*_mapping)(i,10*j + 3) = ijac[1][0];
+      (*_mapping)(i,10*j + 4) = ijac[1][1];
+      (*_mapping)(i,10*j + 5) = ijac[1][2];
+      (*_mapping)(i,10*j + 6) = ijac[2][0];
+      (*_mapping)(i,10*j + 7) = ijac[2][1];
+      (*_mapping)(i,10*j + 8) = ijac[2][2];
       for (int k=0;k<_fs.coefficients.size1();k++){ 
         for (int l=0;l<_fs.coefficients.size1();l++) { 
           imass(k,l) += f[k]*f[l]*weight*detjac;
@@ -129,8 +129,8 @@ void dgGroupOfFaces::addFace(const MFace &topoFace, int iElLeft, int iElRight){
   _closuresLeft.push_back(&(_fsLeft->getFaceClosure(ithFace, sign, rot)));
   const std::vector<int> & geomClosure = elLeft.getFunctionSpace()->getFaceClosure(ithFace, sign, rot);
   if(iElRight>=0){
-    MElement &elRight = *_groupRight.getElement(iElRight);
     _right.push_back(iElRight);
+    MElement &elRight = *_groupRight.getElement(iElRight);
     elRight.getFaceInfo (topoFace, ithFace, sign, rot);
     _closuresRight.push_back(&(_fsRight->getFaceClosure(ithFace, sign, rot)));        
   }
@@ -185,6 +185,21 @@ void dgGroupOfFaces::addEdge(const MEdge &topoEdge, int iElLeft, int iElRight){
   }
 }
 
+void dgGroupOfFaces::addVertex(MVertex *topoVertex, int iElLeft, int iElRight){
+  _left.push_back(iElLeft);
+  MElement &elLeft = *_groupLeft.getElement(iElLeft);
+  int ithVertex;
+  elLeft.getVertexInfo (topoVertex, ithVertex);
+  _closuresLeft.push_back(&_fsLeft->getVertexClosure(ithVertex));
+  if(iElRight>=0){
+    _right.push_back(iElRight);
+    MElement &elRight = *_groupRight.getElement(iElRight);
+    elRight.getVertexInfo (topoVertex, ithVertex);
+    _closuresRight.push_back(&_fsRight->getVertexClosure(ithVertex));
+  }
+  _faces.push_back(new MPoint(topoVertex) );
+}
+
 void dgGroupOfFaces::init(int pOrder) {
   _fsFace = _faces[0]->getFunctionSpace (pOrder);
   _integration = dgGetIntegrationRule (_faces[0],pOrder);
@@ -283,6 +298,26 @@ dgGroupOfFaces::~dgGroupOfFaces()
   delete _dPsiLeftDxOnQP;
   delete _dPsiRightDxOnQP;
 }
+
+dgGroupOfFaces::dgGroupOfFaces (const dgGroupOfElements &elGroup, std::string boundaryTag, int pOrder,std::set<MVertex*> &boundaryVertices):
+  _groupLeft(elGroup),_groupRight(elGroup)
+{
+  _boundaryTag=boundaryTag;
+  if(boundaryTag=="")
+    throw;
+  _fsLeft=_groupLeft.getElement(0)->getFunctionSpace(pOrder);
+  _fsRight=NULL;
+  for(int i=0; i<elGroup.getNbElements(); i++){
+    MElement &el = *elGroup.getElement(i);
+    for (int j=0; j<el.getNumVertices(); j++){
+      MVertex* vertex = el.getVertex(j);
+      if(boundaryVertices.find(vertex)!=boundaryVertices.end())
+        addVertex(vertex,i,-1);
+    }
+  }
+  init(pOrder);
+}
+
 dgGroupOfFaces::dgGroupOfFaces (const dgGroupOfElements &elGroup, std::string boundaryTag, int pOrder,std::set<MEdge,Less_Edge> &boundaryEdges):
   _groupLeft(elGroup),_groupRight(elGroup)
 {
@@ -301,6 +336,7 @@ dgGroupOfFaces::dgGroupOfFaces (const dgGroupOfElements &elGroup, std::string bo
   }
   init(pOrder);
 }
+
 dgGroupOfFaces::dgGroupOfFaces (const dgGroupOfElements &elGroup, std::string boundaryTag, int pOrder,std::set<MFace,Less_Face> &boundaryFaces):
   _groupLeft(elGroup),_groupRight(elGroup)
 {
@@ -326,6 +362,21 @@ dgGroupOfFaces::dgGroupOfFaces (const dgGroupOfElements &elGroup, int pOrder):
   _fsLeft=_groupLeft.getElement(0)->getFunctionSpace(pOrder);
   _fsRight=_groupRight.getElement(0)->getFunctionSpace(pOrder);
   switch (_groupLeft.getElement(0)->getDim()) {
+    case 1 : {
+      std::map<MVertex*,int> vertexMap;
+      for(int i=0; i<elGroup.getNbElements(); i++){
+        MElement &el = *elGroup.getElement(i);
+        for (int j=0; j<el.getNumVertices(); j++){
+          MVertex* vertex = el.getVertex(j);
+          if(vertexMap.find(vertex) == vertexMap.end()){
+            vertexMap[vertex] = i;
+          }else{
+            addVertex(vertex,vertexMap[vertex],i);
+          }
+        }
+      }
+      break;
+    }
     case 2 : {
       std::map<MEdge,int,Less_Edge> edgeMap;
       for(int i=0; i<elGroup.getNbElements(); i++){
diff --git a/Solver/dgGroupOfElements.h b/Solver/dgGroupOfElements.h
index 3482bbb4da..2bd2e554aa 100644
--- a/Solver/dgGroupOfElements.h
+++ b/Solver/dgGroupOfElements.h
@@ -90,6 +90,7 @@ class dgGroupOfFaces {
   const dgGroupOfElements &_groupLeft,&_groupRight;
   void addFace(const MFace &topoFace, int iElLeft, int iElRight);
   void addEdge(const MEdge &topoEdge, int iElLeft, int iElRight);
+  void addVertex(MVertex *topoVertex, int iElLeft, int iElRight);
   // Two polynomialBases for left and right elements
   // the group has always the same types for left and right
   const polynomialBasis *_fsLeft,*_fsRight, *_fsFace;
@@ -132,6 +133,7 @@ public:
   const std::vector<int> * getClosureRight(int iFace) const{ return _closuresRight[iFace];}
   inline fullMatrix<double> &getNormals () const {return *_normals;}
   dgGroupOfFaces (const dgGroupOfElements &elements,int pOrder);
+  dgGroupOfFaces (const dgGroupOfElements &elGroup, std::string boundaryTag, int pOrder,std::set<MVertex*> &boundaryVertices);
   dgGroupOfFaces (const dgGroupOfElements &elGroup, std::string boundaryTag, int pOrder,std::set<MEdge,Less_Edge> &boundaryEdges);
   dgGroupOfFaces (const dgGroupOfElements &elGroup, std::string boundaryTag, int pOrder,std::set<MFace,Less_Face> &boundaryFaces);
   virtual ~dgGroupOfFaces ();
-- 
GitLab