From 29db91e265361b88f04c1283f4aca32e3d84ea72 Mon Sep 17 00:00:00 2001
From: Nicolas Marsic <nicolas.marsic@gmail.com>
Date: Wed, 17 Oct 2012 15:27:27 +0000
Subject: [PATCH] Nodal Element on Tet (with closure for Edges and Faces) --
 Local Functions closure for Edges on the fly (no more orientation map) --
 Still need Local Functions closure for Faces on the fly AND Face based Dof

---
 FunctionSpace/CMakeLists.txt          |   3 +-
 FunctionSpace/FunctionSpace.cpp       |   5 +-
 FunctionSpace/FunctionSpaceScalar.cpp |  74 +++++---
 FunctionSpace/HexNodeBasis.cpp        |  12 +-
 FunctionSpace/TetNodeBasis.cpp        | 245 ++++++++++++++++++++++++++
 FunctionSpace/TetNodeBasis.h          |  30 ++++
 6 files changed, 331 insertions(+), 38 deletions(-)
 create mode 100644 FunctionSpace/TetNodeBasis.cpp
 create mode 100644 FunctionSpace/TetNodeBasis.h

diff --git a/FunctionSpace/CMakeLists.txt b/FunctionSpace/CMakeLists.txt
index b31dd7a1b5..a1c28aa15b 100644
--- a/FunctionSpace/CMakeLists.txt
+++ b/FunctionSpace/CMakeLists.txt
@@ -19,7 +19,8 @@ set(SRC
   TriNedelecBasis.cpp
   HexNodeBasis.cpp
   HexEdgeBasis.cpp
-
+  TetNodeBasis.cpp
+  
   FunctionSpace.cpp
   FunctionSpaceScalar.cpp
   FunctionSpaceVector.cpp
diff --git a/FunctionSpace/FunctionSpace.cpp b/FunctionSpace/FunctionSpace.cpp
index 7cffb23b0d..b94195a6ce 100644
--- a/FunctionSpace/FunctionSpace.cpp
+++ b/FunctionSpace/FunctionSpace.cpp
@@ -17,6 +17,7 @@ FunctionSpace::~FunctionSpace(void){
   delete basis;
 
   // Closure //
+  /*
   map<const MElement*, vector<bool>*>::iterator cIt 
     = edgeClosure->begin();
   map<const MElement*, vector<bool>*>::iterator cStop 
@@ -25,7 +26,7 @@ FunctionSpace::~FunctionSpace(void){
   for(; cIt != cStop; cIt++)
     delete cIt->second;
   delete edgeClosure;
-
+  */
   // Dof //
   if(dof){
     set<const Dof*>::iterator dStop = dof->end();
@@ -89,7 +90,7 @@ void FunctionSpace::build(const GroupOfElement& goe,
   fPerCell = basis->getNCellBased(); // We always got 1 cell 
 
   // Build Closure //
-  buildClosure();
+  //buildClosure();
 
   // Build Dof //
   buildDof();
diff --git a/FunctionSpace/FunctionSpaceScalar.cpp b/FunctionSpace/FunctionSpaceScalar.cpp
index e5b7887f7c..677267d5ac 100644
--- a/FunctionSpace/FunctionSpaceScalar.cpp
+++ b/FunctionSpace/FunctionSpaceScalar.cpp
@@ -8,52 +8,68 @@ FunctionSpaceScalar::~FunctionSpaceScalar(void){
 
 const vector<const Polynomial*> FunctionSpaceScalar::
 getLocalFunctions(const MElement& element) const{
+  
+  // Get Basis //
+  const BasisScalar&                        basis = getBasis(element);
+  const vector       <const Polynomial*>&   node  = basis.getNodeFunctions();
+  const vector<vector<const Polynomial*>*>& edge  = basis.getEdgeFunctions();
+  const vector       <const Polynomial*>&   cell  = basis.getCellFunctions();
 
-  // Get Closure //
-  map<const MElement*, vector<bool>*>::iterator it = 
-    edgeClosure->find(&element);
+  const unsigned int nFNode = basis.getNVertexBased();
+  const unsigned int nFEdge = basis.getNEdgeBased();
+  const unsigned int nFCell = basis.getNCellBased();
 
-  if(it == edgeClosure->end())
-    throw Exception("Element not found for closure");
 
-  vector<bool>* closure   = it->second;
+  // Get Edge Closure //
+  MElement&          eelement = const_cast<MElement&>(element);
+  const unsigned int nEdge    = eelement.getNumEdges();
+  
+  vector<bool> edgeClosure(nEdge);
+  
+  // Look Edges 
+  for(unsigned int i = 0; i < nEdge; i++){
+    MEdge edge     = eelement.getEdge(i);
+    edgeClosure[i] = 
+      edge.getVertex(0)->getNum() > edge.getVertex(1)->getNum();
+  }
 
-  // Get Basis //
-  const vector       <const Polynomial*>&   node = getBasis(element).getNodeFunctions();
-  const vector<vector<const Polynomial*>*>& edge = getBasis(element).getEdgeFunctions();
-  const vector       <const Polynomial*>&   cell = getBasis(element).getCellFunctions();
 
   // Get Functions //
-  unsigned int i           = 0;
-  const unsigned int nNode = node.size();
-  const unsigned int nEdge = edge[0]->size();
-  const unsigned int nCell = cell.size();
-
-  vector<const Polynomial*> fun(getBasis(element).getSize());
+  vector<const Polynomial*> fun(basis.getSize());
+  unsigned int i = 0;
   
-  // Vertex Based //
-  for(unsigned int j = 0; j < nNode; j++){
+  // Vertex Based
+  for(unsigned int j = 0; j < nFNode; j++){
     fun[i] = node[j];
     i++;
   }
 
-  // Edge Based //
-  for(unsigned int j = 0; j < nEdge; j++){
-    if((*closure)[i])
-      fun[i] = (*edge[0])[j];
-
-    else
-      fun[i] = (*edge[1])[j];
+  // Edge Based
+  // Number of basis function *per* edge
+  //  --> should always be an integer !
+  const unsigned int nFPerEdge = nFEdge / nEdge;
+  unsigned int fEdge = 0;
 
-    i++;
+  for(unsigned int j = 0; j < nFPerEdge; j++){
+    for(unsigned int k = 0; k < nEdge; k++){
+      if(edgeClosure[k])
+	fun[i] = (*edge[0])[fEdge];
+      
+      else
+	fun[i] = (*edge[1])[fEdge];
+      
+      fEdge++;
+      i++;
+    }
   }
 
-  // Vertex Based //
-  for(unsigned int j = 0; j < nCell; j++){
+  // Vertex Based
+  for(unsigned int j = 0; j < nFCell; j++){
     fun[i] = cell[j];
     i++;
   }
 
-  // Return 
+
+  // Return //
   return fun;
 }
diff --git a/FunctionSpace/HexNodeBasis.cpp b/FunctionSpace/HexNodeBasis.cpp
index fef2ee1cf4..922d33ba38 100644
--- a/FunctionSpace/HexNodeBasis.cpp
+++ b/FunctionSpace/HexNodeBasis.cpp
@@ -119,8 +119,8 @@ HexNodeBasis::HexNodeBasis(const int order){
   int i = 8;
 
   // Points definig Edges
-  int edge1[12] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3};
-  int edge2[12] = {1, 2, 3, 0, 5, 6, 7, 4, 4, 5, 6, 7};
+  const unsigned int edge1[12] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3};
+  const unsigned int edge2[12] = {1, 2, 3, 0, 5, 6, 7, 4, 4, 5, 6, 7};
 
   for(int l = 1; l < order; l++){
     for(int e = 0; e < 12; e++){
@@ -135,10 +135,10 @@ HexNodeBasis::HexNodeBasis(const int order){
   
   // Face Based (Preliminary) //
   // Points definig Faces
-  int face1[6] = {0, 3, 2, 1, 5, 4};
-  int face2[6] = {1, 7, 6, 0, 6, 7};
-  int face3[6] = {2, 6, 5, 4, 7, 3};
-  int face4[6] = {3, 2, 1, 5, 4, 0};
+  const unsigned int face1[6] = {0, 3, 2, 1, 5, 4};
+  const unsigned int face2[6] = {1, 7, 6, 0, 6, 7};
+  const unsigned int face3[6] = {2, 6, 5, 4, 7, 3};
+  const unsigned int face4[6] = {3, 2, 1, 5, 4, 0};
 
   // 'Xi' Functions
   for(int f = 0; f < 6; f++)
diff --git a/FunctionSpace/TetNodeBasis.cpp b/FunctionSpace/TetNodeBasis.cpp
new file mode 100644
index 0000000000..05770e8280
--- /dev/null
+++ b/FunctionSpace/TetNodeBasis.cpp
@@ -0,0 +1,245 @@
+#include "TetNodeBasis.h"
+#include "Legendre.h"
+
+using namespace std;
+
+TetNodeBasis::TetNodeBasis(unsigned int order){
+  // Set Basis Type //
+  this->order = order;
+  
+  type = 0;
+  dim  = 3;
+
+  nVertex = 4;
+  nEdge   = 6 * (order - 1);
+  nFace   = 2 * (order - 1) * (order - 2);
+  nCell   =     (order - 1) * (order - 2) * (order - 3) / 6;
+
+  size    = nVertex + nEdge + nFace + nCell;
+
+  // Alloc Temporary Space //
+  Polynomial* legendre     = new Polynomial[order];
+  Polynomial* sclLegendre  = new Polynomial[order];
+  Polynomial* intLegendre  = new Polynomial[order];
+
+  // Classical, Scaled and Intrated-Scaled Legendre Polynomial //
+  const unsigned int orderMinus      = order - 1;
+  const unsigned int orderMinusTwo   = order - 2;
+  const unsigned int orderMinusThree = order - 3;
+
+  Legendre::legendre(legendre, orderMinus);
+  Legendre::scaled(sclLegendre, orderMinus);
+  Legendre::intScaled(intLegendre, order);
+
+  // Points definig Edges //
+  const unsigned int edge0[6] = {0, 1, 2, 2, 3, 3};
+  const unsigned int edge1[6] = {1, 2, 0, 3, 0, 1};
+
+  // Points definig Faces //
+  const unsigned int face0[4] = {0, 0, 0, 1};
+  const unsigned int face1[4] = {1, 1, 2, 2};
+  const unsigned int face2[4] = {3, 2, 3, 3};
+
+  // Counter //
+  unsigned int i;
+
+  // Basis //
+  node = new vector<const Polynomial*>(nVertex);
+  edge = new vector<vector<const Polynomial*>*>(2);
+  face = new vector<vector<const Polynomial*>*>(6);
+  cell = new vector<const Polynomial*>(nCell);
+
+  (*edge)[0] = new vector<const Polynomial*>(nEdge);
+  (*edge)[1] = new vector<const Polynomial*>(nEdge);
+
+  (*face)[0] = new vector<const Polynomial*>(nFace);
+  (*face)[1] = new vector<const Polynomial*>(nFace);
+  (*face)[2] = new vector<const Polynomial*>(nFace);
+  (*face)[3] = new vector<const Polynomial*>(nFace);
+  (*face)[4] = new vector<const Polynomial*>(nFace);
+  (*face)[5] = new vector<const Polynomial*>(nFace);
+
+
+  // Vertex Based (Lagrange) //
+  (*node)[0] = 
+    new Polynomial(Polynomial(1, 0, 0, 0) - 
+		   Polynomial(1, 1, 0, 0) - 
+		   Polynomial(1, 0, 1, 0) - 
+		   Polynomial(1, 0, 0, 1));
+
+  (*node)[1] = 
+    new Polynomial(Polynomial(1, 1, 0, 0));
+
+  (*node)[2] = 
+    new Polynomial(Polynomial(1, 0, 1, 0));
+
+  (*node)[3] = 
+    new Polynomial(Polynomial(1, 0, 0, 1));
+
+ 
+  // Edge Based //
+  i = 0;
+
+  for(unsigned int l = 1; l < order; l++){
+    for(unsigned int e = 0; e < 6; e++){
+      (*(*edge)[0])[i] = 
+	new Polynomial(intLegendre[l].compose
+		       (*(*node)[edge0[e]] - *(*node)[edge1[e]], 
+			*(*node)[edge0[e]] + *(*node)[edge1[e]]));
+
+      (*(*edge)[1])[i] = 
+	new Polynomial(intLegendre[l].compose
+		       (*(*node)[edge1[e]] - *(*node)[edge0[e]], 
+			*(*node)[edge1[e]] + *(*node)[edge0[e]]));      
+      
+      i++;
+    }
+  }
+
+
+  // Face Based //
+  i = 0;
+
+  for(unsigned int l1 = 1; l1 < orderMinus; l1++){
+    for(unsigned int l2 = 0; l1 + l2 - 1 < orderMinusTwo; l2++){
+      for(unsigned int m = 0; m < 4; m++){
+	Polynomial sum = 
+	  *(*node)[face0[m]] + 
+	  *(*node)[face1[m]] + 
+	  *(*node)[face2[m]];	  
+
+	(*(*face)[0])[i] = 
+	  new Polynomial(intLegendre[l1].compose
+			 (*(*node)[face0[m]] - *(*node)[face1[m]], 
+			  *(*node)[face0[m]] + *(*node)[face1[m]]) * 
+			 
+			 *(*node)[face2[m]] * 
+			 
+			 sclLegendre[l2].compose
+			 (*(*node)[face2[m]] * 2 - sum, sum));
+
+	(*(*face)[1])[i] = 
+	  new Polynomial(intLegendre[l1].compose
+			 (*(*node)[face1[m]] - *(*node)[face0[m]], 
+			  *(*node)[face1[m]] + *(*node)[face0[m]]) * 
+			 
+			 *(*node)[face2[m]] * 
+			 
+			 sclLegendre[l2].compose
+			 (*(*node)[face2[m]] * 2 - sum, sum));
+
+	(*(*face)[2])[i] = 
+	  new Polynomial(intLegendre[l1].compose
+			 (*(*node)[face1[m]] - *(*node)[face2[m]], 
+			  *(*node)[face1[m]] + *(*node)[face2[m]]) * 
+			 
+			 *(*node)[face0[m]] * 
+			 
+			 sclLegendre[l2].compose
+			 (*(*node)[face0[m]] * 2 - sum, sum));
+
+	(*(*face)[3])[i] = 
+	  new Polynomial(intLegendre[l1].compose
+			 (*(*node)[face2[m]] - *(*node)[face1[m]], 
+			  *(*node)[face2[m]] + *(*node)[face1[m]]) * 
+			 
+			 *(*node)[face0[m]] * 
+			 
+			 sclLegendre[l2].compose
+			 (*(*node)[face0[m]] * 2 - sum, sum));
+
+	(*(*face)[4])[i] = 
+	  new Polynomial(intLegendre[l1].compose
+			 (*(*node)[face2[m]] - *(*node)[face0[m]], 
+			  *(*node)[face2[m]] + *(*node)[face0[m]]) * 
+			 
+			 *(*node)[face1[m]] * 
+			 
+			 sclLegendre[l2].compose
+			 (*(*node)[face1[m]] * 2 - sum, sum));
+
+	(*(*face)[5])[i] = 
+	  new Polynomial(intLegendre[l1].compose
+			 (*(*node)[face0[m]] - *(*node)[face2[m]], 
+			  *(*node)[face0[m]] + *(*node)[face2[m]]) * 
+			 
+			 *(*node)[face1[m]] * 
+			 
+			 sclLegendre[l2].compose
+			 (*(*node)[face1[m]] * 2 - sum, sum));
+
+	i++;
+      }
+    }
+  }
+  
+
+  // Cell Based //
+  Polynomial oneMinusFour         = Polynomial(1, 0, 0, 0) - *(*node)[3];
+  Polynomial twoThreeOneMinusFour = *(*node)[2] * 2 - oneMinusFour;
+  Polynomial twoFourMinusOne      = *(*node)[3] * 2 - Polynomial(1, 0, 0, 0);
+
+  Polynomial sub = *(*node)[0] - *(*node)[1];
+  Polynomial add = *(*node)[0] + *(*node)[1];
+
+  i = 0;
+  
+  for(unsigned int l1 = 1; l1 < orderMinusTwo; l1++){
+    for(unsigned int l2 = 0; l2 + l1 - 1 < orderMinusThree; l2++){
+      for(unsigned int l3 = 0; l3 + l2 + l1 - 1 < orderMinusThree; l3++){
+	
+	(*cell)[i] = 
+	  new Polynomial(intLegendre[l1].compose(sub, add)             * 
+			 *(*node)[2]                                   * 		 
+			 sclLegendre[l2].compose(twoThreeOneMinusFour, 
+						 oneMinusFour)         *
+			 *(*node)[3]                                   *
+			 legendre[l3].compose(twoFourMinusOne));
+	
+	i++;
+      }
+    }
+  }
+  
+  // Free Temporary Sapce //
+  delete[] legendre;
+  delete[] sclLegendre;
+  delete[] intLegendre;
+}
+
+TetNodeBasis::~TetNodeBasis(void){
+  // Vertex Based //
+  for(int i = 0; i < nVertex; i++)
+    delete (*node)[i];
+  
+  delete node;
+
+
+  // Edge Based //
+  for(int c = 0; c < 2; c++){
+    for(int i = 0; i < nEdge; i++)
+      delete (*(*edge)[c])[i];
+    
+    delete (*edge)[c];
+  }
+  
+  delete edge;
+
+
+  // Face Based //
+  for(int c = 0; c < 6; c++){
+    for(int i = 0; i < nFace; i++)
+      delete (*(*face)[c])[i];
+    
+    delete (*face)[c];
+  }
+
+  delete face;
+
+
+  // Cell Based //
+  for(int i = 0; i < nCell; i++)
+    delete (*cell)[i];
+
+  delete cell;
+}
diff --git a/FunctionSpace/TetNodeBasis.h b/FunctionSpace/TetNodeBasis.h
new file mode 100644
index 0000000000..2083fddf59
--- /dev/null
+++ b/FunctionSpace/TetNodeBasis.h
@@ -0,0 +1,30 @@
+#ifndef _TETNODEBASIS_H_
+#define _TETNODEBASIS_H_
+
+#include "BasisScalar.h"
+
+/**
+   @class TetNodeBasis
+   @brief A Node Basis for Tetrahedrons
+ 
+   This class can instantiate a Node-Based Basis 
+   (high or low order) for Tetrahedrons.@n
+   
+   It uses 
+   <a href="http://www.hpfem.jku.at/publications/szthesis.pdf">Zaglmayr's</a>  
+   Basis for @em high @em order Polynomial%s generation.@n
+ */
+
+class TetNodeBasis: public BasisScalar{
+ public:
+  //! @param order The order of the Basis
+  //!
+  //! Returns a new Node-Basis for Tetrahedrons of the given order
+  TetNodeBasis(unsigned int order);
+  
+  //! Deletes this Basis
+  //!
+  virtual ~TetNodeBasis(void);
+};
+
+#endif
-- 
GitLab