From 9033bad71a61e31997ef14432d47392ea271c740 Mon Sep 17 00:00:00 2001 From: Nicolas Marsic <nicolas.marsic@gmail.com> Date: Thu, 22 Nov 2012 17:25:29 +0000 Subject: [PATCH] Now Lagrange Basis (for Tri) completly in Basis Framework -- Still need a sexy way to choose between Zaglmayr and Lagrange -- Need to put LagrangeBasis::project elsewhere --- FunctionSpace/BasisGenerator.cpp | 69 ++++++++++++++++++------ FunctionSpace/BasisGenerator.h | 82 +++++++++++++++++++++++++---- FunctionSpace/CMakeLists.txt | 5 +- FunctionSpace/FunctionSpace.cpp | 2 +- FunctionSpace/LagrangeBasis.cpp | 39 ++++++++++++++ FunctionSpace/LagrangeBasis.h | 10 ++++ FunctionSpace/LagrangeGenerator.cpp | 22 -------- FunctionSpace/LagrangeGenerator.h | 52 ------------------ FunctionSpace/TriLagrangeBasis.cpp | 81 ++++++++++++++++++++++++---- 9 files changed, 246 insertions(+), 116 deletions(-) delete mode 100644 FunctionSpace/LagrangeGenerator.cpp delete mode 100644 FunctionSpace/LagrangeGenerator.h diff --git a/FunctionSpace/BasisGenerator.cpp b/FunctionSpace/BasisGenerator.cpp index 299201fe79..cfb3efbeb4 100644 --- a/FunctionSpace/BasisGenerator.cpp +++ b/FunctionSpace/BasisGenerator.cpp @@ -12,6 +12,7 @@ #include "TriNodeBasis.h" #include "TriEdgeBasis.h" #include "TriNedelecBasis.h" +#include "TriLagrangeBasis.h" #include "TetNodeBasis.h" #include "TetEdgeBasis.h" @@ -28,21 +29,57 @@ BasisGenerator::~BasisGenerator(void){ Basis* BasisGenerator::generate(int elementType, int basisType, - int order){ + int order, + std::string family){ + + if(!family.compare(std::string("zaglmayr"))) + return generateZaglmayr(elementType, basisType, order); + + else if(!family.compare(std::string("lagrange"))) + return generateLagrange(elementType, basisType, order); + + else + throw Exception("Unknwown Basis Family: %s", family.c_str()); +} + +Basis* BasisGenerator::generateZaglmayr(int elementType, + int basisType, + int order){ + + switch(elementType){ + case TYPE_LIN: return linZaglmayrGen(basisType, order); + case TYPE_TRI: return triZaglmayrGen(basisType, order); + case TYPE_QUA: return quaZaglmayrGen(basisType, order); + case TYPE_TET: return tetZaglmayrGen(basisType, order); + case TYPE_HEX: return hexZaglmayrGen(basisType, order); + + default: throw Exception("Unknown Element Type (%d) for Basis Generation", + elementType); + } +} + +Basis* BasisGenerator::generateLagrange(int elementType, + int basisType, + int order){ + if(basisType != 0) + throw + Exception("Cannot Have a %d-Form Lagrange Basis (0-Form only)", + basisType); + switch(elementType){ - case TYPE_LIN: return linGen(basisType, order); - case TYPE_TRI: return triGen(basisType, order); - case TYPE_QUA: return quaGen(basisType, order); - case TYPE_TET: return tetGen(basisType, order); - case TYPE_HEX: return hexGen(basisType, order); + case TYPE_LIN: throw Exception("Lagrange Basis on Lines not Implemented"); + case TYPE_TRI: return new TriLagrangeBasis(order); + case TYPE_QUA: throw Exception("Lagrange Basis on Quads not Implemented"); + case TYPE_TET: throw Exception("Lagrange Basis on Tets not Implemented"); + case TYPE_HEX: throw Exception("Lagrange Basis on Hexs not Implemented"); default: throw Exception("Unknown Element Type (%d) for Basis Generation", elementType); } } -Basis* BasisGenerator::linGen(int basisType, - int order){ +Basis* BasisGenerator::linZaglmayrGen(int basisType, + int order){ switch(basisType){ case 0: return new LineNodeBasis(order); case 1: @@ -56,8 +93,8 @@ Basis* BasisGenerator::linGen(int basisType, } } -Basis* BasisGenerator::triGen(int basisType, - int order){ +Basis* BasisGenerator::triZaglmayrGen(int basisType, + int order){ switch(basisType){ case 0: return new TriNodeBasis(order); case 1: @@ -71,8 +108,8 @@ Basis* BasisGenerator::triGen(int basisType, } } -Basis* BasisGenerator::quaGen(int basisType, - int order){ +Basis* BasisGenerator::quaZaglmayrGen(int basisType, + int order){ switch(basisType){ case 0: return new QuadNodeBasis(order); case 1: return new QuadEdgeBasis(order); @@ -83,8 +120,8 @@ Basis* BasisGenerator::quaGen(int basisType, } } -Basis* BasisGenerator::tetGen(int basisType, - int order){ +Basis* BasisGenerator::tetZaglmayrGen(int basisType, + int order){ switch(basisType){ case 0: return new TetNodeBasis(order); case 1: return new TetEdgeBasis(order); @@ -95,8 +132,8 @@ Basis* BasisGenerator::tetGen(int basisType, } } -Basis* BasisGenerator::hexGen(int basisType, - int order){ +Basis* BasisGenerator::hexZaglmayrGen(int basisType, + int order){ switch(basisType){ case 0: return new HexNodeBasis(order); case 1: return new HexEdgeBasis(order); diff --git a/FunctionSpace/BasisGenerator.h b/FunctionSpace/BasisGenerator.h index 1f071ea3bc..6d3351c319 100644 --- a/FunctionSpace/BasisGenerator.h +++ b/FunctionSpace/BasisGenerator.h @@ -1,6 +1,7 @@ #ifndef _BASISGENERATOR_H_ #define _BASISGENERATOR_H_ +#include <string> #include "Basis.h" /** @@ -20,15 +21,29 @@ class BasisGenerator{ BasisGenerator(void); ~BasisGenerator(void); + static Basis* generate(int elementType, + int basisType, + int order, + std::string family); + static Basis* generate(int elementType, int basisType, int order); - static Basis* linGen(int basisType, int order); - static Basis* triGen(int basisType, int order); - static Basis* quaGen(int basisType, int order); - static Basis* tetGen(int basisType, int order); - static Basis* hexGen(int basisType, int order); + static Basis* linZaglmayrGen(int basisType, int order); + static Basis* triZaglmayrGen(int basisType, int order); + static Basis* quaZaglmayrGen(int basisType, int order); + static Basis* tetZaglmayrGen(int basisType, int order); + static Basis* hexZaglmayrGen(int basisType, int order); + + private: + static Basis* generateZaglmayr(int elementType, + int basisType, + int order); + + static Basis* generateLagrange(int elementType, + int basisType, + int order); }; @@ -50,8 +65,10 @@ class BasisGenerator{ on which the requested Basis will be created @param basisType The Basis type @param order The order or the requested Basis + @param family A string - This method will @em instanciate the requested Basis + This method will @em instanciate the requested Basis, + of the requested family @return Returns a @em pointer to a newly @em instantiated Basis @@ -68,9 +85,28 @@ class BasisGenerator{ @li @c 1 for 1-Form @li @c 2 for 2-Form @li @c 3 for 3-Form + + @note Families are: + @li @c zaglmayr for + <a href="http://www.hpfem.jku.at/publications/szthesis.pdf">Zaglmayr's</a> + Basis Functions + @li @c lagrange for Lagrange's Basis Functions + ** + + @fn BasisGenerator::generate + @param elementType The type of the element, + on which the requested Basis will be created + @param basisType The Basis type + @param order The order or the requested Basis + + Same as + BasisGenerator::generate(@c elementType, @c basisType, @c order, @c zaglmayr) + + @return Returns a @em pointer to a newly + @em instantiated Basis ** - @fn BasisGenerator::linGen + @fn BasisGenerator::linZaglmayrGen @param basisType The Basis type @param order The order or the requested Basis @@ -85,9 +121,11 @@ class BasisGenerator{ @li @c 1 for 1-Form @li @c 2 for 2-Form @li @c 3 for 3-Form + + @note The Basis family will be @c zaglmayr ** - @fn BasisGenerator::triGen + @fn BasisGenerator::triZaglmayrGen @param basisType The Basis type @param order The order or the requested Basis @@ -102,9 +140,11 @@ class BasisGenerator{ @li @c 1 for 1-Form @li @c 2 for 2-Form @li @c 3 for 3-Form + + @note The Basis family will be @c zaglmayr ** - @fn BasisGenerator::quaGen + @fn BasisGenerator::quaZaglmayrGen @param basisType The Basis type @param order The order or the requested Basis @@ -119,9 +159,11 @@ class BasisGenerator{ @li @c 1 for 1-Form @li @c 2 for 2-Form @li @c 3 for 3-Form + + @note The Basis family will be @c zaglmayr ** - @fn BasisGenerator::tetGen + @fn BasisGenerator::tetZaglmayrGen @param basisType The Basis type @param order The order or the requested Basis @@ -136,9 +178,11 @@ class BasisGenerator{ @li @c 1 for 1-Form @li @c 2 for 2-Form @li @c 3 for 3-Form + + @note The Basis family will be @c zaglmayr ** - @fn BasisGenerator::hexGen + @fn BasisGenerator::hexZaglmayrGen @param basisType The Basis type @param order The order or the requested Basis @@ -153,7 +197,23 @@ class BasisGenerator{ @li @c 1 for 1-Form @li @c 2 for 2-Form @li @c 3 for 3-Form + + @note The Basis family will be @c zaglmayr ** */ +////////////////////// +// Inline Functions // +////////////////////// + +inline Basis* BasisGenerator::generate(int elementType, + int basisType, + int order){ + + return BasisGenerator::generate(elementType, + basisType, + order, + "zaglmayr"); +} + #endif diff --git a/FunctionSpace/CMakeLists.txt b/FunctionSpace/CMakeLists.txt index d02168cc8d..a6c7d63d7c 100644 --- a/FunctionSpace/CMakeLists.txt +++ b/FunctionSpace/CMakeLists.txt @@ -8,6 +8,7 @@ set(SRC Legendre.cpp Basis.cpp + LagrangeBasis.cpp BasisScalar.cpp BasisVector.cpp BasisGenerator.cpp @@ -16,9 +17,6 @@ set(SRC CurlBasis.cpp DivBasis.cpp - LagrangeGenerator.cpp - LagrangeBasis.cpp - TriLagrangeBasis.cpp LineNodeBasis.cpp LineEdgeBasis.cpp @@ -30,6 +28,7 @@ set(SRC TriNodeBasis.cpp TriEdgeBasis.cpp TriNedelecBasis.cpp + TriLagrangeBasis.cpp HexNodeBasis.cpp HexEdgeBasis.cpp diff --git a/FunctionSpace/FunctionSpace.cpp b/FunctionSpace/FunctionSpace.cpp index 9c973bc2af..93cea8990b 100644 --- a/FunctionSpace/FunctionSpace.cpp +++ b/FunctionSpace/FunctionSpace.cpp @@ -60,7 +60,7 @@ void FunctionSpace::build(const GroupOfElement& goe, type = basisType; basis = BasisGenerator::generate(elementType, basisType, - order); + order, "lagrange"); // Number of *Per* Entity functions // fPerVertex = basis->getNVertexBased() / nVertex; diff --git a/FunctionSpace/LagrangeBasis.cpp b/FunctionSpace/LagrangeBasis.cpp index 9402df5f4c..4336a6ca16 100644 --- a/FunctionSpace/LagrangeBasis.cpp +++ b/FunctionSpace/LagrangeBasis.cpp @@ -58,3 +58,42 @@ project(const MElement& element, // Return ; return newCoef; } + +unsigned int** LagrangeBasis::triEdgeOrder(int order){ + // Check // + if(order <= 1) + return NULL; + + // Number of Edge Based Basis // + const unsigned int orderMinus = order - 1; + const unsigned int size = 3 * orderMinus; + + // Alloc // + unsigned int i; + unsigned int** edgeOrder = new unsigned int*[2]; + edgeOrder[0] = new unsigned int[size]; + edgeOrder[1] = new unsigned int[size]; + + // Direct Numeration // + i = 0; + + for(unsigned int j = 0; j < orderMinus; j++){ + for(unsigned int k = 0; k < size; k += orderMinus){ + edgeOrder[0][i] = k + j; + i++; + } + } + + // Invert Numeration // + i = 0; + + for(unsigned int j = 0; j < orderMinus; j++){ + for(unsigned int k = 0; k < size; k += orderMinus){ + edgeOrder[1][i] = k + orderMinus - 1 - j; + i++; + } + } + + // Retrun // + return edgeOrder; +} diff --git a/FunctionSpace/LagrangeBasis.h b/FunctionSpace/LagrangeBasis.h index 0d990a576f..940040348b 100644 --- a/FunctionSpace/LagrangeBasis.h +++ b/FunctionSpace/LagrangeBasis.h @@ -67,6 +67,16 @@ class LagrangeBasis: public BasisScalar{ //! Returns a new LagrangeBasis //! LagrangeBasis(void); + + //! @param order The ordre of the requested LagrangeBasis + //! @return Returns a 2D table + //! (of size 2 x (3 * (@c order - 1))) + //! with the Edge Triangle Inverted Closure for Lagrange + //! @note The first dimension of the returned table + //! is the direct closure, and the second dimension + //! the invert closure + //! @warning The returned table @em must be @em deleted + static unsigned int** triEdgeOrder(int order); }; diff --git a/FunctionSpace/LagrangeGenerator.cpp b/FunctionSpace/LagrangeGenerator.cpp deleted file mode 100644 index 99c8f0c960..0000000000 --- a/FunctionSpace/LagrangeGenerator.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "Exception.h" -#include "TriLagrangeBasis.h" -#include "LagrangeGenerator.h" - -LagrangeGenerator::LagrangeGenerator(void){ -} - -LagrangeGenerator::~LagrangeGenerator(void){ -} - -LagrangeBasis* LagrangeGenerator::generate(unsigned int elementType, - unsigned int lagrangeOrder){ - switch(elementType){ - case TYPE_TRI: return new TriLagrangeBasis(lagrangeOrder); - case TYPE_QUA: throw Exception("Lagrange Basis on Quads not Implemented"); - case TYPE_TET: throw Exception("Lagrange Basis on Tets not Implemented"); - case TYPE_HEX: throw Exception("Lagrange Basis on Hexs not Implemented"); - - default: throw Exception("Unknown Element Type (%d) for Lagrange Basis", - elementType); - } -} diff --git a/FunctionSpace/LagrangeGenerator.h b/FunctionSpace/LagrangeGenerator.h deleted file mode 100644 index 233d3d76da..0000000000 --- a/FunctionSpace/LagrangeGenerator.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _LAGRANGEGENERATOR_H_ -#define _LAGRANGEGENERATOR_H_ - -#include "LagrangeBasis.h" - -/** - @class LagrangeGenerator - @brief Generates a Lagrange Basis - - Generates a Lagrange Basis - */ - -class LagrangeGenerator{ - public: - LagrangeGenerator(void); - ~LagrangeGenerator(void); - - static LagrangeBasis* generate(unsigned int elementType, - unsigned int lagrangeOrder); -}; - -/** - @fn LagrangeGenerator::LagrangeGenerator - Instantiates a new LagrangeGenerator - - @note - A LagrangeGenerator got @em only @em class @em methods, - so it is not required to instanciate it. - ** - - @fn LagrangeGenerator::~LagrangeGenerator - Deletes this LagrangeGenerator - ** - - @fn LagrangeGenerator::generate - @param elementType The type of the element, - on which the requested LagrangeBasis will be created - @param lagrangeOrder The order or the requested LagrangeBasis - - This method will @em instanciate the requested LagrangeBasis - - @return Returns a @em pointer to a newly - @em instantiated LagrangeBasis - - @note Element types are: - @li @c TYPE_TRI for Triangles - @li @c TYPE_QUA for Quadrangles - @li @c TYPE_TET for Tetrahedrons - @li @c TYPE_HEX for Hexahedrons -*/ - -#endif diff --git a/FunctionSpace/TriLagrangeBasis.cpp b/FunctionSpace/TriLagrangeBasis.cpp index 99f8a6d7ca..093647adc9 100644 --- a/FunctionSpace/TriLagrangeBasis.cpp +++ b/FunctionSpace/TriLagrangeBasis.cpp @@ -66,27 +66,34 @@ TriLagrangeBasis::TriLagrangeBasis(int order){ type = 0; dim = 2; - nVertex = l->coefficients.size1(); - nEdge = 0; + nVertex = 3; + nEdge = 3 * (order - 1); nFace = 0; - nCell = 0; + nCell = (order - 1) * (order - 2) / 2; - nEdgeClosure = 0; + nEdgeClosure = 2; nFaceClosure = 0; - size = nVertex; - + size = nVertex + nEdge + nFace + nCell; + + + // Alloc Some Stuff // + const int nMonomial = l->monomials.size1(); + unsigned int** edgeOrder; + Polynomial* pEdgeClosureLess = new Polynomial[nEdge]; - // Basis (pure nodal) // + + // Basis // node = new vector<Polynomial*>(nVertex); - edge = new vector<vector<Polynomial*>*>(0); + edge = new vector<vector<Polynomial*>*>(2); face = new vector<vector<Polynomial*>*>(0); - cell = new vector<Polynomial*>(0); + cell = new vector<Polynomial*>(nCell); + (*edge)[0] = new vector<Polynomial*>(nEdge); + (*edge)[1] = new vector<Polynomial*>(nEdge); - // Instanciate Polynomials // - const int nMonomial = l->monomials.size1(); + // Vertex Based // for(int i = 0; i < nVertex; i++){ Polynomial p = Polynomial(0, 0, 0, 0); @@ -98,6 +105,58 @@ TriLagrangeBasis::TriLagrangeBasis(int order){ (*node)[i] = new Polynomial(p); } + + + // Edge Based // + // Without Closure + for(int i = 0; i < nEdge; i++){ + int ci = i + nVertex; + pEdgeClosureLess[i] = Polynomial(0, 0, 0, 0); + + for(int j = 0; j < nMonomial; j++) + pEdgeClosureLess[i] = + pEdgeClosureLess[i] + + Polynomial(l->coefficients(ci, j), // Coef + l->monomials(j, 0), // powerX + l->monomials(j, 1), // powerY + 0); // powerZ + } + + // With Closure + edgeOrder = triEdgeOrder(order); // Closure Ordering + + for(int i = 0; i < nEdge; i++){ + (*(*edge)[0])[i] = + new Polynomial(pEdgeClosureLess[edgeOrder[0][i]]); + + (*(*edge)[1])[i] = + new Polynomial(pEdgeClosureLess[edgeOrder[1][i]]); + } + + + // Cell Based // + for(int i = 0; i < nCell; i++){ + int ci = i + nVertex + nEdge; + Polynomial p = Polynomial(0, 0, 0, 0); + + for(int j = 0; j < nMonomial; j++) + p = p + Polynomial(l->coefficients(ci, j), // Coef + l->monomials(j, 0), // powerX + l->monomials(j, 1), // powerY + 0); // powerZ + + (*cell)[i] = new Polynomial(p); + } + + + // Delete Temporary Space // + delete[] pEdgeClosureLess; + + if(edgeOrder){ + delete[] edgeOrder[0]; + delete[] edgeOrder[1]; + delete[] edgeOrder; + } } TriLagrangeBasis::~TriLagrangeBasis(void){ -- GitLab