diff --git a/FunctionSpace/TriLagrangeBasis.cpp b/FunctionSpace/TriLagrangeBasis.cpp index 3c96b885ede5df82be23f3e23c42cce89b926b2b..99f8a6d7ca515d617afa68c1b6a82f06deb2e9c7 100644 --- a/FunctionSpace/TriLagrangeBasis.cpp +++ b/FunctionSpace/TriLagrangeBasis.cpp @@ -1,4 +1,4 @@ -#include "polynomialBasis.h" +#include "BasisFactory.h" #include "Exception.h" #include "TriLagrangeBasis.h" @@ -57,7 +57,7 @@ TriLagrangeBasis::TriLagrangeBasis(int order){ break; } - l = polynomialBases::find(tag); + l = (polynomialBasis*)BasisFactory::create(tag); point = new fullMatrix<double>(triPoint(order)); // Set Basis Type // diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp index 1d76cb7a6bad51c1aff08fed0b5c02ceb8d4390f..bdc5c5132e16a4f74b2dde6ae891676cc2072f64 100644 --- a/Geo/MElement.cpp +++ b/Geo/MElement.cpp @@ -112,7 +112,7 @@ void MElement::scaledJacRange(double &jmin, double &jmax) { jmin = jmax = 1.0; #if defined(HAVE_MESH) - if (getType() == TYPE_PYR) return; +// if (getType() == TYPE_PYR) return; extern double mesh_functional_distorsion(MElement*,double,double); if (getPolynomialOrder() == 1) return; const bezierBasis *jac = getJacobianFuncSpace()->bezier; @@ -1416,6 +1416,138 @@ int MElement::ParentTypeFromTag(int tag) } } +// Gives the order corresponding to any element type. +int MElement::OrderFromTag(int tag) +{ + + switch (tag) { + case MSH_PNT : return 0; + case MSH_LIN_1 : return 0; + case MSH_LIN_2 : return 1; + case MSH_LIN_3 : return 2; + case MSH_LIN_4 : return 3; + case MSH_LIN_5 : return 4; + case MSH_LIN_6 : return 5; + case MSH_LIN_7 : return 6; + case MSH_LIN_8 : return 7; + case MSH_LIN_9 : return 8; + case MSH_LIN_10 : return 9; + case MSH_LIN_11 : return 10; + case MSH_TRI_1 : return 0; + case MSH_TRI_3 : return 1; + case MSH_TRI_6 : return 2; + case MSH_TRI_10 : return 3; + case MSH_TRI_15 : return 4; + case MSH_TRI_21 : return 5; + case MSH_TRI_28 : return 6; + case MSH_TRI_36 : return 7; + case MSH_TRI_45 : return 8; + case MSH_TRI_55 : return 9; + case MSH_TRI_66 : return 10; + case MSH_TRI_9 : return 3; + case MSH_TRI_12 : return 4; + case MSH_TRI_15I : return 5; + case MSH_TRI_18 : return 6; + case MSH_TRI_21I : return 7; + case MSH_TRI_24 : return 8; + case MSH_TRI_27 : return 9; + case MSH_TRI_30 : return 10; + case MSH_TET_1 : return 0; + case MSH_TET_4 : return 1; + case MSH_TET_10 : return 2; + case MSH_TET_20 : return 3; + case MSH_TET_35 : return 4; + case MSH_TET_56 : return 5; + case MSH_TET_84 : return 6; + case MSH_TET_120 : return 7; + case MSH_TET_165 : return 8; + case MSH_TET_220 : return 9; + case MSH_TET_286 : return 10; + case MSH_TET_34 : return 4; + case MSH_TET_52 : return 5; + case MSH_TET_74 : return 6; + case MSH_TET_100 : return 7; + case MSH_TET_130 : return 8; + case MSH_TET_164 : return 9; + case MSH_TET_202 : return 10; + case MSH_QUA_1 : return 0; + case MSH_QUA_4 : return 1; + case MSH_QUA_9 : return 2; + case MSH_QUA_16 : return 3; + case MSH_QUA_25 : return 4; + case MSH_QUA_36 : return 5; + case MSH_QUA_49 : return 6; + case MSH_QUA_64 : return 7; + case MSH_QUA_81 : return 8; + case MSH_QUA_100 : return 9; + case MSH_QUA_121 : return 10; + case MSH_QUA_8 : return 2; + case MSH_QUA_12 : return 3; + case MSH_QUA_16I : return 4; + case MSH_QUA_20 : return 5; + case MSH_QUA_24 : return 6; + case MSH_QUA_28 : return 7; + case MSH_QUA_32 : return 8; + case MSH_QUA_36I : return 9; + case MSH_QUA_40 : return 10; + case MSH_PRI_1 : return 0; + case MSH_PRI_6 : return 1; + case MSH_PRI_18 : return 2; + case MSH_PRI_40 : return 3; + case MSH_PRI_75 : return 4; + case MSH_PRI_126 : return 5; + case MSH_PRI_196 : return 6; + case MSH_PRI_288 : return 7; + case MSH_PRI_405 : return 8; + case MSH_PRI_550 : return 9; + case MSH_PRI_15 : return 2; + case MSH_PRI_38 : return 3; + case MSH_PRI_66 : return 4; + case MSH_PRI_102 : return 5; + case MSH_PRI_146 : return 6; + case MSH_PRI_198 : return 7; + case MSH_PRI_258 : return 8; + case MSH_PRI_326 : return 9; + case MSH_HEX_8 : return 1; + case MSH_HEX_27 : return 2; + case MSH_HEX_64 : return 3; + case MSH_HEX_125 : return 4; + case MSH_HEX_216 : return 5; + case MSH_HEX_343 : return 6; + case MSH_HEX_512 : return 7; + case MSH_HEX_729 : return 8; + case MSH_HEX_1000: return 9; + case MSH_HEX_20 : return 2; + case MSH_HEX_56 : return 3; + case MSH_HEX_98 : return 4; + case MSH_HEX_152 : return 5; + case MSH_HEX_222 : return 6; + case MSH_HEX_296 : return 7; + case MSH_HEX_386 : return 8; + case MSH_HEX_488 : return 9; + case MSH_PYR_5 : return 1; + case MSH_PYR_14 : return 2; + case MSH_PYR_30 : return 3; + case MSH_PYR_55 : return 4; + case MSH_PYR_91 : return 5; + case MSH_PYR_140 : return 6; + case MSH_PYR_204 : return 7; + case MSH_PYR_285 : return 8; + case MSH_PYR_385 : return 9; + case MSH_PYR_13 : return 2; + case MSH_PYR_29 : return 3; + case MSH_PYR_50 : return 4; + case MSH_PYR_77 : return 5; + case MSH_PYR_110 : return 6; + case MSH_PYR_149 : return 7; + case MSH_PYR_194 : return 8; + case MSH_PYR_245 : return 9; + default : + Msg::Error("Unknown element type %d: reverting to order 1",tag); + return 1; + } + +} MElement *MElementFactory::create(int type, std::vector<MVertex*> &v, diff --git a/Geo/MElement.h b/Geo/MElement.h index 7abe28e7bbb911cc9e7b3ccb3c503fa9081f2830..9029b64772a471e223c2cb82f842d81f1b9cf73c 100644 --- a/Geo/MElement.h +++ b/Geo/MElement.h @@ -355,6 +355,7 @@ class MElement std::map<MElement*, MElement*> &newDomains); static int ParentTypeFromTag(int tag); + static int OrderFromTag(int tag); }; diff --git a/Geo/MHexahedron.cpp b/Geo/MHexahedron.cpp index 38dbab818806c213a7b42583929e9425158e89c9..b6dc0cedc3d76bfc0b92ae4607bd6b0dc47b4dcb 100644 --- a/Geo/MHexahedron.cpp +++ b/Geo/MHexahedron.cpp @@ -184,7 +184,7 @@ const nodalBasis* MHexahedron::getFunctionSpace(int o) const case 7: return BasisFactory::create(MSH_HEX_296); case 8: return BasisFactory::create(MSH_HEX_386); case 9: return BasisFactory::create(MSH_HEX_488); - default: Msg::Error("Order %d hex function space not implemented", order); + default: Msg::Error("Order %d hex function space not implemented", order); break; } } else { @@ -199,7 +199,44 @@ const nodalBasis* MHexahedron::getFunctionSpace(int o) const case 7: return BasisFactory::create(MSH_HEX_512); case 8: return BasisFactory::create(MSH_HEX_729); case 9: return BasisFactory::create(MSH_HEX_1000); - default: Msg::Error("Order %d hex function space not implemented", order); + default: Msg::Error("Order %d hex function space not implemented", order); break; + } + } + return 0; +} + +const JacobianBasis* MHexahedron::getJacobianFuncSpace(int o) const +{ + int order = (o == -1) ? getPolynomialOrder() : o; + + int nv = getNumVolumeVertices(); + + if ((nv == 0) && (o == -1)) { + switch (order) { + case 1: return JacobianBasis::find(MSH_HEX_8); + case 2: return JacobianBasis::find(MSH_HEX_20); + case 3: return JacobianBasis::find(MSH_HEX_56); + case 4: return JacobianBasis::find(MSH_HEX_98); + case 5: return JacobianBasis::find(MSH_HEX_152); + case 6: return JacobianBasis::find(MSH_HEX_222); + case 7: return JacobianBasis::find(MSH_HEX_296); + case 8: return JacobianBasis::find(MSH_HEX_386); + case 9: return JacobianBasis::find(MSH_HEX_488); + default: Msg::Error("Order %d hex incomplete Jacobian function space not implemented", order); break; + } + } + else { + switch (order) { + case 1: return JacobianBasis::find(MSH_HEX_8); + case 2: return JacobianBasis::find(MSH_HEX_27); + case 3: return JacobianBasis::find(MSH_HEX_64); + case 4: return JacobianBasis::find(MSH_HEX_125); + case 5: return JacobianBasis::find(MSH_HEX_216); + case 6: return JacobianBasis::find(MSH_HEX_343); + case 7: return JacobianBasis::find(MSH_HEX_512); + case 8: return JacobianBasis::find(MSH_HEX_729); + case 9: return JacobianBasis::find(MSH_HEX_1000); + default: Msg::Error("Order %d hex Jacobian function space not implemented", order); break; } } return 0; diff --git a/Geo/MHexahedron.h b/Geo/MHexahedron.h index d089dbae6141ed459a5c29144bdfd73f26d98860..d5984c1ef576f87da06504d1a9baa291aa999ea9 100644 --- a/Geo/MHexahedron.h +++ b/Geo/MHexahedron.h @@ -58,6 +58,7 @@ class MHexahedron : public MElement { virtual int getNumVertices() const { return 8; } virtual MVertex *getVertex(int num){ return _v[num]; } virtual const nodalBasis* getFunctionSpace(int o=-1) const; + virtual const JacobianBasis* getJacobianFuncSpace(int o=-1) const; virtual MVertex *getVertexDIFF(int num) { static const int map[8] = {2, 3, 7, 6, 0, 1, 5, 4}; diff --git a/Geo/MPyramid.cpp b/Geo/MPyramid.cpp index 5eb5db0e489b93df5439cc58ffc5f1f2fa4e1954..f4e42ef6ca7a4fb60502618e5476fce80723cfd7 100644 --- a/Geo/MPyramid.cpp +++ b/Geo/MPyramid.cpp @@ -66,6 +66,20 @@ const nodalBasis* MPyramid::getFunctionSpace(int o) const return 0; } +const JacobianBasis* MPyramid::getJacobianFuncSpace(int o) const +{ + int order = (o == -1) ? getPolynomialOrder() : o; + + switch (order) { + case 1: return JacobianBasis::find(MSH_PYR_5); + case 2: return JacobianBasis::find(MSH_PYR_14); + case 3: return JacobianBasis::find(MSH_PYR_30); + default: Msg::Error("Order %d pyramid function space not implemented", order); break; + } + + return 0; +} + MPyramidN::~MPyramidN() {} double MPyramidN::distoShapeMeasure() diff --git a/Geo/MPyramid.h b/Geo/MPyramid.h index 1277b1d75533e7867ba7605d3c01cc6964c196df..36bbca031974586a96d7e87ba858bf76c62b6101 100644 --- a/Geo/MPyramid.h +++ b/Geo/MPyramid.h @@ -68,6 +68,7 @@ class MPyramid : public MElement { virtual int getNumVertices() const { return 5; } virtual MVertex *getVertex(int num){ return _v[num]; } virtual const nodalBasis* getFunctionSpace(int o=-1) const; + virtual const JacobianBasis* getJacobianFuncSpace(int o=-1) const; virtual int getNumEdges(){ return 8; } virtual MEdge getEdge(int num) { diff --git a/Mesh/HighOrder.cpp b/Mesh/HighOrder.cpp index a7333333b68aa4d8041482933675a36f327b8346..150cb77043ff073019103f8632aa3ec310269b8e 100644 --- a/Mesh/HighOrder.cpp +++ b/Mesh/HighOrder.cpp @@ -21,7 +21,6 @@ #include "Numeric.h" #include "Context.h" #include "fullMatrix.h" -#include "polynomialBasis.h" #include "BasisFactory.h" #define SQU(a) ((a)*(a)) @@ -598,14 +597,14 @@ static int getNewFacePoints(int numPrimaryFacePoints, int nPts, fullMatrix<doubl switch (nPts){ case 0 : break; case 1 : break; - case 2 : points = polynomialBases::find(MSH_TRI_10)->points; start = 9; break; - case 3 : points = polynomialBases::find(MSH_TRI_15)->points; start = 12; break; - case 4 : points = polynomialBases::find(MSH_TRI_21)->points; start = 15; break; - case 5 : points = polynomialBases::find(MSH_TRI_28)->points; start = 18; break; - case 6 : points = polynomialBases::find(MSH_TRI_36)->points; start = 21; break; - case 7 : points = polynomialBases::find(MSH_TRI_45)->points; start = 24; break; - case 8 : points = polynomialBases::find(MSH_TRI_55)->points; start = 27; break; - case 9 : points = polynomialBases::find(MSH_TRI_66)->points; start = 30; break; + case 2 : points = BasisFactory::create(MSH_TRI_10)->points; start = 9; break; + case 3 : points = BasisFactory::create(MSH_TRI_15)->points; start = 12; break; + case 4 : points = BasisFactory::create(MSH_TRI_21)->points; start = 15; break; + case 5 : points = BasisFactory::create(MSH_TRI_28)->points; start = 18; break; + case 6 : points = BasisFactory::create(MSH_TRI_36)->points; start = 21; break; + case 7 : points = BasisFactory::create(MSH_TRI_45)->points; start = 24; break; + case 8 : points = BasisFactory::create(MSH_TRI_55)->points; start = 27; break; + case 9 : points = BasisFactory::create(MSH_TRI_66)->points; start = 30; break; default : Msg::Error("getFaceVertices not implemented for order %i", nPts +1); break; @@ -614,14 +613,14 @@ static int getNewFacePoints(int numPrimaryFacePoints, int nPts, fullMatrix<doubl case 4: switch (nPts){ case 0 : break; - case 1 : points = polynomialBases::find(MSH_QUA_9)->points; break; - case 2 : points = polynomialBases::find(MSH_QUA_16)->points; break; - case 3 : points = polynomialBases::find(MSH_QUA_25)->points; break; - case 4 : points = polynomialBases::find(MSH_QUA_36)->points; break; - case 5 : points = polynomialBases::find(MSH_QUA_49)->points; break; - case 6 : points = polynomialBases::find(MSH_QUA_64)->points; break; - case 7 : points = polynomialBases::find(MSH_QUA_81)->points; break; - case 8 : points = polynomialBases::find(MSH_QUA_100)->points; break; + case 1 : points = BasisFactory::create(MSH_QUA_9)->points; break; + case 2 : points = BasisFactory::create(MSH_QUA_16)->points; break; + case 3 : points = BasisFactory::create(MSH_QUA_25)->points; break; + case 4 : points = BasisFactory::create(MSH_QUA_36)->points; break; + case 5 : points = BasisFactory::create(MSH_QUA_49)->points; break; + case 6 : points = BasisFactory::create(MSH_QUA_64)->points; break; + case 7 : points = BasisFactory::create(MSH_QUA_81)->points; break; + case 8 : points = BasisFactory::create(MSH_QUA_100)->points; break; default : Msg::Error("getFaceVertices not implemented for order %i", nPts +1); break; @@ -743,14 +742,14 @@ static void getRegionVertices(GRegion *gr, MElement *incomplete, MElement *ele, case TYPE_HEX : switch (nPts){ case 0: return; - case 1: points = polynomialBases::find(MSH_HEX_27)->points; break; - case 2: points = polynomialBases::find(MSH_HEX_64)->points; break; - case 3: points = polynomialBases::find(MSH_HEX_125)->points; break; - case 4: points = polynomialBases::find(MSH_HEX_216)->points; break; - case 5: points = polynomialBases::find(MSH_HEX_343)->points; break; - case 6: points = polynomialBases::find(MSH_HEX_512)->points; break; - case 7: points = polynomialBases::find(MSH_HEX_729)->points; break; - case 8: points = polynomialBases::find(MSH_HEX_1000)->points; break; + case 1: points = BasisFactory::create(MSH_HEX_27)->points; break; + case 2: points = BasisFactory::create(MSH_HEX_64)->points; break; + case 3: points = BasisFactory::create(MSH_HEX_125)->points; break; + case 4: points = BasisFactory::create(MSH_HEX_216)->points; break; + case 5: points = BasisFactory::create(MSH_HEX_343)->points; break; + case 6: points = BasisFactory::create(MSH_HEX_512)->points; break; + case 7: points = BasisFactory::create(MSH_HEX_729)->points; break; + case 8: points = BasisFactory::create(MSH_HEX_1000)->points; break; default : Msg::Error("getRegionVertices not implemented for order %i", nPts+1); break; diff --git a/Numeric/BasisFactory.cpp b/Numeric/BasisFactory.cpp index 4479b6d4eb0be7c76b6270f37f88f38a77e64c9a..ce341f915630702a417446451451f3d436fa4dbd 100644 --- a/Numeric/BasisFactory.cpp +++ b/Numeric/BasisFactory.cpp @@ -32,181 +32,15 @@ const nodalBasis* BasisFactory::create(int elementType) { case(TYPE_PRI): case(TYPE_TET): case(TYPE_HEX): - B = new polynomialBasis(); + B = new polynomialBasis(elementType); break; case(TYPE_PYR): - B = new pyramidalBasis(); + B = new pyramidalBasis(elementType); break; default: Msg::Error("Unknown type of element."); return 0; } - B->parentType = parentType; - - // There is currently only 1 type of basis for any - // element type, hence we use the element type as the - // basis type. - B->type = elementType; - switch(elementType) { - case MSH_PNT : B->order = 0; B->serendip = false; break; - case MSH_LIN_1 : B->order = 0; B->serendip = false; break; - case MSH_LIN_2 : B->order = 1; B->serendip = false; break; - case MSH_LIN_3 : B->order = 2; B->serendip = false; break; - case MSH_LIN_4 : B->order = 3; B->serendip = false; break; - case MSH_LIN_5 : B->order = 4; B->serendip = false; break; - case MSH_LIN_6 : B->order = 5; B->serendip = false; break; - case MSH_LIN_7 : B->order = 6; B->serendip = false; break; - case MSH_LIN_8 : B->order = 7; B->serendip = false; break; - case MSH_LIN_9 : B->order = 8; B->serendip = false; break; - case MSH_LIN_10 : B->order = 9; B->serendip = false; break; - case MSH_LIN_11 : B->order = 10;B->serendip = false; break; - case MSH_TRI_1 : B->order = 0; B->serendip = false; break; - case MSH_TRI_3 : B->order = 1; B->serendip = false; break; - case MSH_TRI_6 : B->order = 2; B->serendip = false; break; - case MSH_TRI_10 : B->order = 3; B->serendip = false; break; - case MSH_TRI_15 : B->order = 4; B->serendip = false; break; - case MSH_TRI_21 : B->order = 5; B->serendip = false; break; - case MSH_TRI_28 : B->order = 6; B->serendip = false; break; - case MSH_TRI_36 : B->order = 7; B->serendip = false; break; - case MSH_TRI_45 : B->order = 8; B->serendip = false; break; - case MSH_TRI_55 : B->order = 9; B->serendip = false; break; - case MSH_TRI_66 : B->order = 10;B->serendip = false; break; - case MSH_TRI_9 : B->order = 3; B->serendip = true; break; - case MSH_TRI_12 : B->order = 4; B->serendip = true; break; - case MSH_TRI_15I : B->order = 5; B->serendip = true; break; - case MSH_TRI_18 : B->order = 6; B->serendip = true; break; - case MSH_TRI_21I : B->order = 7; B->serendip = true; break; - case MSH_TRI_24 : B->order = 8; B->serendip = true; break; - case MSH_TRI_27 : B->order = 9; B->serendip = true; break; - case MSH_TRI_30 : B->order = 10;B->serendip = true; break; - case MSH_TET_1 : B->order = 0; B->serendip = false; break; - case MSH_TET_4 : B->order = 1; B->serendip = false; break; - case MSH_TET_10 : B->order = 2; B->serendip = false; break; - case MSH_TET_20 : B->order = 3; B->serendip = false; break; - case MSH_TET_35 : B->order = 4; B->serendip = false; break; - case MSH_TET_56 : B->order = 5; B->serendip = false; break; - case MSH_TET_84 : B->order = 6; B->serendip = false; break; - case MSH_TET_120 : B->order = 7; B->serendip = false; break; - case MSH_TET_165 : B->order = 8; B->serendip = false; break; - case MSH_TET_220 : B->order = 9; B->serendip = false; break; - case MSH_TET_286 : B->order = 10;B->serendip = false; break; - case MSH_TET_34 : B->order = 4; B->serendip = true; break; - case MSH_TET_52 : B->order = 5; B->serendip = true; break; - case MSH_TET_74 : B->order = 6; B->serendip = true; break; - case MSH_TET_100 : B->order = 7; B->serendip = true; break; - case MSH_TET_130 : B->order = 8; B->serendip = true; break; - case MSH_TET_164 : B->order = 9; B->serendip = true; break; - case MSH_TET_202 : B->order = 10;B->serendip = true; break; - case MSH_QUA_1 : B->order = 0; B->serendip = false; break; - case MSH_QUA_4 : B->order = 1; B->serendip = false; break; - case MSH_QUA_9 : B->order = 2; B->serendip = false; break; - case MSH_QUA_16 : B->order = 3; B->serendip = false; break; - case MSH_QUA_25 : B->order = 4; B->serendip = false; break; - case MSH_QUA_36 : B->order = 5; B->serendip = false; break; - case MSH_QUA_49 : B->order = 6; B->serendip = false; break; - case MSH_QUA_64 : B->order = 7; B->serendip = false; break; - case MSH_QUA_81 : B->order = 8; B->serendip = false; break; - case MSH_QUA_100 : B->order = 9; B->serendip = false; break; - case MSH_QUA_121 : B->order = 10;B->serendip = false; break; - case MSH_QUA_8 : B->order = 2; B->serendip = true; break; - case MSH_QUA_12 : B->order = 3; B->serendip = true; break; - case MSH_QUA_16I : B->order = 4; B->serendip = true; break; - case MSH_QUA_20 : B->order = 5; B->serendip = true; break; - case MSH_QUA_24 : B->order = 6; B->serendip = true; break; - case MSH_QUA_28 : B->order = 7; B->serendip = true; break; - case MSH_QUA_32 : B->order = 8; B->serendip = true; break; - case MSH_QUA_36I : B->order = 9; B->serendip = true; break; - case MSH_QUA_40 : B->order = 10;B->serendip = true; break; - case MSH_PRI_1 : B->order = 0; B->serendip = false; break; - case MSH_PRI_6 : B->order = 1; B->serendip = false; break; - case MSH_PRI_18 : B->order = 2; B->serendip = false; break; - case MSH_HEX_8 : B->order = 1; B->serendip = false; break; - case MSH_HEX_27 : B->order = 2; B->serendip = false; break; - case MSH_HEX_64 : B->order = 3; B->serendip = false; break; - case MSH_HEX_125 : B->order = 4; B->serendip = false; break; - case MSH_HEX_216 : B->order = 5; B->serendip = false; break; - case MSH_HEX_343 : B->order = 6; B->serendip = false; break; - case MSH_HEX_512 : B->order = 7; B->serendip = false; break; - case MSH_HEX_729 : B->order = 8; B->serendip = false; break; - case MSH_HEX_1000: B->order = 9; B->serendip = false; break; - case MSH_HEX_20 : B->order = 2; B->serendip = false; break; - case MSH_HEX_56 : B->order = 3; B->serendip = true; break; - case MSH_HEX_98 : B->order = 4; B->serendip = true; break; - case MSH_HEX_152 : B->order = 5; B->serendip = true; break; - case MSH_HEX_222 : B->order = 6; B->serendip = true; break; - case MSH_HEX_296 : B->order = 7; B->serendip = true; break; - case MSH_HEX_386 : B->order = 8; B->serendip = true; break; - case MSH_HEX_488 : B->order = 9; B->serendip = true; break; - case MSH_PYR_1 : B->order = 0; B->serendip = false; break; - case MSH_PYR_5 : B->order = 1; B->serendip = false; break; - case MSH_PYR_14 : B->order = 2; B->serendip = false; break; - case MSH_PYR_30 : B->order = 3; B->serendip = false; break; - case MSH_PYR_55 : B->order = 4; B->serendip = false; break; - case MSH_PYR_91 : B->order = 5; B->serendip = false; break; - case MSH_PYR_140 : B->order = 6; B->serendip = false; break; - case MSH_PYR_204 : B->order = 7; B->serendip = false; break; - case MSH_PYR_285 : B->order = 8; B->serendip = false; break; - case MSH_PYR_385 : B->order = 9; B->serendip = false; break; - case MSH_PYR_29 : B->order = 3; B->serendip = true; break; - case MSH_PYR_50 : B->order = 4; B->serendip = true; break; - case MSH_PYR_77 : B->order = 5; B->serendip = true; break; - case MSH_PYR_110 : B->order = 6; B->serendip = true; break; - case MSH_PYR_149 : B->order = 7; B->serendip = true; break; - case MSH_PYR_194 : B->order = 8; B->serendip = true; break; - case MSH_PYR_245 : B->order = 9; B->serendip = true; break; - - default : - Msg::Error("Unknown function space %d: reverting to TET_4", elementType); - B->parentType = TYPE_TET; B->order = 1; B->serendip = false; break; - } - - // Here is where we do create the basis. - switch (B->parentType) { - case TYPE_PNT : - B->numFaces = 1; - B->dimension = 0; - B->points = gmshGeneratePointsLine(0); - break; - case TYPE_LIN : - B->numFaces = 2; - B->dimension = 1; - B->points = gmshGeneratePointsLine(B->order); - break; - case TYPE_TRI : - B->numFaces = 3; - B->dimension = 2; - B->points = gmshGeneratePointsTriangle(B->order, B->serendip); - break; - case TYPE_QUA : - B->numFaces = 4; - B->dimension = 2; - B->points = gmshGeneratePointsQuadrangle(B->order, B->serendip); - break; - case TYPE_TET : - B->numFaces = 4; - B->dimension = 3; - B->points = gmshGeneratePointsTetrahedron(B->order, B->serendip); - break; - case TYPE_PRI : - B->numFaces = 5; - B->dimension = 3; - B->points = gmshGeneratePointsPrism(B->order, B->serendip); - break; - case TYPE_HEX : - B->numFaces = 6; - B->dimension = 3; - B->points = gmshGeneratePointsHexahedron(B->order, B->serendip); - break; - case TYPE_PYR : - B->numFaces = 5; - B->dimension = 3; - B->points = gmshGeneratePointsPyramid(B->order, B->serendip); - break; - default: - Msg::Error("Unknown element type!\n"); - } - - B->initialize(); fs.insert(std::make_pair(elementType, B)); diff --git a/Numeric/BergotBasis.cpp b/Numeric/BergotBasis.cpp index e361960798f64e78940a03ef197e3f4b28ce98b0..2638b5bd1327713c3cdb6558c7a98acd1b6fba8b 100644 --- a/Numeric/BergotBasis.cpp +++ b/Numeric/BergotBasis.cpp @@ -10,6 +10,8 @@ }*/ + + BergotBasis::BergotBasis(int p): order(p) { // allocate function information and fill @@ -41,6 +43,7 @@ BergotBasis::BergotBasis(int p): order(p) } + BergotBasis::~BergotBasis() { delete [] iOrder; @@ -49,10 +52,7 @@ BergotBasis::~BergotBasis() } -int BergotBasis::size() const -{ - return (2*order*order*order + 9*order*order + 13*order + 6)/6; -} + void BergotBasis::f(double u, double v, double w, double* val) const { @@ -99,7 +99,9 @@ void BergotBasis::f(double u, double v, double w, double* val) const } } -inline void BergotBasis::df(double u, double v, double w, double grads[][3]) const + + +void BergotBasis::df(double u, double v, double w, double grads[][3]) const { std::vector<double> uFcts(order+1); legendre.f(u,&(uFcts[0])); diff --git a/Numeric/BergotBasis.h b/Numeric/BergotBasis.h index 0a68e68ce46ae34cb3db150fd8799ae812c54c5f..f03d5082bd271b8278ca6d80ba63411bdb8f1faf 100644 --- a/Numeric/BergotBasis.h +++ b/Numeric/BergotBasis.h @@ -11,15 +11,17 @@ #include "jacobiPolynomials.h" #include "legendrePolynomials.h" -class BergotBasis : public nodalBasis { +class BergotBasis { public: - BergotBasis() {}; BergotBasis(int p); - ~BergotBasis(); + virtual ~BergotBasis(); + + int size() const { const int n = order+1; return n*(n+1)*(2*n+1)/6; } + void f(double u, double v, double w, double *val) const; - inline void df(double u, double v, double w, double grads[][3]) const; + void df(double u, double v, double w, double grads[][3]) const; void initialize() {}; @@ -36,8 +38,6 @@ class BergotBasis : public nodalBasis { //! list of Jacobi polynomials up to order p in function of index i (\f$ \alpha = 2*i + 2\f$) std::map<int,JacobiPolynomials> jacobi; - int size() const; - }; #endif diff --git a/Numeric/CMakeLists.txt b/Numeric/CMakeLists.txt index aa2bb2bb932f5a5e7a23a0dd2df366f98ef1419a..383a213684f25dd41036d695349ef2ba589e3562 100644 --- a/Numeric/CMakeLists.txt +++ b/Numeric/CMakeLists.txt @@ -7,6 +7,7 @@ set(SRC Numeric.cpp fullMatrix.cpp BasisFactory.cpp + nodalBasis.cpp polynomialBasis.cpp JacobianBasis.cpp BergotBasis.cpp diff --git a/Numeric/JacobianBasis.cpp b/Numeric/JacobianBasis.cpp index c05d04d19e2689b39b7b83b38fe6ced8a3cdec51..e21b2a1736e189c95ad3d29dffa43c3823ee5184 100644 --- a/Numeric/JacobianBasis.cpp +++ b/Numeric/JacobianBasis.cpp @@ -8,6 +8,9 @@ #include "JacobianBasis.h" #include <vector> #include "polynomialBasis.h" +#include "pyramidalBasis.h" +#include "pointsGenerators.h" +#include "BasisFactory.h" // Bezier Exponents static fullMatrix<double> generate1DExponents(int order) @@ -449,8 +452,8 @@ static fullMatrix<double> generateExponentsHex(int order) fullMatrix<double> lineExp = generate1DExponents(order); for (int i = 0; i < 2; ++i) { - for (int j = 0; i < 2; ++j) { - for (int k = 0; i < 2; ++k) { + for (int j = 0; j < 2; ++j) { + for (int k = 0; k < 2; ++k) { exponents(index, 0) = lineExp(i, 0); exponents(index, 1) = lineExp(j, 0); exponents(index, 2) = lineExp(k, 0); @@ -460,8 +463,8 @@ static fullMatrix<double> generateExponentsHex(int order) } for (int i = 2; i < lineExp.size1(); ++i) { - for (int j = 0; i < 2; ++j) { - for (int k = 0; i < 2; ++k) { + for (int j = 0; j < 2; ++j) { + for (int k = 0; k < 2; ++k) { exponents(index, 0) = lineExp(i, 0); exponents(index, 1) = lineExp(j, 0); exponents(index, 2) = lineExp(k, 0); @@ -470,8 +473,8 @@ static fullMatrix<double> generateExponentsHex(int order) } } for (int i = 0; i < lineExp.size1(); ++i) { - for (int j = 2; i < lineExp.size1(); ++j) { - for (int k = 0; i < 2; ++k) { + for (int j = 2; j < lineExp.size1(); ++j) { + for (int k = 0; k < 2; ++k) { exponents(index, 0) = lineExp(i, 0); exponents(index, 1) = lineExp(j, 0); exponents(index, 2) = lineExp(k, 0); @@ -480,8 +483,8 @@ static fullMatrix<double> generateExponentsHex(int order) } } for (int i = 0; i < lineExp.size1(); ++i) { - for (int j = 0; i < lineExp.size1(); ++j) { - for (int k = 2; i < lineExp.size1(); ++k) { + for (int j = 0; j < lineExp.size1(); ++j) { + for (int k = 2; k < lineExp.size1(); ++k) { exponents(index, 0) = lineExp(i, 0); exponents(index, 1) = lineExp(j, 0); exponents(index, 2) = lineExp(k, 0); @@ -507,64 +510,6 @@ static fullMatrix<double> generate1DPoints(int order) return line; } -static fullMatrix<double> gmshGeneratePointsTriangle(int order, bool serendip) -{ - int nbPoints = serendip ? 3 * order : (order + 1) * (order + 2) / 2; - fullMatrix<double> point(nbPoints, 2); - - point(0, 0) = 0; - point(0, 1) = 0; - - if (order > 0) { - double dd = 1. / order; - - point(1, 0) = 1; - point(1, 1) = 0; - point(2, 0) = 0; - point(2, 1) = 1; - - int index = 3; - - if (order > 1) { - - double ksi = 0; - double eta = 0; - - for (int i = 0; i < order - 1; i++, index++) { - ksi += dd; - point(index, 0) = ksi; - point(index, 1) = eta; - } - - ksi = 1.; - - for (int i = 0; i < order - 1; i++, index++) { - ksi -= dd; - eta += dd; - point(index, 0) = ksi; - point(index, 1) = eta; - } - - eta = 1.; - ksi = 0.; - - for (int i = 0; i < order - 1; i++, index++) { - eta -= dd; - point(index, 0) = ksi; - point(index, 1) = eta; - } - - if (order > 2 && !serendip) { - fullMatrix<double> inner = gmshGeneratePointsTriangle(order - 3, serendip); - inner.scale(1. - 3. * dd); - inner.add(dd); - point.copy(inner, 0, nbPoints - index, 0, 2, index, 0); - } - } - } - return point; -} - static fullMatrix<double> generatePointsQuadRecur(int order, bool serendip) { int nbPoints = serendip ? order*4 : (order+1)*(order+1); @@ -618,143 +563,6 @@ static fullMatrix<double> generatePointsQuad(int order, bool serendip) return point; } - -static fullMatrix<double> gmshGeneratePointsTetrahedron(int order, bool serendip) -{ - int nbPoints = - (serendip ? - 4 + 6 * std::max(0, order - 1) + 4 * std::max(0, (order - 2) * (order - 1) / 2) : - (order + 1) * (order + 2) * (order + 3) / 6); - - fullMatrix<double> point(nbPoints, 3); - - double overOrder = (order == 0 ? 1. : 1. / order); - - point(0, 0) = 0.; - point(0, 1) = 0.; - point(0, 2) = 0.; - - if (order > 0) { - point(1, 0) = order; - point(1, 1) = 0; - point(1, 2) = 0; - - point(2, 0) = 0.; - point(2, 1) = order; - point(2, 2) = 0.; - - point(3, 0) = 0.; - point(3, 1) = 0.; - point(3, 2) = order; - - // edges e5 and e6 switched in original version, opposite direction - // the template has been defined in table edges_tetra and faces_tetra (MElement.h) - - if (order > 1) { - for (int k = 0; k < (order - 1); k++) { - point(4 + k, 0) = k + 1; - point(4 + order - 1 + k, 0) = order - 1 - k; - point(4 + 2 * (order - 1) + k, 0) = 0.; - point(4 + 3 * (order - 1) + k, 0) = 0.; - // point(4 + 4 * (order - 1) + k, 0) = order - 1 - k; - // point(4 + 5 * (order - 1) + k, 0) = 0.; - point(4 + 4 * (order - 1) + k, 0) = 0.; - point(4 + 5 * (order - 1) + k, 0) = k+1; - - point(4 + k, 1) = 0.; - point(4 + order - 1 + k, 1) = k + 1; - point(4 + 2 * (order - 1) + k, 1) = order - 1 - k; - point(4 + 3 * (order - 1) + k, 1) = 0.; - // point(4 + 4 * (order - 1) + k, 1) = 0.; - // point(4 + 5 * (order - 1) + k, 1) = order - 1 - k; - point(4 + 4 * (order - 1) + k, 1) = k+1; - point(4 + 5 * (order - 1) + k, 1) = 0.; - - point(4 + k, 2) = 0.; - point(4 + order - 1 + k, 2) = 0.; - point(4 + 2 * (order - 1) + k, 2) = 0.; - point(4 + 3 * (order - 1) + k, 2) = order - 1 - k; - point(4 + 4 * (order - 1) + k, 2) = order - 1 - k; - point(4 + 5 * (order - 1) + k, 2) = order - 1 - k; - } - - if (order > 2) { - int ns = 4 + 6 * (order - 1); - int nbdofface = nbdoftriangle(order - 3); - - double *u = new double[nbdofface]; - double *v = new double[nbdofface]; - double *w = new double[nbdofface]; - - nodepositionface0(order - 3, u, v, w); - - // u-v plane - - for (int i = 0; i < nbdofface; i++){ - point(ns + i, 0) = u[i] * (order - 3) + 1.; - point(ns + i, 1) = v[i] * (order - 3) + 1.; - point(ns + i, 2) = w[i] * (order - 3); - } - - ns = ns + nbdofface; - - // u-w plane - - nodepositionface1(order - 3, u, v, w); - - for (int i=0; i < nbdofface; i++){ - point(ns + i, 0) = u[i] * (order - 3) + 1.; - point(ns + i, 1) = v[i] * (order - 3) ; - point(ns + i, 2) = w[i] * (order - 3) + 1.; - } - - // v-w plane - - ns = ns + nbdofface; - - nodepositionface2(order - 3, u, v, w); - - for (int i = 0; i < nbdofface; i++){ - point(ns + i, 0) = u[i] * (order - 3); - point(ns + i, 1) = v[i] * (order - 3) + 1.; - point(ns + i, 2) = w[i] * (order - 3) + 1.; - } - - // u-v-w plane - - ns = ns + nbdofface; - - nodepositionface3(order - 3, u, v, w); - - for (int i = 0; i < nbdofface; i++){ - point(ns + i, 0) = u[i] * (order - 3) + 1.; - point(ns + i, 1) = v[i] * (order - 3) + 1.; - point(ns + i, 2) = w[i] * (order - 3) + 1.; - } - - ns = ns + nbdofface; - - delete [] u; - delete [] v; - delete [] w; - - if (!serendip && order > 3) { - - fullMatrix<double> interior = gmshGeneratePointsTetrahedron(order - 4, false); - for (int k = 0; k < interior.size1(); k++) { - point(ns + k, 0) = 1. + interior(k, 0) * (order - 4); - point(ns + k, 1) = 1. + interior(k, 1) * (order - 4); - point(ns + k, 2) = 1. + interior(k, 2) * (order - 4); - } - } - } - } - } - - point.scale(overOrder); - return point; -} - static fullMatrix<double> generatePointsPrism(int order, bool serendip) { const double prism18Pts[18][3] = { @@ -1126,9 +934,10 @@ static fullMatrix<double> generateSubDivisor -static void generateGradShapes(JacobianBasis &jfs, const fullMatrix<double> &points - , const fullMatrix<double> &monomials, const fullMatrix<double> &coefficients) +static void generateGradShapes(JacobianBasis &jfs, const fullMatrix<double> &points, + const fullMatrix<double> &monomials, const fullMatrix<double> &coefficients) { + int nbPts = points.size1(); int nbDofs = monomials.size1(); int dim = points.size2(); @@ -1208,10 +1017,14 @@ static void generateGradShapes(JacobianBasis &jfs, const fullMatrix<double> &poi } } } + break; } return; + } + + std::map<int, bezierBasis> bezierBasis::_bbs; const bezierBasis *bezierBasis::find(int tag) { @@ -1220,80 +1033,96 @@ const bezierBasis *bezierBasis::find(int tag) return &it->second; bezierBasis &B = _bbs[tag]; - const polynomialBasis *F = polynomialBases::find(tag); - int dimSimplex; - std::vector< fullMatrix<double> > subPoints; - switch (F->parentType) { - case TYPE_PNT : - B.numLagPts = 1; - B.exponents = generate1DExponents(0); - B.points = generate1DPoints(0); - dimSimplex = 0; - break; - case TYPE_LIN : { - B.numLagPts = 2; - B.exponents = generate1DExponents(F->order); - B.points = generate1DPoints(F->order); - dimSimplex = 0; - subPoints = generateSubPointsLine(0); - break; - } - case TYPE_TRI : { - B.numLagPts = 3; - B.exponents = generateExponentsTriangle(F->order); - B.points = gmshGeneratePointsTriangle(F->order,false); - dimSimplex = 2; - subPoints = generateSubPointsTriangle(F->order); - break; - } - case TYPE_QUA : { - B.numLagPts = 4; - B.exponents = generateExponentsQuad(F->order); - B.points = generatePointsQuad(F->order,false); - dimSimplex = 0; - subPoints = generateSubPointsQuad(F->order); - // B.points.print("points"); - break; - } - case TYPE_TET : { - B.numLagPts = 4; - B.exponents = generateExponentsTetrahedron(F->order); - B.points = gmshGeneratePointsTetrahedron(F->order,false); - dimSimplex = 3; - subPoints = generateSubPointsTetrahedron(F->order); - break; - } - case TYPE_PRI : { - B.numLagPts = 6; - B.exponents = generateExponentsPrism(F->order); - B.points = generatePointsPrism(F->order, false); - dimSimplex = 2; - subPoints = generateSubPointsPrism(F->order); - break; + B.order = MElement::OrderFromTag(tag); + + if (MElement::ParentTypeFromTag(tag) == TYPE_PYR) { + B.numLagPts = 5; + B.points = gmshGeneratePointsPyramid(B.order,false); + B.matrixLag2Bez.resize(B.points.size1(),B.points.size1(),0.); + B.matrixBez2Lag.resize(B.points.size1(),B.points.size1(),0.); + for (int i=0; i<B.matrixBez2Lag.size1(); ++i) { + B.matrixLag2Bez(i,i) = 1.; + B.matrixBez2Lag(i,i) = 1.; } - case TYPE_HEX : { - B.numLagPts = 8; - B.exponents = generateExponentsHex(F->order); - B.points = generatePointsHex(F->order, false); - dimSimplex = 0; - subPoints = generateSubPointsHex(F->order); - break; - } - default : { - Msg::Error("Unknown function space %d: reverting to TET_1", tag); - F = polynomialBases::find(MSH_TET_1); - B.numLagPts = 4; - B.exponents = generateExponentsTetrahedron(0); - B.points = gmshGeneratePointsTetrahedron(0, false); - dimSimplex = 3; - subPoints = generateSubPointsTetrahedron(0); +// B.subDivisor = generateSubDivisor(B.exponents, subPoints, B.matrixLag2Bez, F->order, dimSimplex); +// B.numDivisions = (int) pow(2., (int) B.points.size2()); + } + else { + const polynomialBasis *F = (polynomialBasis*)BasisFactory::create(tag); + int dimSimplex; + std::vector< fullMatrix<double> > subPoints; + switch (F->parentType) { + case TYPE_PNT : + B.numLagPts = 1; + B.exponents = generate1DExponents(0); + B.points = generate1DPoints(0); + dimSimplex = 0; + break; + case TYPE_LIN : { + B.numLagPts = 2; + B.exponents = generate1DExponents(F->order); + B.points = generate1DPoints(F->order); + dimSimplex = 0; + subPoints = generateSubPointsLine(0); + break; + } + case TYPE_TRI : { + B.numLagPts = 3; + B.exponents = generateExponentsTriangle(F->order); + B.points = gmshGeneratePointsTriangle(F->order,false); + dimSimplex = 2; + subPoints = generateSubPointsTriangle(F->order); + break; + } + case TYPE_QUA : { + B.numLagPts = 4; + B.exponents = generateExponentsQuad(F->order); + B.points = generatePointsQuad(F->order,false); + dimSimplex = 0; + subPoints = generateSubPointsQuad(F->order); + // B.points.print("points"); + break; + } + case TYPE_TET : { + B.numLagPts = 4; + B.exponents = generateExponentsTetrahedron(F->order); + B.points = gmshGeneratePointsTetrahedron(F->order,false); + dimSimplex = 3; + subPoints = generateSubPointsTetrahedron(F->order); + break; + } + case TYPE_PRI : { + B.numLagPts = 6; + B.exponents = generateExponentsPrism(F->order); + B.points = generatePointsPrism(F->order, false); + dimSimplex = 2; + subPoints = generateSubPointsPrism(F->order); + break; + } + case TYPE_HEX : { + B.numLagPts = 8; + B.exponents = generateExponentsHex(F->order); + B.points = generatePointsHex(F->order, false); + dimSimplex = 0; + subPoints = generateSubPointsHex(F->order); + break; + } + default : { + Msg::Error("Unknown function space %d: reverting to TET_1", tag); + B.numLagPts = 4; + B.exponents = generateExponentsTetrahedron(0); + B.points = gmshGeneratePointsTetrahedron(0, false); + dimSimplex = 3; + subPoints = generateSubPointsTetrahedron(0); + break; + } } + B.matrixBez2Lag = generateBez2LagMatrix(B.exponents, B.points, F->order, dimSimplex); + B.matrixBez2Lag.invert(B.matrixLag2Bez); + B.subDivisor = generateSubDivisor(B.exponents, subPoints, B.matrixLag2Bez, F->order, dimSimplex); + B.numDivisions = (int) pow(2., (int) B.points.size2()); } - B.matrixBez2Lag = generateBez2LagMatrix(B.exponents, B.points, F->order, dimSimplex); - B.matrixBez2Lag.invert(B.matrixLag2Bez); - B.subDivisor = generateSubDivisor(B.exponents, subPoints, B.matrixLag2Bez, F->order, dimSimplex); - B.numDivisions = (int) pow(2., (int) B.points.size2()); return &B; } @@ -1301,24 +1130,38 @@ std::map<int, JacobianBasis> JacobianBasis::_fs; const JacobianBasis *JacobianBasis::find(int tag) { std::map<int, JacobianBasis>::const_iterator it = _fs.find(tag); - if (it != _fs.end()) - return &it->second; + if (it != _fs.end()) return &it->second; JacobianBasis &J = _fs[tag]; - const polynomialBasis *F = polynomialBases::find(tag); - int jacobianOrder; - switch (F->parentType) { - case TYPE_PNT : jacobianOrder = 0; break; - case TYPE_LIN : jacobianOrder = F->order - 1; break; - case TYPE_TRI : jacobianOrder = 2 * (F->order - 1); break; - case TYPE_QUA : jacobianOrder = 2 * F->order - 1; break; - case TYPE_TET : jacobianOrder = 3 * (F->order - 1); break; - case TYPE_PRI : jacobianOrder = 3 * F->order - 1; break; - case TYPE_HEX : jacobianOrder = 3 * F->order - 1; break; + if (MElement::ParentTypeFromTag(tag) == TYPE_PYR) { + switch (tag) { + case MSH_PYR_5 : J.bezier = bezierBasis::find(MSH_PYR_14); break; // TODO: Order 1, Jac. "order" 2, check this + case MSH_PYR_14 : J.bezier = bezierBasis::find(MSH_PYR_91); break; // TODO: Order 2, Jac. "order" 5, check this + case MSH_PYR_30 : J.bezier = bezierBasis::find(MSH_PYR_285); break; // TODO: Order 3, Jac. "order" 8, check this default : - Msg::Error("Unknown function space %d: reverting to TET_4", tag); - jacobianOrder = 0; + Msg::Error("Unknown Jacobian function space for element type %d: reverting to PYR_5", tag); + J.bezier = bezierBasis::find(MSH_PYR_14); + break; + } + } + else { + const int parentType = MElement::ParentTypeFromTag(tag), order = MElement::OrderFromTag(tag); + int jacobianOrder; + switch (parentType) { + case TYPE_PNT : jacobianOrder = 0; break; + case TYPE_LIN : jacobianOrder = order - 1; break; + case TYPE_TRI : jacobianOrder = 2 * (order - 1); break; + case TYPE_QUA : jacobianOrder = 2 * order - 1; break; + case TYPE_TET : jacobianOrder = 3 * (order - 1); break; + case TYPE_PRI : jacobianOrder = 3 * order - 1; break; + case TYPE_HEX : jacobianOrder = 3 * order - 1; break; + default : + Msg::Error("Unknown Jacobian function space for element type %d: reverting to TET_4", tag); + jacobianOrder = 0; + break; + } + J.bezier = bezierBasis::find(polynomialBasis::getTag(parentType, jacobianOrder, false)); + polynomialBasis *F = (polynomialBasis*)BasisFactory::create(tag); + generateGradShapes(J, J.bezier->points, F->monomials, F->coefficients); } - J.bezier = bezierBasis::find(polynomialBasis::getTag(F->parentType, jacobianOrder, false)); - generateGradShapes(J, J.bezier->points, F->monomials, F->coefficients); return &J; } diff --git a/Numeric/JacobianBasis.h b/Numeric/JacobianBasis.h index d876be6ddaa9d725ccd37e7323f1f6dd0e0f20a7..af8326a968153c54ea6a901bd7db55b7b4995da2 100644 --- a/Numeric/JacobianBasis.h +++ b/Numeric/JacobianBasis.h @@ -13,6 +13,7 @@ class bezierBasis { private : static std::map<int, bezierBasis> _bbs; public : + int order; int numLagPts; int numDivisions; // the 'numLagPts' first exponents are related to 'Lagrangian' values diff --git a/Numeric/nodalBasis.cpp b/Numeric/nodalBasis.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e11af47cadf4e0572cdb990b374375b9b86364d6 --- /dev/null +++ b/Numeric/nodalBasis.cpp @@ -0,0 +1,1589 @@ +// Gmsh - Copyright (C) 1997-2012 C. Geuzaine, J.-F. Remacle +// +// See the LICENSE.txt file for license information. Please report all +// bugs and problems to <gmsh@geuz.org>. + +#include <limits> +#include "nodalBasis.h" +#include "BasisFactory.h" +//#include "pointsGenerators.h" + + + +static int nbdoftriangle(int order) { return (order + 1) * (order + 2) / 2; } + +//KH : caveat : node coordinates are not yet coherent with node numbering associated +// to numbering of principal vertices of face !!!! + +// uv surface - orientation v0-v2-v1 + + + +static void nodepositionface0(int order, double *u, double *v, double *w) +{ + int ndofT = nbdoftriangle(order); + if (order == 0) { u[0] = 0.; v[0] = 0.; w[0] = 0.; return; } + + u[0]= 0.; v[0]= 0.; w[0] = 0.; + u[1]= 0.; v[1]= order; w[1] = 0.; + u[2]= order; v[2]= 0.; w[2] = 0.; + + // edges + for (int k = 0; k < (order - 1); k++){ + u[3 + k] = 0.; + v[3 + k] = k + 1; + w[3 + k] = 0.; + + u[3 + order - 1 + k] = k + 1; + v[3 + order - 1 + k] = order - 1 - k ; + w[3 + order - 1 + k] = 0.; + + u[3 + 2 * (order - 1) + k] = order - 1 - k; + v[3 + 2 * (order - 1) + k] = 0.; + w[3 + 2 * (order - 1) + k] = 0.; + } + + if (order > 2){ + int nbdoftemp = nbdoftriangle(order - 3); + nodepositionface0(order - 3, &u[3 + 3 * (order - 1)], &v[3 + 3 * (order - 1)], + &w[3 + 3* (order - 1)]); + for (int k = 0; k < nbdoftemp; k++){ + u[3 + k + 3 * (order - 1)] = u[3 + k + 3 * (order - 1)] * (order - 3) + 1.; + v[3 + k + 3 * (order - 1)] = v[3 + k + 3 * (order - 1)] * (order - 3) + 1.; + w[3 + k + 3 * (order - 1)] = w[3 + k + 3 * (order - 1)] * (order - 3); + } + } + for (int k = 0; k < ndofT; k++){ + u[k] = u[k] / order; + v[k] = v[k] / order; + w[k] = w[k] / order; + } +} + + + +// uw surface - orientation v0-v1-v3 +static void nodepositionface1(int order, double *u, double *v, double *w) +{ + int ndofT = nbdoftriangle(order); + if (order == 0) { u[0] = 0.; v[0] = 0.; w[0] = 0.; return; } + + u[0] = 0.; v[0]= 0.; w[0] = 0.; + u[1] = order; v[1]= 0.; w[1] = 0.; + u[2] = 0.; v[2]= 0.; w[2] = order; + // edges + for (int k = 0; k < (order - 1); k++){ + u[3 + k] = k + 1; + v[3 + k] = 0.; + w[3 + k] = 0.; + + u[3 + order - 1 + k] = order - 1 - k; + v[3 + order - 1 + k] = 0.; + w[3 + order - 1+ k ] = k + 1; + + u[3 + 2 * (order - 1) + k] = 0. ; + v[3 + 2 * (order - 1) + k] = 0.; + w[3 + 2 * (order - 1) + k] = order - 1 - k; + } + if (order > 2){ + int nbdoftemp = nbdoftriangle(order - 3); + nodepositionface1(order - 3, &u[3 + 3 * (order - 1)], &v[3 + 3 * (order -1 )], + &w[3 + 3 * (order - 1)]); + for (int k = 0; k < nbdoftemp; k++){ + u[3 + k + 3 * (order - 1)] = u[3 + k + 3 * (order - 1)] * (order - 3) + 1.; + v[3 + k + 3 * (order - 1)] = v[3 + k + 3 * (order - 1)] * (order - 3); + w[3 + k + 3 * (order - 1)] = w[3 + k + 3 * (order - 1)] * (order - 3) + 1.; + } + } + for (int k = 0; k < ndofT; k++){ + u[k] = u[k] / order; + v[k] = v[k] / order; + w[k] = w[k] / order; + } +} + + + +// vw surface - orientation v0-v3-v2 +static void nodepositionface2(int order, double *u, double *v, double *w) +{ + int ndofT = nbdoftriangle(order); + if (order == 0) { u[0] = 0.; v[0] = 0.; return; } + + u[0]= 0.; v[0]= 0.; w[0] = 0.; + u[1]= 0.; v[1]= 0.; w[1] = order; + u[2]= 0.; v[2]= order; w[2] = 0.; + // edges + for (int k = 0; k < (order - 1); k++){ + + u[3 + k] = 0.; + v[3 + k] = 0.; + w[3 + k] = k + 1; + + u[3 + order - 1 + k] = 0.; + v[3 + order - 1 + k] = k + 1; + w[3 + order - 1 + k] = order - 1 - k; + + u[3 + 2 * (order - 1) + k] = 0.; + v[3 + 2 * (order - 1) + k] = order - 1 - k; + w[3 + 2 * (order - 1) + k] = 0.; + } + if (order > 2){ + int nbdoftemp = nbdoftriangle(order - 3); + nodepositionface2(order - 3, &u[3 + 3 * (order - 1)], &v[3 + 3 * (order - 1)], + &w[3 + 3 * (order - 1)]); + for (int k = 0; k < nbdoftemp; k++){ + u[3 + k + 3 * (order - 1)] = u[3 + k + 3 * (order - 1)] * (order - 3); + v[3 + k + 3 * (order - 1)] = v[3 + k + 3 * (order - 1)] * (order - 3) + 1.; + w[3 + k + 3 * (order - 1)] = w[3 + k + 3 * (order - 1)] * (order - 3) + 1.; + } + } + for (int k = 0; k < ndofT; k++){ + u[k] = u[k] / order; + v[k] = v[k] / order; + w[k] = w[k] / order; + } +} + + + +// uvw surface - orientation v3-v1-v2 +static void nodepositionface3(int order, double *u, double *v, double *w) +{ + int ndofT = nbdoftriangle(order); + if (order == 0) { u[0] = 0.; v[0] = 0.; w[0] = 0.; return; } + + u[0]= 0.; v[0]= 0.; w[0] = order; + u[1]= order; v[1]= 0.; w[1] = 0.; + u[2]= 0.; v[2]= order; w[2] = 0.; + // edges + for (int k = 0; k < (order - 1); k++){ + + u[3 + k] = k + 1; + v[3 + k] = 0.; + w[3 + k] = order - 1 - k; + + u[3 + order - 1 + k] = order - 1 - k; + v[3 + order - 1 + k] = k + 1; + w[3 + order - 1 + k] = 0.; + + u[3 + 2 * (order - 1) + k] = 0.; + v[3 + 2 * (order - 1) + k] = order - 1 - k; + w[3 + 2 * (order - 1) + k] = k + 1; + } + if (order > 2){ + int nbdoftemp = nbdoftriangle(order - 3); + nodepositionface3(order - 3, &u[3 + 3 * (order - 1)], &v[3 + 3 * (order - 1)], + &w[3 + 3 * (order - 1)]); + for (int k = 0; k < nbdoftemp; k++){ + u[3 + k + 3 * (order - 1)] = u[3 + k + 3 * (order - 1)] * (order - 3) + 1.; + v[3 + k + 3 * (order - 1)] = v[3 + k + 3 * (order - 1)] * (order - 3) + 1.; + w[3 + k + 3 * (order - 1)] = w[3 + k + 3 * (order - 1)] * (order - 3) + 1.; + } + } + for (int k = 0; k < ndofT; k++){ + u[k] = u[k] / order; + v[k] = v[k] / order; + w[k] = w[k] / order; + } +} + + + +static fullMatrix<double> generate1DPoints(int order) +{ + fullMatrix<double> line(order + 1, 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; +} + + + +static fullMatrix<double> gmshGeneratePointsTetrahedron(int order, bool serendip) +{ + int nbPoints = + (serendip ? + 4 + 6 * std::max(0, order - 1) + 4 * std::max(0, (order - 2) * (order - 1) / 2) : + (order + 1) * (order + 2) * (order + 3) / 6); + + fullMatrix<double> point(nbPoints, 3); + + double overOrder = (order == 0 ? 1. : 1. / order); + + point(0, 0) = 0.; + point(0, 1) = 0.; + point(0, 2) = 0.; + + if (order > 0) { + point(1, 0) = order; + point(1, 1) = 0; + point(1, 2) = 0; + + point(2, 0) = 0.; + point(2, 1) = order; + point(2, 2) = 0.; + + point(3, 0) = 0.; + point(3, 1) = 0.; + point(3, 2) = order; + + // edges e5 and e6 switched in original version, opposite direction + // the template has been defined in table edges_tetra and faces_tetra (MElement.h) + + if (order > 1) { + for (int k = 0; k < (order - 1); k++) { + point(4 + k, 0) = k + 1; + point(4 + order - 1 + k, 0) = order - 1 - k; + point(4 + 2 * (order - 1) + k, 0) = 0.; + point(4 + 3 * (order - 1) + k, 0) = 0.; + // point(4 + 4 * (order - 1) + k, 0) = order - 1 - k; + // point(4 + 5 * (order - 1) + k, 0) = 0.; + point(4 + 4 * (order - 1) + k, 0) = 0.; + point(4 + 5 * (order - 1) + k, 0) = k+1; + + point(4 + k, 1) = 0.; + point(4 + order - 1 + k, 1) = k + 1; + point(4 + 2 * (order - 1) + k, 1) = order - 1 - k; + point(4 + 3 * (order - 1) + k, 1) = 0.; + // point(4 + 4 * (order - 1) + k, 1) = 0.; + // point(4 + 5 * (order - 1) + k, 1) = order - 1 - k; + point(4 + 4 * (order - 1) + k, 1) = k+1; + point(4 + 5 * (order - 1) + k, 1) = 0.; + + point(4 + k, 2) = 0.; + point(4 + order - 1 + k, 2) = 0.; + point(4 + 2 * (order - 1) + k, 2) = 0.; + point(4 + 3 * (order - 1) + k, 2) = order - 1 - k; + point(4 + 4 * (order - 1) + k, 2) = order - 1 - k; + point(4 + 5 * (order - 1) + k, 2) = order - 1 - k; + } + + if (order > 2) { + int ns = 4 + 6 * (order - 1); + int nbdofface = nbdoftriangle(order - 3); + + double *u = new double[nbdofface]; + double *v = new double[nbdofface]; + double *w = new double[nbdofface]; + + nodepositionface0(order - 3, u, v, w); + + // u-v plane + + for (int i = 0; i < nbdofface; i++){ + point(ns + i, 0) = u[i] * (order - 3) + 1.; + point(ns + i, 1) = v[i] * (order - 3) + 1.; + point(ns + i, 2) = w[i] * (order - 3); + } + + ns = ns + nbdofface; + + // u-w plane + + nodepositionface1(order - 3, u, v, w); + + for (int i=0; i < nbdofface; i++){ + point(ns + i, 0) = u[i] * (order - 3) + 1.; + point(ns + i, 1) = v[i] * (order - 3) ; + point(ns + i, 2) = w[i] * (order - 3) + 1.; + } + + // v-w plane + + ns = ns + nbdofface; + + nodepositionface2(order - 3, u, v, w); + + for (int i = 0; i < nbdofface; i++){ + point(ns + i, 0) = u[i] * (order - 3); + point(ns + i, 1) = v[i] * (order - 3) + 1.; + point(ns + i, 2) = w[i] * (order - 3) + 1.; + } + + // u-v-w plane + + ns = ns + nbdofface; + + nodepositionface3(order - 3, u, v, w); + + for (int i = 0; i < nbdofface; i++){ + point(ns + i, 0) = u[i] * (order - 3) + 1.; + point(ns + i, 1) = v[i] * (order - 3) + 1.; + point(ns + i, 2) = w[i] * (order - 3) + 1.; + } + + ns = ns + nbdofface; + + delete [] u; + delete [] v; + delete [] w; + + if (!serendip && order > 3) { + + fullMatrix<double> interior = gmshGeneratePointsTetrahedron(order - 4, false); + for (int k = 0; k < interior.size1(); k++) { + point(ns + k, 0) = 1. + interior(k, 0) * (order - 4); + point(ns + k, 1) = 1. + interior(k, 1) * (order - 4); + point(ns + k, 2) = 1. + interior(k, 2) * (order - 4); + } + } + } + } + } + + point.scale(overOrder); + return point; +} + + + +static fullMatrix<double> gmshGeneratePointsTriangle(int order, bool serendip) +{ + int nbPoints = serendip ? 3 * order : (order + 1) * (order + 2) / 2; + fullMatrix<double> point(nbPoints, 2); + + point(0, 0) = 0; + point(0, 1) = 0; + + if (order > 0) { + double dd = 1. / order; + + point(1, 0) = 1; + point(1, 1) = 0; + point(2, 0) = 0; + point(2, 1) = 1; + + int index = 3; + + if (order > 1) { + + double ksi = 0; + double eta = 0; + + for (int i = 0; i < order - 1; i++, index++) { + ksi += dd; + point(index, 0) = ksi; + point(index, 1) = eta; + } + + ksi = 1.; + + for (int i = 0; i < order - 1; i++, index++) { + ksi -= dd; + eta += dd; + point(index, 0) = ksi; + point(index, 1) = eta; + } + + eta = 1.; + ksi = 0.; + + for (int i = 0; i < order - 1; i++, index++) { + eta -= dd; + point(index, 0) = ksi; + point(index, 1) = eta; + } + + if (order > 2 && !serendip) { + fullMatrix<double> inner = gmshGeneratePointsTriangle(order - 3, serendip); + inner.scale(1. - 3. * dd); + inner.add(dd); + point.copy(inner, 0, nbPoints - index, 0, 2, index, 0); + } + } + } + return point; +} + + + +static fullMatrix<double> gmshGeneratePointsPrism(int order, bool serendip) +{ + const double prism18Pts[18][3] = { + {0, 0, -1}, // 0 + {1, 0, -1}, // 1 + {0, 1, -1}, // 2 + {0, 0, 1}, // 3 + {1, 0, 1}, // 4 + {0, 1, 1}, // 5 + {0.5, 0, -1}, // 6 + {0, 0.5, -1}, // 7 + {0, 0, 0}, // 8 + {0.5, 0.5, -1}, // 9 + {1, 0, 0}, // 10 + {0, 1, 0}, // 11 + {0.5, 0, 1}, // 12 + {0, 0.5, 1}, // 13 + {0.5, 0.5, 1}, // 14 + {0.5, 0, 0}, // 15 + {0, 0.5, 0}, // 16 + {0.5, 0.5, 0}, // 17 + }; + + int nbPoints = (order + 1)*(order + 1)*(order + 2)/2; + fullMatrix<double> point(nbPoints, 3); + + int index = 0; + fullMatrix<double> triPoints = gmshGeneratePointsTriangle(order,false); + fullMatrix<double> linePoints = generate1DPoints(order); + + if (order == 2) + for (int i =0; i<18; i++) + for (int j=0; j<3;j++) + point(i,j) = prism18Pts[i][j]; + else + for (int j = 0; j <linePoints.size1() ; j++) { + for (int i = 0; i < triPoints.size1(); i++) { + point(index,0) = triPoints(i,0); + point(index,1) = triPoints(i,1); + point(index,2) = linePoints(j,0); + index ++; + } + } + + return point; +} + + + +static fullMatrix<double> gmshGeneratePointsQuad(int order, bool serendip) +{ + int nbPoints = serendip ? order*4 : (order+1)*(order+1); + fullMatrix<double> point(nbPoints, 2); + + if (order > 0) { + point(0, 0) = -1; + point(0, 1) = -1; + point(1, 0) = 1; + point(1, 1) = -1; + point(2, 0) = 1; + point(2, 1) = 1; + point(3, 0) = -1; + point(3, 1) = 1; + + if (order > 1) { + int index = 4; + const static int edges[4][2]={{0,1},{1,2},{2,3},{3,0}}; + for (int iedge=0; iedge<4; iedge++) { + int p0 = edges[iedge][0]; + int p1 = edges[iedge][1]; + for (int i = 1; i < order; i++, index++) { + point(index, 0) = point(p0, 0) + i*(point(p1,0)-point(p0,0))/order; + point(index, 1) = point(p0, 1) + i*(point(p1,1)-point(p0,1))/order; + } + } + // FIXIT it was > 2 and I beleive it is >= 2 !! + if (order >= 2 && !serendip) { + fullMatrix<double> inner = gmshGeneratePointsQuad(order - 2, false); + inner.scale(1. - 2./order); + point.copy(inner, 0, nbPoints - index, 0, 2, index, 0); + } + } + } + else { + point(0, 0) = 0; + point(0, 1) = 0; + } + return point; +} + + + +static fullMatrix<double> gmshGeneratePointsHex(int order, bool serendip) +{ + int nbPoints = (order+1)*(order+1)*(order+1); + if (serendip) nbPoints -= (order-1)*(order-1)*(order-1); + fullMatrix<double> point(nbPoints, 3); + + // should be a public member of MHexahedron, just copied + static const int edges[12][2] = { + {0, 1}, + {0, 3}, + {0, 4}, + {1, 2}, + {1, 5}, + {2, 3}, + {2, 6}, + {3, 7}, + {4, 5}, + {4, 7}, + {5, 6}, + {6, 7} + }; + static const int faces[6][4] = { + {0, 3, 2, 1}, + {0, 1, 5, 4}, + {0, 4, 7, 3}, + {1, 2, 6, 5}, + {2, 3, 7, 6}, + {4, 5, 6, 7} + }; + + if (order > 0) { + point(0, 0) = -1; + point(0, 1) = -1; + point(0, 2) = -1; + point(1, 0) = 1; + point(1, 1) = -1; + point(1, 2) = -1; + point(2, 0) = 1; + point(2, 1) = 1; + point(2, 2) = -1; + point(3, 0) = -1; + point(3, 1) = 1; + point(3, 2) = -1; + + point(4, 0) = -1; + point(4, 1) = -1; + point(4, 2) = 1; + point(5, 0) = 1; + point(5, 1) = -1; + point(5, 2) = 1; + point(6, 0) = 1; + point(6, 1) = 1; + point(6, 2) = 1; + point(7, 0) = -1; + point(7, 1) = 1; + point(7, 2) = 1; + + if (order > 1) { + int index = 8; + for (int iedge=0; iedge<12; iedge++) { + int p0 = edges[iedge][0]; + int p1 = edges[iedge][1]; + for (int i = 1; i < order; i++, index++) { + point(index, 0) = point(p0, 0) + i*(point(p1,0)-point(p0,0))/order; + point(index, 1) = point(p0, 1) + i*(point(p1,1)-point(p0,1))/order; + point(index, 2) = point(p0, 2) + i*(point(p1,2)-point(p0,2))/order; + } + } + + fullMatrix<double> fp = gmshGeneratePointsQuad(order - 2, false); + fp.scale(1. - 2./order); + for (int iface=0; iface<6; iface++) { + int p0 = faces[iface][0]; + int p1 = faces[iface][1]; + int p2 = faces[iface][2]; + int p3 = faces[iface][3]; + for (int i=0;i<fp.size1();i++, index++){ + const double u = fp(i,0); + const double v = fp(i,1); + const double newU = + 0.25*(1.-u)*(1.-v)*point(p0,0) + + 0.25*(1.+u)*(1.-v)*point(p1,0) + + 0.25*(1.+u)*(1.+v)*point(p2,0) + + 0.25*(1.-u)*(1.+v)*point(p3,0) ; + const double newV = + 0.25*(1.-u)*(1.-v)*point(p0,1) + + 0.25*(1.+u)*(1.-v)*point(p1,1) + + 0.25*(1.+u)*(1.+v)*point(p2,1) + + 0.25*(1.-u)*(1.+v)*point(p3,1) ; + const double newW = + 0.25*(1.-u)*(1.-v)*point(p0,2) + + 0.25*(1.+u)*(1.-v)*point(p1,2) + + 0.25*(1.+u)*(1.+v)*point(p2,2) + + 0.25*(1.-u)*(1.+v)*point(p3,2) ; + point(index, 0) = newU; + point(index, 1) = newV; + point(index, 2) = newW; + } + } + if (!serendip) { + fullMatrix<double> inner = gmshGeneratePointsHex(order - 2, false); + inner.scale(1. - 2./order); + point.copy(inner, 0, nbPoints - index, 0, 3, index, 0); + } + } + } + else if (order == 0){ + point(0, 0) = 0; + point(0, 1) = 0; + point(0, 2) = 0; + } + return point; +} + + + +static fullMatrix<double> gmshGeneratePointsPyramid(int order, bool serendip) +{ + int nbPoints = (order+1)*((order+1)+1)*(2*(order+1)+1)/6; + + // Remove volume points if incomplete basis + if (serendip && order > 2) nbPoints -= (order-2)*((order-2)+1)*(2*(order-2)+1)/6; + + fullMatrix<double> points(nbPoints, 3); + + static const int edges[8][2] = { + {0, 1}, + {0, 3}, + {0, 4}, + {1, 2}, + {1, 4}, + {2, 3}, + {2, 4}, + {3, 4}, + }; + static const int faces[5][4] = { + {0, 1, 4, -1}, + {3, 0, 4, -1}, + {1, 2, 4, -1}, + {2, 3, 4, -1}, + {0, 3, 2, 1} + }; + + if (order == 0) { + points(0,0) = 0.0; + points(0,1) = 0.0; + points(0,2) = 0.0; + return points; + } + + // Principal vertices of the pyramid + points(0,0) = -1.0; points(0,1) = -1.0; points(0,2) = 0.0; + points(1,0) = 1.0; points(1,1) = -1.0; points(1,2) = 0.0; + points(2,0) = 1.0; points(2,1) = 1.0; points(2,2) = 0.0; + points(3,0) = -1.0; points(3,1) = 1.0; points(3,2) = 0.0; + points(4,0) = 0.0; points(4,1) = 0.0; points(4,2) = 1.0; + + if (order > 1) { + int p = 5; + + // Edges + for (int e = 0; e < 8; e++) { + double vec[3]; + vec[0] = points(edges[e][1],0) - points(edges[e][0],0); + vec[1] = points(edges[e][1],1) - points(edges[e][0],1); + vec[2] = points(edges[e][1],2) - points(edges[e][0],2); + for (int i = 0; i < order - 1; i++) { + points(p,0) = points(edges[e][0],0) + vec[0]/order * (i+1); + points(p,1) = points(edges[e][0],1) + vec[1]/order * (i+1); + points(p,2) = points(edges[e][0],2) + vec[2]/order * (i+1); + p++; + } + } + + // Faces + for (int f = 0; f < 4; f++) { + fullMatrix<double> fp = gmshGeneratePointsTriangle(order, false); + + fullVector<double> u(4); + fullVector<double> v(4); + fullVector<double> w(4); + fullVector<double> y(4); + + fullVector<double> up(4); + fullVector<double> vp(4); + fullVector<double> wp(4); + fullVector<double> yp(4); + + for (int c = 0; c < 3; c++) { + u(c) = fp(0,c); + v(c) = fp(1,c); + w(c) = fp(2,c); + up(c) = points(faces[f][0],c); + vp(c) = points(faces[f][1],c); + wp(c) = points(faces[f][2],c); + } + + u(2) = 0.0; + v(2) = 0.0; + w(2) = 0.0; + u(3) = 1.0; + v(3) = 1.0; + w(3) = 1.0; + + y(0) = u(0) + ((v(1)-u(1))*(w(2)-u(2)) - (v(2)-u(2))*(w(1)-u(1))); + y(1) = u(1) + ((v(2)-u(2))*(w(0)-u(0)) - (v(0)-u(0))*(w(2)-u(2))); + y(2) = u(2) + ((v(0)-u(0))*(w(1)-u(1)) - (v(1)-u(1))*(w(0)-u(0))); + y(3) = 1.0; + + up(3) = 1.0; + vp(3) = 1.0; + wp(3) = 1.0; + + yp(0) = up(0) + ((vp(1)-up(1))*(wp(2)-up(2)) - (vp(2)-up(2))*(wp(1)-up(1))); + yp(1) = up(1) + ((vp(2)-up(2))*(wp(0)-up(0)) - (vp(0)-up(0))*(wp(2)-up(2))); + yp(2) = up(2) + ((vp(0)-up(0))*(wp(1)-up(1)) - (vp(1)-up(1))*(wp(0)-up(0))); + yp(3) = 1.0; + + fullMatrix<double> M(4,4); + fullMatrix<double> Mp(4,4); + + M(0,0) = u(0); M(0,1) = v(0); M(0,2) = w(0); M(0,3) = y(0); + M(1,0) = u(1); M(1,1) = v(1); M(1,2) = w(1); M(1,3) = y(1); + M(2,0) = u(2); M(2,1) = v(2); M(2,2) = w(2); M(2,3) = y(2); + M(3,0) = u(3); M(3,1) = v(3); M(3,2) = w(3); M(3,3) = y(3); + + Mp(0,0) = up(0); Mp(0,1) = vp(0); Mp(0,2) = wp(0); Mp(0,3) = yp(0); + Mp(1,0) = up(1); Mp(1,1) = vp(1); Mp(1,2) = wp(1); Mp(1,3) = yp(1); + Mp(2,0) = up(2); Mp(2,1) = vp(2); Mp(2,2) = wp(2); Mp(2,3) = yp(2); + Mp(3,0) = up(3); Mp(3,1) = vp(3); Mp(3,2) = wp(3); Mp(3,3) = yp(3); + + + M.invertInPlace(); + fullMatrix<double> T(4,4); + Mp.mult(M, T); + + for(int k = 3*order; k < fp.size1(); k++) { + fullVector<double> pnt(4); + pnt(0) = fp(k,0); + pnt(1) = fp(k,1); + pnt(2) = 0.0; + pnt(3) = 1.0; + + fullVector<double> res(4); + T.mult(pnt, res); + + points(p, 0) = res(0); + points(p, 1) = res(1); + points(p, 2) = res(2); + + p++; + + } + } + + fullMatrix<double> fpq = gmshGeneratePointsQuad(order-2, false); + fullMatrix<double> transform(2,2); + fullMatrix<double> scaled(fpq.size1(), fpq.size2()); + transform(0,0) = (order-2)/(double)order; transform(0,1) = 0.0; + transform(1,0) = 0.0; transform(1,1) = (order-2)/(double)order; + fpq.mult(transform, scaled); + + for (int i = 0; i < scaled.size1(); i++) { + points(p, 0) = scaled(i, 1); + points(p, 1) = scaled(i, 0); + points(p, 2) = 0.0; + p++; + } + + // Volume + if (!serendip and order > 2) { + fullMatrix<double> volume_points = gmshGeneratePointsPyramid(order - 3, false); + // scale to order-3/order + fullMatrix<double> T(3,3); + T(0,0) = (order - 3.0) / order; T(0,1) = 0.0; T(0,2) = 0.0; + T(1,0) = 0.0; T(1,1) = (order - 3.0) / order; T(1,2) = 0.0; + T(2,0) = 0.0; T(2,1) = 0.0; T(2,2) = (order - 3.0) / order; + fullMatrix<double> scaled(volume_points.size1(), volume_points.size2()); + volume_points.mult(T, scaled); + + // translate 1/order + for (int i = 0; i < scaled.size1(); i++) { + points(p, 0) = scaled(i,0); + points(p, 1) = scaled(i,1); + points(p, 2) = scaled(i,2) + 1.0/order; + p++; + } + } + } + return points; +} + + + +static void generate1dVertexClosure(nodalBasis::clCont &closure, int order) +{ + closure.clear(); + closure.resize(2); + closure[0].push_back(0); + closure[1].push_back(order == 0 ? 0 : 1); + closure[0].type = MSH_PNT; + closure[1].type = MSH_PNT; +} + + + +static void generate1dVertexClosureFull(nodalBasis::clCont &closure, + std::vector<int> &closureRef, int order) +{ + closure.clear(); + closure.resize(2); + closure[0].push_back(0); + if (order != 0) { + closure[0].push_back(1); + closure[1].push_back(1); + } + closure[1].push_back(0); + for (int i = 0; i < order - 1; i++) { + closure[0].push_back(2 + i); + closure[1].push_back(2 + order - 2 - i); + } + closureRef.resize(2); + closureRef[0] = 0; + closureRef[1] = 0; +} + + + +static void getFaceClosureTet(int iFace, int iSign, int iRotate, + nodalBasis::closure &closure, int order) +{ + closure.clear(); + closure.resize((order + 1) * (order + 2) / 2); + closure.type = nodalBasis::getTag(TYPE_TRI, order, false); + + switch (order){ + case 0: + closure[0] = 0; + break; + default: + int face[4][3] = {{-3, -2, -1}, {1, -6, 4}, {-4, 5, 3}, {6, 2, -5}}; + int order1node[4][3] = {{0, 2, 1}, {0, 1, 3}, {0, 3, 2}, {3, 1, 2}}; + for (int i = 0; i < 3; ++i){ + int k = (3 + (iSign * i) + iRotate) % 3; //- iSign * iRotate + closure[i] = order1node[iFace][k]; + } + for (int i = 0;i < 3; ++i){ + int edgenumber = iSign * + face[iFace][(6 + i * iSign + (-1 + iSign) / 2 + iRotate) % 3]; //- iSign * iRotate + for (int k = 0; k < (order - 1); k++){ + if (edgenumber > 0) + closure[3 + i * (order - 1) + k] = + 4 + (edgenumber - 1) * (order - 1) + k; + else + closure[3 + i * (order - 1) + k] = + 4 + (-edgenumber) * (order - 1) - 1 - k; + } + } + int fi = 3 + 3 * (order - 1); + int ti = 4 + 6 * (order - 1); + int ndofff = (order - 3 + 2) * (order - 3 + 1) / 2; + ti = ti + iFace * ndofff; + for (int k = 0; k < order / 3; k++){ + int orderint = order - 3 - k * 3; + if (orderint > 0){ + for (int ci = 0; ci < 3 ; ci++){ + int shift = (3 + iSign * ci + iRotate) % 3; //- iSign * iRotate + closure[fi + ci] = ti + shift; + } + fi = fi + 3; ti = ti + 3; + for (int l = 0; l < orderint - 1; l++){ + for (int ei = 0; ei < 3; ei++){ + int edgenumber = (6 + ei * iSign + (-1 + iSign) / 2 + iRotate) % 3; + //- iSign * iRotate + if (iSign > 0) + closure[fi + ei * (orderint - 1) + l] = + ti + edgenumber * (orderint - 1) + l; + else + closure[fi + ei * (orderint - 1) + l] = + ti + (1 + edgenumber) * (orderint - 1) - 1 - l; + } + } + fi = fi + 3 * (orderint - 1); ti = ti + 3 * (orderint - 1); + } + else { + closure[fi] = ti; + ti++; + fi++; + } + } + break; + } +} + + + +static void generate2dEdgeClosureFull(nodalBasis::clCont &closure, + std::vector<int> &closureRef, + int order, int nNod, bool serendip) +{ + closure.clear(); + closure.resize(2*nNod); + closureRef.resize(2*nNod); + int shift = 0; + for (int corder = order; corder>=0; corder -= (nNod == 3 ? 3 : 2)) { + if (corder == 0) { + for (int r = 0; r < nNod ; r++){ + closure[r].push_back(shift); + closure[r+nNod].push_back(shift); + } + break; + } + for (int r = 0; r < nNod ; r++){ + for (int j = 0; j < nNod; j++) { + closure[r].push_back(shift + (r + j) % nNod); + closure[r + nNod].push_back(shift + (r - j + 1 + nNod) % nNod); + } + } + shift += nNod; + int n = nNod*(corder-1); + for (int r = 0; r < nNod ; r++){ + for (int j = 0; j < n; j++){ + closure[r].push_back(shift + (j + (corder - 1) * r) % n); + closure[r + nNod].push_back(shift + (n - j - 1 + (corder - 1) * (r + 1)) % n); + } + } + shift += n; + if (serendip) break; + } + for (int r = 0; r < nNod*2 ; r++) { + closure[r].type = nodalBasis::getTag(TYPE_LIN, order); + closureRef[r] = 0; + } +} + + + +static void addEdgeNodes(nodalBasis::clCont &closureFull, const int *edges, int order) +{ + if (order < 2) + return; + int numNodes = 0; + for (int i = 0; edges[i] >= 0; ++i) { + numNodes = std::max(numNodes, edges[i] + 1); + } + std::vector<std::vector<int> > nodes2edges(numNodes, std::vector<int>(numNodes, -1)); + for (int i = 0; edges[i] >= 0; i += 2) { + nodes2edges[edges[i]][edges[i + 1]] = i; + nodes2edges[edges[i + 1]][edges[i]] = i + 1; + } + for (unsigned int iClosure = 0; iClosure < closureFull.size(); iClosure++) { + std::vector<int> &cl = closureFull[iClosure]; + for (int iEdge = 0; edges[iEdge] >= 0; iEdge += 2) { + if (cl.empty()) + continue; + int n0 = cl[edges[iEdge]]; + int n1 = cl[edges[iEdge + 1]]; + int oEdge = nodes2edges[n0][n1]; + if (oEdge == -1) + Msg::Error("invalid p1 closure or invalid edges list"); + for (int i = 0 ; i < order - 1; i++) + cl.push_back(numNodes + oEdge/2 * (order - 1) + ((oEdge % 2) ? order - 2 - i : i)); + } + } +} + + + +static void generateFaceClosureTet(nodalBasis::clCont &closure, int order) +{ + closure.clear(); + for (int iRotate = 0; iRotate < 3; iRotate++){ + for (int iSign = 1; iSign >= -1; iSign -= 2){ + for (int iFace = 0; iFace < 4; iFace++){ + nodalBasis::closure closure_face; + getFaceClosureTet(iFace, iSign, iRotate, closure_face, order); + closure.push_back(closure_face); + } + } + } +} + + + +static void generateFaceClosureTetFull(nodalBasis::clCont &closureFull, + std::vector<int> &closureRef, + int order, bool serendip) +{ + closureFull.clear(); + //input : + static const short int faces[4][3] = {{0,1,2}, {0,3,1}, {0,2,3}, {3,2,1}}; + static const int edges[] = {0, 1, 1, 2, 2, 0, 3, 0, 3, 2, 3, 1, -1}; + static const int faceOrientation[6] = {0,1,2,5,3,4}; + closureFull.resize(24); + closureRef.resize(24); + for (int i = 0; i < 24; i ++) + closureRef[i] = 0; + if (order == 0) { + for (int i = 0; i < 24; i ++) { + closureFull[i].push_back(0); + } + return; + } + //Mapping for the p1 nodes + nodalBasis::clCont closure; + generateFaceClosureTet(closure, 1); + for (unsigned int i = 0; i < closureFull.size(); i++) { + std::vector<int> &clFull = closureFull[i]; + std::vector<int> &cl = closure[i]; + clFull.resize(4, -1); + closureRef[i] = 0; + for (unsigned int j = 0; j < cl.size(); j ++) + clFull[closure[0][j]] = cl[j]; + for (int j = 0; j < 4; j ++) + if (clFull[j] == -1) + clFull[j] = (6 - clFull[(j + 1) % 4] - clFull[(j + 2) % 4] - clFull[(j + 3) % 4]); + } + int nodes2Faces[4][4][4]; + for (int i = 0; i < 4; i++) { + for (int iRotate = 0; iRotate < 3; iRotate ++) { + short int n0 = faces[i][(3 - iRotate) % 3]; + short int n1 = faces[i][(4 - iRotate) % 3]; + short int n2 = faces[i][(5 - iRotate) % 3]; + nodes2Faces[n0][n1][n2] = i * 6 + iRotate; + nodes2Faces[n0][n2][n1] = i * 6 + iRotate + 3; + } + } + nodalBasis::clCont closureTriangles; + std::vector<int> closureTrianglesRef; + if (order >= 3) + generate2dEdgeClosureFull(closureTriangles, closureTrianglesRef, order - 3, 3, false); + addEdgeNodes(closureFull, edges, order); + for (unsigned int iClosure = 0; iClosure < closureFull.size(); iClosure++) { + //faces + std::vector<int> &cl = closureFull[iClosure]; + if (order >= 3) { + for (int iFace = 0; iFace < 4; iFace ++) { + int n0 = cl[faces[iFace][0]]; + int n1 = cl[faces[iFace][1]]; + int n2 = cl[faces[iFace][2]]; + short int id = nodes2Faces[n0][n1][n2]; + short int iTriClosure = faceOrientation [id % 6]; + short int idFace = id/6; + int nOnFace = closureTriangles[iTriClosure].size(); + for (int i = 0; i < nOnFace; i++) { + cl.push_back(4 + 6 * (order - 1) + idFace * nOnFace + + closureTriangles[iTriClosure][i]); + } + } + } + } + if (order >= 4 && !serendip) { + nodalBasis::clCont insideClosure; + std::vector<int> fakeClosureRef; + generateFaceClosureTetFull(insideClosure, fakeClosureRef, order - 4, false); + for (unsigned int i = 0; i < closureFull.size(); i ++) { + unsigned int shift = closureFull[i].size(); + for (unsigned int j = 0; j < insideClosure[i].size(); j++) + closureFull[i].push_back(insideClosure[i][j] + shift); + } + } +} + + + +void rotateHex(int iFace, int iRot, int iSign, double uI, double vI, + double &uO, double &vO, double &wO) +{ + if (iSign<0){ + double tmp=uI; + uI=vI; + vI=tmp; + } + for (int i=0; i < iRot; i++){ + double tmp=uI; + uI=-vI; + vI=tmp; + } + switch (iFace) { + case 0: uO = vI; vO = uI; wO=-1; break; + case 1: uO = uI; vO = -1; wO=vI; break; + case 2: uO =-1; vO = vI; wO=uI; break; + case 3: uO = 1; vO = uI; wO=vI; break; + case 4: uO =-uI; vO = 1; wO=vI; break; + case 5: uO =uI; vO = vI; wO=1; break; + } +} + + + +void rotateHexFull(int iFace, int iRot, int iSign, double uI, double vI, double wI, double &uO, double &vO, double &wO) +{ + switch (iFace) { + case 0: uO = uI; vO = vI; wO = wI; break; + case 1: uO = wI; vO = uI; wO = vI; break; + case 2: uO = vI; vO = wI; wO = uI; break; + case 3: uO = wI; vO = vI; wO =-uI; break; + case 4: uO = wI; vO =-uI; wO =-vI; break; + case 5: uO = vI; vO = uI; wO =-wI; break; + } + for (int i = 0; i < iRot; i++){ + double tmp = uO; + uO = -vO; + vO = tmp; + } + if (iSign<0){ + double tmp = uO; + uO = vO; + vO = tmp; + } +} + + + +inline static double pow2(double x) +{ + return x * x; +} + +/* +static void checkClosure(int tag) { + printf("TYPE = %i\n", tag); + const nodalBasis &fs = *nodalBases::find(tag); + for (int i = 0; i < fs.closures.size(); ++i) { + const std::vector<int> &clRef = fs.closures[fs.closureRef[i]]; + const std::vector<int> &cl = fs.closures[i]; + const std::vector<int> &clFull = fs.fullClosures[i]; + printf("i = %i\n", i); + for (int j = 0; j < cl.size(); ++j) { + printf("%3i ", clFull[clRef[j]]); + } + printf("\n"); + for (int j = 0; j < cl.size(); ++j) { + printf("%3i ", cl[j]); + } + printf("\n"); + } +} +*/ + + + +static void generateFaceClosureHex(nodalBasis::clCont &closure, int order, + bool serendip, const fullMatrix<double> &points) +{ + closure.clear(); + const nodalBasis &fsFace = *BasisFactory::create(nodalBasis::getTag(TYPE_QUA, order, serendip)); + for (int iRotate = 0; iRotate < 4; iRotate++){ + for (int iSign = 1; iSign >= -1; iSign -= 2){ + for (int iFace = 0; iFace < 6; iFace++) { + nodalBasis::closure cl; + cl.type = fsFace.type; + cl.resize(fsFace.points.size1()); + for (unsigned int iNode = 0; iNode < cl.size(); ++iNode) { + double u,v,w; + rotateHex(iFace, iRotate, iSign, fsFace.points(iNode, 0), + fsFace.points(iNode, 1), u, v, w); + cl[iNode] = 0; + double D = std::numeric_limits<double>::max(); + for (int jNode = 0; jNode < points.size1(); ++jNode) { + double d = pow2(points(jNode, 0) - u) + pow2(points(jNode, 1) - v) + + pow2(points(jNode, 2) - w); + if (d < D) { + cl[iNode] = jNode; + D = d; + } + } + } + closure.push_back(cl); + } + } + } +} + + + +static void generateFaceClosureHexFull(nodalBasis::clCont &closure, + std::vector<int> &closureRef, + int order, bool serendip, + const fullMatrix<double> &points) +{ + closure.clear(); + int clId = 0; + for (int iRotate = 0; iRotate < 4; iRotate++){ + for (int iSign = 1; iSign >= -1; iSign -= 2){ + for (int iFace = 0; iFace < 6; iFace++) { + nodalBasis::closure cl; + cl.resize(points.size1()); + for (int iNode = 0; iNode < points.size1(); ++iNode) { + double u,v,w; + rotateHexFull(iFace, iRotate, iSign, points(iNode, 0), points(iNode, 1), + points(iNode, 2), u, v, w); + int J = 0; + double D = std::numeric_limits<double>::max(); + for (int jNode = 0; jNode < points.size1(); ++jNode) { + double d = pow2(points(jNode, 0) - u) + pow2(points(jNode, 1) - v) + + pow2(points(jNode, 2) - w); + if (d < D) { + J = jNode; + D = d; + } + } + cl[J] = iNode; + } + closure.push_back(cl); + closureRef.push_back(0); + clId ++; + } + } + } +} + + + +static void getFaceClosurePrism(int iFace, int iSign, int iRotate, + nodalBasis::closure &closure, int order) +{ + if (order > 2) + Msg::Error("FaceClosure not implemented for prisms of order %d",order); + bool isTriangle = iFace<2; + int nNodes = isTriangle ? (order+1)*(order+2)/2 : (order+1)*(order+1); + closure.clear(); + if (isTriangle && iRotate > 2) return; + closure.resize(nNodes); + if (order==0) { + closure[0] = 0; + return; + } + int order1node[5][4] = {{0, 2, 1, -1}, {3, 4, 5, -1}, {0, 1, 4, 3}, {0, 3, 5, 2}, + {1, 2, 5, 4}}; + int order2node[5][5] = {{7, 9, 6, -1, -1}, {12, 14, 13, -1, -1}, {6, 10, 12, 8, 15}, + {8, 13, 11, 7, 16}, {9, 11, 14, 10, 17}}; + // int order2node[5][4] = {{7, 9, 6, -1}, {12, 14, 13, -1}, {6, 10, 12, 8}, + // {8, 13, 11, 7}, {9, 11, 14, 10}}; + int nVertex = isTriangle ? 3 : 4; + closure.type = nodalBasis::getTag(isTriangle ? TYPE_TRI : TYPE_QUA, order); + for (int i = 0; i < nVertex; ++i){ + int k = (nVertex + (iSign * i) + iRotate) % nVertex; //- iSign * iRotate + closure[i] = order1node[iFace][k]; + } + if (order==2) { + for (int i = 0; i < nVertex; ++i){ + int k = (nVertex + (iSign==-1?-1:0) + (iSign * i) + iRotate) % nVertex; + //- iSign * iRotate + closure[nVertex+i] = order2node[iFace][k]; + } + if (!isTriangle) + closure[nNodes-1] = order2node[iFace][4]; // center + } +} + + + +static void generateFaceClosurePrism(nodalBasis::clCont &closure, int order) +{ + closure.clear(); + for (int iRotate = 0; iRotate < 4; iRotate++){ + for (int iSign = 1; iSign >= -1; iSign -= 2){ + for (int iFace = 0; iFace < 5; iFace++){ + nodalBasis::closure closure_face; + getFaceClosurePrism(iFace, iSign, iRotate, closure_face, order); + closure.push_back(closure_face); + } + } + } +} + + + +static void generateFaceClosurePrismFull(nodalBasis::clCont &closureFull, + std::vector<int> &closureRef, int order) +{ + nodalBasis::clCont closure; + closureFull.clear(); + closureFull.resize(40); + closureRef.resize(40); + generateFaceClosurePrism(closure, 1); + int ref3 = -1, ref4a = -1, ref4b = -1; + for (unsigned int i = 0; i < closure.size(); i++) { + std::vector<int> &clFull = closureFull[i]; + std::vector<int> &cl = closure[i]; + if (cl.size() == 0) + continue; + clFull.resize(6, -1); + int &ref = cl.size() == 3 ? ref3 : (cl[0] / 3 + cl[1] / 3) % 2 ? ref4b : ref4a; + if (ref == -1) + ref = i; + closureRef[i] = ref; + for (unsigned int j = 0; j < cl.size(); j ++) + clFull[closure[ref][j]] = cl[j]; + for (int j = 0; j < 6; j ++) { + if (clFull[j] == -1) { + int k = ((j / 3) + 1) % 2 * 3; + int sum = (clFull[k + (j + 1) % 3] + clFull[k + (j + 2) % 3]); + clFull[j] = ((sum / 6 + 1) % 2) * 3 + (12 - sum) % 3; + } + } + } + static const int edges[] = {0, 1, 0, 2, 0, 3, 1, 2, 1, 4, 2, 5, + 3, 4, 3, 5, 4, 5, -1}; + addEdgeNodes(closureFull, edges, order); + if ( order < 2 ) + return; + // face center nodes for p2 prism + static const int faces[5][4] = {{0, 2, 1, -1}, {3, 4, 5, -1}, {0, 1, 4, 3}, + {0, 3, 5, 2}, {1, 2, 5, 4}}; + + if ( order == 2 ) { + int nextFaceNode = 15; + int numFaces = 5; + int numFaceNodes = 4; + std::map<int,int> nodeSum2Face; + for (int iFace = 0; iFace < numFaces ; iFace ++) { + int nodeSum = 0; + for (int iNode = 0; iNode < numFaceNodes; iNode++ ) { + nodeSum += faces[iFace][iNode]; + } + nodeSum2Face[nodeSum] = iFace; + } + for (unsigned int i = 0; i < closureFull.size(); i++ ) { + if (closureFull[i].empty()) + continue; + for (int iFace = 0; iFace < numFaces; iFace++ ) { + int nodeSum = 0; + for (int iNode = 0; iNode < numFaceNodes; iNode++) + nodeSum += faces[iFace][iNode] < 0 ? faces[iFace][iNode] : + closureFull[i][ faces[iFace][iNode] ]; + std::map<int,int>::iterator it = nodeSum2Face.find(nodeSum); + if (it == nodeSum2Face.end() ) + Msg::Error("Prism face not found"); + int mappedFaceId = it->second; + if ( mappedFaceId > 1) { + closureFull[i].push_back(nextFaceNode + mappedFaceId - 2); + } + } + } + } else { + Msg::Error("FaceClosureFull not implemented for prisms of order %d",order); + } + +} + + + +static void generate2dEdgeClosure(nodalBasis::clCont &closure, int order, int nNod = 3) +{ + closure.clear(); + closure.resize(2*nNod); + for (int j = 0; j < nNod ; j++){ + closure[j].push_back(j); + closure[j].push_back((j+1)%nNod); + closure[nNod+j].push_back((j+1)%nNod); + closure[nNod+j].push_back(j); + for (int i=0; i < order-1; i++){ + closure[j].push_back( nNod + (order-1)*j + i ); + closure[nNod+j].push_back(nNod + (order-1)*(j+1) -i -1); + } + closure[j].type = closure[nNod+j].type = nodalBasis::getTag(TYPE_LIN, order); + } +} + + + +static void generateClosureOrder0(nodalBasis::clCont &closure, int nb) +{ + closure.clear(); + closure.resize(nb); + for (int i=0; i < nb; i++) { + closure[i].push_back(0); + closure[i].type = MSH_PNT; + } +} + + + +nodalBasis::nodalBasis(int tag) +{ + + type = tag; + + switch (tag) { + case MSH_PNT : parentType = TYPE_PNT; order = 0; serendip = false; break; + case MSH_LIN_1 : parentType = TYPE_LIN; order = 0; serendip = false; break; + case MSH_LIN_2 : parentType = TYPE_LIN; order = 1; serendip = false; break; + case MSH_LIN_3 : parentType = TYPE_LIN; order = 2; serendip = false; break; + case MSH_LIN_4 : parentType = TYPE_LIN; order = 3; serendip = false; break; + case MSH_LIN_5 : parentType = TYPE_LIN; order = 4; serendip = false; break; + case MSH_LIN_6 : parentType = TYPE_LIN; order = 5; serendip = false; break; + case MSH_LIN_7 : parentType = TYPE_LIN; order = 6; serendip = false; break; + case MSH_LIN_8 : parentType = TYPE_LIN; order = 7; serendip = false; break; + case MSH_LIN_9 : parentType = TYPE_LIN; order = 8; serendip = false; break; + case MSH_LIN_10 : parentType = TYPE_LIN; order = 9; serendip = false; break; + case MSH_LIN_11 : parentType = TYPE_LIN; order = 10;serendip = false; break; + case MSH_TRI_1 : parentType = TYPE_TRI; order = 0; serendip = false; break; + case MSH_TRI_3 : parentType = TYPE_TRI; order = 1; serendip = false; break; + case MSH_TRI_6 : parentType = TYPE_TRI; order = 2; serendip = false; break; + case MSH_TRI_10 : parentType = TYPE_TRI; order = 3; serendip = false; break; + case MSH_TRI_15 : parentType = TYPE_TRI; order = 4; serendip = false; break; + case MSH_TRI_21 : parentType = TYPE_TRI; order = 5; serendip = false; break; + case MSH_TRI_28 : parentType = TYPE_TRI; order = 6; serendip = false; break; + case MSH_TRI_36 : parentType = TYPE_TRI; order = 7; serendip = false; break; + case MSH_TRI_45 : parentType = TYPE_TRI; order = 8; serendip = false; break; + case MSH_TRI_55 : parentType = TYPE_TRI; order = 9; serendip = false; break; + case MSH_TRI_66 : parentType = TYPE_TRI; order = 10;serendip = false; break; + case MSH_TRI_9 : parentType = TYPE_TRI; order = 3; serendip = true; break; + case MSH_TRI_12 : parentType = TYPE_TRI; order = 4; serendip = true; break; + case MSH_TRI_15I : parentType = TYPE_TRI; order = 5; serendip = true; break; + case MSH_TRI_18 : parentType = TYPE_TRI; order = 6; serendip = true; break; + case MSH_TRI_21I : parentType = TYPE_TRI; order = 7; serendip = true; break; + case MSH_TRI_24 : parentType = TYPE_TRI; order = 8; serendip = true; break; + case MSH_TRI_27 : parentType = TYPE_TRI; order = 9; serendip = true; break; + case MSH_TRI_30 : parentType = TYPE_TRI; order = 10;serendip = true; break; + case MSH_TET_1 : parentType = TYPE_TET; order = 0; serendip = false; break; + case MSH_TET_4 : parentType = TYPE_TET; order = 1; serendip = false; break; + case MSH_TET_10 : parentType = TYPE_TET; order = 2; serendip = false; break; + case MSH_TET_20 : parentType = TYPE_TET; order = 3; serendip = false; break; + case MSH_TET_35 : parentType = TYPE_TET; order = 4; serendip = false; break; + case MSH_TET_56 : parentType = TYPE_TET; order = 5; serendip = false; break; + case MSH_TET_84 : parentType = TYPE_TET; order = 6; serendip = false; break; + case MSH_TET_120 : parentType = TYPE_TET; order = 7; serendip = false; break; + case MSH_TET_165 : parentType = TYPE_TET; order = 8; serendip = false; break; + case MSH_TET_220 : parentType = TYPE_TET; order = 9; serendip = false; break; + case MSH_TET_286 : parentType = TYPE_TET; order = 10;serendip = false; break; + case MSH_TET_34 : parentType = TYPE_TET; order = 4; serendip = true; break; + case MSH_TET_52 : parentType = TYPE_TET; order = 5; serendip = true; break; + case MSH_TET_74 : parentType = TYPE_TET; order = 6; serendip = true; break; + case MSH_TET_100 : parentType = TYPE_TET; order = 7; serendip = true; break; + case MSH_TET_130 : parentType = TYPE_TET; order = 8; serendip = true; break; + case MSH_TET_164 : parentType = TYPE_TET; order = 9; serendip = true; break; + case MSH_TET_202 : parentType = TYPE_TET; order = 10;serendip = true; break; + case MSH_QUA_1 : parentType = TYPE_QUA; order = 0; serendip = false; break; + case MSH_QUA_4 : parentType = TYPE_QUA; order = 1; serendip = false; break; + case MSH_QUA_9 : parentType = TYPE_QUA; order = 2; serendip = false; break; + case MSH_QUA_16 : parentType = TYPE_QUA; order = 3; serendip = false; break; + case MSH_QUA_25 : parentType = TYPE_QUA; order = 4; serendip = false; break; + case MSH_QUA_36 : parentType = TYPE_QUA; order = 5; serendip = false; break; + case MSH_QUA_49 : parentType = TYPE_QUA; order = 6; serendip = false; break; + case MSH_QUA_64 : parentType = TYPE_QUA; order = 7; serendip = false; break; + case MSH_QUA_81 : parentType = TYPE_QUA; order = 8; serendip = false; break; + case MSH_QUA_100 : parentType = TYPE_QUA; order = 9; serendip = false; break; + case MSH_QUA_121 : parentType = TYPE_QUA; order = 10;serendip = false; break; + case MSH_QUA_8 : parentType = TYPE_QUA; order = 2; serendip = true; break; + case MSH_QUA_12 : parentType = TYPE_QUA; order = 3; serendip = true; break; + case MSH_QUA_16I : parentType = TYPE_QUA; order = 4; serendip = true; break; + case MSH_QUA_20 : parentType = TYPE_QUA; order = 5; serendip = true; break; + case MSH_QUA_24 : parentType = TYPE_QUA; order = 6; serendip = true; break; + case MSH_QUA_28 : parentType = TYPE_QUA; order = 7; serendip = true; break; + case MSH_QUA_32 : parentType = TYPE_QUA; order = 8; serendip = true; break; + case MSH_QUA_36I : parentType = TYPE_QUA; order = 9; serendip = true; break; + case MSH_QUA_40 : parentType = TYPE_QUA; order = 10;serendip = true; break; + case MSH_PRI_1 : parentType = TYPE_PRI; order = 0; serendip = false; break; + case MSH_PRI_6 : parentType = TYPE_PRI; order = 1; serendip = false; break; + case MSH_PRI_18 : parentType = TYPE_PRI; order = 2; serendip = false; break; + case MSH_PRI_40 : parentType = TYPE_PRI; order = 3; serendip = false; break; + case MSH_PRI_75 : parentType = TYPE_PRI; order = 4; serendip = false; break; + case MSH_PRI_126 : parentType = TYPE_PRI; order = 5; serendip = false; break; + case MSH_PRI_196 : parentType = TYPE_PRI; order = 6; serendip = false; break; + case MSH_PRI_288 : parentType = TYPE_PRI; order = 7; serendip = false; break; + case MSH_PRI_405 : parentType = TYPE_PRI; order = 8; serendip = false; break; + case MSH_PRI_550 : parentType = TYPE_PRI; order = 9; serendip = false; break; + case MSH_PRI_15 : parentType = TYPE_PRI; order = 2; serendip = true; break; + case MSH_PRI_38 : parentType = TYPE_PRI; order = 3; serendip = true; break; + case MSH_PRI_66 : parentType = TYPE_PRI; order = 4; serendip = true; break; + case MSH_PRI_102 : parentType = TYPE_PRI; order = 5; serendip = true; break; + case MSH_PRI_146 : parentType = TYPE_PRI; order = 6; serendip = true; break; + case MSH_PRI_198 : parentType = TYPE_PRI; order = 7; serendip = true; break; + case MSH_PRI_258 : parentType = TYPE_PRI; order = 8; serendip = true; break; + case MSH_PRI_326 : parentType = TYPE_PRI; order = 9; serendip = true; break; + case MSH_HEX_8 : parentType = TYPE_HEX; order = 1; serendip = false; break; + case MSH_HEX_27 : parentType = TYPE_HEX; order = 2; serendip = false; break; + case MSH_HEX_64 : parentType = TYPE_HEX; order = 3; serendip = false; break; + case MSH_HEX_125 : parentType = TYPE_HEX; order = 4; serendip = false; break; + case MSH_HEX_216 : parentType = TYPE_HEX; order = 5; serendip = false; break; + case MSH_HEX_343 : parentType = TYPE_HEX; order = 6; serendip = false; break; + case MSH_HEX_512 : parentType = TYPE_HEX; order = 7; serendip = false; break; + case MSH_HEX_729 : parentType = TYPE_HEX; order = 8; serendip = false; break; + case MSH_HEX_1000: parentType = TYPE_HEX; order = 9; serendip = false; break; + case MSH_HEX_20 : parentType = TYPE_HEX; order = 2; serendip = false; break; + case MSH_HEX_56 : parentType = TYPE_HEX; order = 3; serendip = true; break; + case MSH_HEX_98 : parentType = TYPE_HEX; order = 4; serendip = true; break; + case MSH_HEX_152 : parentType = TYPE_HEX; order = 5; serendip = true; break; + case MSH_HEX_222 : parentType = TYPE_HEX; order = 6; serendip = true; break; + case MSH_HEX_296 : parentType = TYPE_HEX; order = 7; serendip = true; break; + case MSH_HEX_386 : parentType = TYPE_HEX; order = 8; serendip = true; break; + case MSH_HEX_488 : parentType = TYPE_HEX; order = 9; serendip = true; break; + case MSH_PYR_5 : parentType = TYPE_PYR; order = 1; serendip = false; break; + case MSH_PYR_14 : parentType = TYPE_PYR; order = 2; serendip = false; break; + case MSH_PYR_30 : parentType = TYPE_PYR; order = 3; serendip = false; break; + case MSH_PYR_55 : parentType = TYPE_PYR; order = 4; serendip = false; break; + case MSH_PYR_91 : parentType = TYPE_PYR; order = 5; serendip = false; break; + case MSH_PYR_140 : parentType = TYPE_PYR; order = 6; serendip = false; break; + case MSH_PYR_204 : parentType = TYPE_PYR; order = 7; serendip = false; break; + case MSH_PYR_285 : parentType = TYPE_PYR; order = 8; serendip = false; break; + case MSH_PYR_385 : parentType = TYPE_PYR; order = 9; serendip = false; break; + case MSH_PYR_13 : parentType = TYPE_PYR; order = 2; serendip = false; break; + case MSH_PYR_29 : parentType = TYPE_PYR; order = 3; serendip = true; break; + case MSH_PYR_50 : parentType = TYPE_PYR; order = 4; serendip = true; break; + case MSH_PYR_77 : parentType = TYPE_PYR; order = 5; serendip = true; break; + case MSH_PYR_110 : parentType = TYPE_PYR; order = 6; serendip = true; break; + case MSH_PYR_149 : parentType = TYPE_PYR; order = 7; serendip = true; break; + case MSH_PYR_194 : parentType = TYPE_PYR; order = 8; serendip = true; break; + case MSH_PYR_245 : parentType = TYPE_PYR; order = 9; serendip = true; break; + default : + Msg::Error("Unknown function space %d: reverting to TET_4", tag); + parentType = TYPE_TET; order = 1; serendip = false; break; + } + + + switch (parentType) { + case TYPE_PNT : + numFaces = 1; + dimension = 0; + points = generate1DPoints(0); + break; + case TYPE_LIN : + numFaces = 2; + dimension = 1; + points = generate1DPoints(order); + generate1dVertexClosure(closures, order); + generate1dVertexClosureFull(fullClosures, closureRef, order); + break; + case TYPE_TRI : + numFaces = 3; + dimension = 2; + points = gmshGeneratePointsTriangle(order, serendip); + if (order == 0) { + generateClosureOrder0(closures, 6); + generateClosureOrder0(fullClosures, 6); + closureRef.resize(6, 0); + } + else { + generate2dEdgeClosure(closures, order); + generate2dEdgeClosureFull(fullClosures, closureRef, order, 3, serendip); + } + break; + case TYPE_QUA : + numFaces = 4; + dimension = 2; + points = gmshGeneratePointsQuad(order, serendip); + if (order == 0) { + generateClosureOrder0(closures, 8); + generateClosureOrder0(fullClosures, 8); + closureRef.resize(8, 0); + } + else { + generate2dEdgeClosure(closures, order, 4); + generate2dEdgeClosureFull(fullClosures, closureRef, order, 4, serendip); + } + break; + case TYPE_TET : + numFaces = 4; + dimension = 3; + points = gmshGeneratePointsTetrahedron(order, serendip); + if (order == 0) { + generateClosureOrder0(closures,24); + generateClosureOrder0(fullClosures, 24); + closureRef.resize(24, 0); + } + else { + generateFaceClosureTet(closures, order); + generateFaceClosureTetFull(fullClosures, closureRef, order, serendip); + } + break; + case TYPE_PRI : + numFaces = 5; + dimension = 3; + points = gmshGeneratePointsPrism(order, serendip); + if (order == 0) { + generateClosureOrder0(closures,48); + generateClosureOrder0(fullClosures,48); + closureRef.resize(48, 0); + } + else { + generateFaceClosurePrism(closures, order); + generateFaceClosurePrismFull(fullClosures, closureRef, order); + } + break; + case TYPE_HEX : + numFaces = 6; + dimension = 3; + points = gmshGeneratePointsHex(order, serendip); + generateFaceClosureHex(closures, order, serendip, points); + generateFaceClosureHexFull(fullClosures, closureRef, order, serendip, points); + break; + case TYPE_PYR : + numFaces = 5; + dimension = 3; + points = gmshGeneratePointsPyramid(order, serendip); + break; + } + +} diff --git a/Numeric/nodalBasis.h b/Numeric/nodalBasis.h index 6a283f4eb754829054f4b00202543ec22a422672..da1bc0d723db5e373bfaf0d334dec90da7b45d28 100644 --- a/Numeric/nodalBasis.h +++ b/Numeric/nodalBasis.h @@ -3,8 +3,8 @@ // See the LICENSE.txt file for license information. Please report all // bugs and problems to <gmsh@geuz.org>. -#ifndef BASIS_H -#define BASIS_H +#ifndef NODALBASIS_H +#define NODALBASIS_H #include "fullMatrix.h" #include "GmshDefines.h" @@ -16,20 +16,21 @@ class nodalBasis { bool serendip; fullMatrix<double> points; - virtual void initialize() = 0; + nodalBasis(int tag); + virtual ~nodalBasis() {} // Basis functions evaluation - inline virtual void f(double u, double v, double w, double *sf) const {Msg::Fatal("Not implemented");}; - inline virtual void f(fullMatrix<double> &coord, fullMatrix<double> &sf) const {Msg::Fatal("Not implemented");}; + virtual void f(double u, double v, double w, double *sf) const {Msg::Fatal("Not implemented");}; + virtual void f(fullMatrix<double> &coord, fullMatrix<double> &sf) const {Msg::Fatal("Not implemented");}; // Basis functions gradients evaluation - inline virtual void df(double u, double v, double w, double grads[][3]) const {Msg::Fatal("Not implemented");}; - inline virtual void df(fullMatrix<double> &coord, fullMatrix<double> &dfm) const {Msg::Fatal("Not implemented");}; + virtual void df(double u, double v, double w, double grads[][3]) const {Msg::Fatal("Not implemented");}; + virtual void df(fullMatrix<double> &coord, fullMatrix<double> &dfm) const {Msg::Fatal("Not implemented");}; - inline virtual void ddf(double u, double v, double w, double grads[][3][3]) const {Msg::Fatal("Not implemented");}; - inline virtual void dddf(double u, double v, double w, double grads[][3][3][3]) const {Msg::Fatal("Not implemented");}; + virtual void ddf(double u, double v, double w, double grads[][3][3]) const {Msg::Fatal("Not implemented");}; + virtual void dddf(double u, double v, double w, double grads[][3][3][3]) const {Msg::Fatal("Not implemented");}; - inline virtual int getNumShapeFunctions() const {Msg::Fatal("Not implemented"); return -1;} + virtual int getNumShapeFunctions() const {Msg::Fatal("Not implemented"); return -1;} class closure : public std::vector<int> { public: @@ -46,100 +47,155 @@ class nodalBasis { // quad face) clCont closures, fullClosures; std::vector<int> closureRef; - inline virtual int getClosureType(int id) const {Msg::Fatal("Not implemented"); return -1;} - inline virtual const std::vector<int> &getClosure(int id) const {Msg::Fatal("Not implemented"); std::vector<int> *ret=NULL; return *ret;} - inline virtual const std::vector<int> &getFullClosure(int id) const {Msg::Fatal("Not implemented"); std::vector<int> *ret=NULL; return *ret;} - inline virtual int getClosureId(int iFace, int iSign=1, int iRot=0) const {Msg::Fatal("Not implemented"); return -1;} - inline virtual void breakClosureId(int i, int &iFace, int &iSign, int &iRot) const {Msg::Fatal("Not implemented");iFace=-1; iSign=-1; iRot=-1;} - - static int getTag(int parentTag, int order, bool serendip = false) - { - switch (parentTag) { - case TYPE_PNT : - return MSH_PNT; - case TYPE_LIN : - switch(order) { - case 0 : return MSH_LIN_1; - case 1 : return MSH_LIN_2; - case 2 : return MSH_LIN_3; - case 3 : return MSH_LIN_4; - case 4 : return MSH_LIN_5; - case 5 : return MSH_LIN_6; - case 6 : return MSH_LIN_7; - case 7 : return MSH_LIN_8; - case 8 : return MSH_LIN_9; - case 9 : return MSH_LIN_10; - case 10: return MSH_LIN_11; - default : Msg::Error("line order %i unknown", order); return 0; - } - case TYPE_TRI : - switch(order) { - case 0 : return MSH_TRI_1; - case 1 : return MSH_TRI_3; - case 2 : return MSH_TRI_6; - case 3 : return serendip ? MSH_TRI_9 : MSH_TRI_10; - case 4 : return serendip ? MSH_TRI_12 : MSH_TRI_15; - case 5 : return serendip ? MSH_TRI_15I: MSH_TRI_21; - case 6 : return serendip ? MSH_TRI_18 : MSH_TRI_28; - case 7 : return serendip ? MSH_TRI_21I: MSH_TRI_36; - case 8 : return serendip ? MSH_TRI_24 : MSH_TRI_45; - case 9 : return serendip ? MSH_TRI_27 : MSH_TRI_55; - case 10: return serendip ? MSH_TRI_30 : MSH_TRI_66; - default : Msg::Error("triangle order %i unknown", order); return 0; - } - case TYPE_QUA : - switch(order) { - case 0 : return MSH_QUA_1; - case 1 : return MSH_QUA_4; - case 2 : return serendip ? MSH_QUA_8 : MSH_QUA_9; - case 3 : return serendip ? MSH_QUA_12 : MSH_QUA_16; - case 4 : return serendip ? MSH_QUA_16I: MSH_QUA_25; - case 5 : return serendip ? MSH_QUA_20 : MSH_QUA_36; - case 6 : return serendip ? MSH_QUA_24 : MSH_QUA_49; - case 7 : return serendip ? MSH_QUA_28 : MSH_QUA_64; - case 8 : return serendip ? MSH_QUA_32 : MSH_QUA_81; - case 9 : return serendip ? MSH_QUA_36I: MSH_QUA_100; - case 10: return serendip ? MSH_QUA_40 : MSH_QUA_121; - default : Msg::Error("quad order %i unknown", order); return 0; - } - case TYPE_TET : - switch(order) { - case 0 : return MSH_TET_1; - case 1 : return MSH_TET_4; - case 2 : return MSH_TET_10; - case 3 : return MSH_TET_20; - case 4 : return serendip ? MSH_TET_34 : MSH_TET_35; - case 5 : return serendip ? MSH_TET_52 : MSH_TET_56; - case 6 : return serendip ? MSH_TET_74 : MSH_TET_84; - case 7 : return serendip ? MSH_TET_100: MSH_TET_120; - case 8 : return serendip ? MSH_TET_130: MSH_TET_165; - case 9 : return serendip ? MSH_TET_164: MSH_TET_220; - case 10: return serendip ? MSH_TET_202: MSH_TET_286; - default : Msg::Error("terahedron order %i unknown", order); return 0; - } - case TYPE_HEX : - switch(order) { - case 1 : return MSH_HEX_8; - case 2 : return serendip ? MSH_HEX_20 : MSH_HEX_27; - case 3 : return serendip ? MSH_HEX_56 : MSH_HEX_64; - case 4 : return serendip ? MSH_HEX_98 : MSH_HEX_125; - case 5 : return serendip ? MSH_HEX_152: MSH_HEX_216; - case 6 : return serendip ? MSH_HEX_222: MSH_HEX_343; - case 7 : return serendip ? MSH_HEX_296: MSH_HEX_512; - case 8 : return serendip ? MSH_HEX_386: MSH_HEX_729; - case 9 : return serendip ? MSH_HEX_488: MSH_HEX_1000; - default : Msg::Error("hexahedron order %i unknown", order); return 0; - } - case TYPE_PRI : - switch(order) { - case 0 : return MSH_PRI_1; - case 1 : return MSH_PRI_6; - case 2 : return MSH_PRI_18; - default : Msg::Error("prism order %i unknown", order); return 0; - } - default : Msg::Error("unknown element type %i", parentTag); return 0; + + // for a given face/edge, with both a sign and a rotation, give an + // ordered list of nodes on this face/edge + virtual int getClosureType(int id) const { return closures[id].type; } + virtual const std::vector<int> &getClosure(int id) const { return closures[id]; } + virtual const std::vector<int> &getFullClosure(int id) const { return fullClosures[id]; } + inline int getClosureId(int iFace, int iSign=1, int iRot=0) const; + inline void breakClosureId(int i, int &iFace, int &iSign, int &iRot) const; + + static inline int getTag(int parentTag, int order, bool serendip = false); + +}; + + + +inline int nodalBasis::getClosureId(int iFace, int iSign, int iRot) const +{ + return iFace + numFaces*(iSign == 1 ? 0 : 1) + 2*numFaces*iRot; +} + + + +inline void nodalBasis::breakClosureId(int i, int &iFace, int &iSign, int &iRot) const +{ + iFace = i % numFaces; + i = (i - iFace)/numFaces; + iSign = i % 2; + iRot = (i - iSign) / 2; +} + + + +inline int nodalBasis::getTag(int parentTag, int order, bool serendip) +{ + switch (parentTag) { + case TYPE_PNT : + return MSH_PNT; + case TYPE_LIN : + switch(order) { + case 0 : return MSH_LIN_1; + case 1 : return MSH_LIN_2; + case 2 : return MSH_LIN_3; + case 3 : return MSH_LIN_4; + case 4 : return MSH_LIN_5; + case 5 : return MSH_LIN_6; + case 6 : return MSH_LIN_7; + case 7 : return MSH_LIN_8; + case 8 : return MSH_LIN_9; + case 9 : return MSH_LIN_10; + case 10: return MSH_LIN_11; + default : Msg::Error("line order %i unknown", order); return 0; + } + break; + case TYPE_TRI : + switch(order) { + case 0 : return MSH_TRI_1; + case 1 : return MSH_TRI_3; + case 2 : return MSH_TRI_6; + case 3 : return serendip ? MSH_TRI_9 : MSH_TRI_10; + case 4 : return serendip ? MSH_TRI_12 : MSH_TRI_15; + case 5 : return serendip ? MSH_TRI_15I: MSH_TRI_21; + case 6 : return serendip ? MSH_TRI_18 : MSH_TRI_28; + case 7 : return serendip ? MSH_TRI_21I: MSH_TRI_36; + case 8 : return serendip ? MSH_TRI_24 : MSH_TRI_45; + case 9 : return serendip ? MSH_TRI_27 : MSH_TRI_55; + case 10: return serendip ? MSH_TRI_30 : MSH_TRI_66; + default : Msg::Error("triangle order %i unknown", order); return 0; + } + break; + case TYPE_QUA : + switch(order) { + case 0 : return MSH_QUA_1; + case 1 : return MSH_QUA_4; + case 2 : return serendip ? MSH_QUA_8 : MSH_QUA_9; + case 3 : return serendip ? MSH_QUA_12 : MSH_QUA_16; + case 4 : return serendip ? MSH_QUA_16I: MSH_QUA_25; + case 5 : return serendip ? MSH_QUA_20 : MSH_QUA_36; + case 6 : return serendip ? MSH_QUA_24 : MSH_QUA_49; + case 7 : return serendip ? MSH_QUA_28 : MSH_QUA_64; + case 8 : return serendip ? MSH_QUA_32 : MSH_QUA_81; + case 9 : return serendip ? MSH_QUA_36I: MSH_QUA_100; + case 10: return serendip ? MSH_QUA_40 : MSH_QUA_121; + default : Msg::Error("quad order %i unknown", order); return 0; + } + break; + case TYPE_TET : + switch(order) { + case 0 : return MSH_TET_1; + case 1 : return MSH_TET_4; + case 2 : return MSH_TET_10; + case 3 : return MSH_TET_20; + case 4 : return serendip ? MSH_TET_34 : MSH_TET_35; + case 5 : return serendip ? MSH_TET_52 : MSH_TET_56; + case 6 : return serendip ? MSH_TET_74 : MSH_TET_84; + case 7 : return serendip ? MSH_TET_100: MSH_TET_120; + case 8 : return serendip ? MSH_TET_130: MSH_TET_165; + case 9 : return serendip ? MSH_TET_164: MSH_TET_220; + case 10: return serendip ? MSH_TET_202: MSH_TET_286; + default : Msg::Error("terahedron order %i unknown", order); return 0; + } + break; + case TYPE_HEX : + switch(order) { + case 1 : return MSH_HEX_8; + case 2 : return serendip ? MSH_HEX_20 : MSH_HEX_27; + case 3 : return serendip ? MSH_HEX_56 : MSH_HEX_64; + case 4 : return serendip ? MSH_HEX_98 : MSH_HEX_125; + case 5 : return serendip ? MSH_HEX_152: MSH_HEX_216; + case 6 : return serendip ? MSH_HEX_222: MSH_HEX_343; + case 7 : return serendip ? MSH_HEX_296: MSH_HEX_512; + case 8 : return serendip ? MSH_HEX_386: MSH_HEX_729; + case 9 : return serendip ? MSH_HEX_488: MSH_HEX_1000; + default : Msg::Error("hexahedron order %i unknown", order); return 0; + } + break; + case TYPE_PRI : + switch(order) { + case 0 : return MSH_PRI_1; + case 1 : return MSH_PRI_6; + case 2 : return serendip ? MSH_PRI_15 : MSH_PRI_18; + case 3 : return serendip ? MSH_PRI_38 : MSH_PRI_40; + case 4 : return serendip ? MSH_PRI_66 : MSH_PRI_75; + case 5 : return serendip ? MSH_PRI_102 : MSH_PRI_126; + case 6 : return serendip ? MSH_PRI_146 : MSH_PRI_196; + case 7 : return serendip ? MSH_PRI_198 : MSH_PRI_288; + case 8 : return serendip ? MSH_PRI_258 : MSH_PRI_405; + case 9 : return serendip ? MSH_PRI_326 : MSH_PRI_550; + default : Msg::Error("prism order %i unknown", order); return 0; } + break; + case TYPE_PYR : + switch(order) { + case 0 : return MSH_PYR_1; + case 1 : return MSH_PYR_5; + case 2 : return serendip ? MSH_PYR_13 : MSH_PYR_14; + case 3: return serendip ? MSH_PYR_29 : MSH_PYR_30; + case 4: return serendip ? MSH_PYR_50 : MSH_PYR_55; + case 5: return serendip ? MSH_PYR_77 : MSH_PYR_91; + case 6: return serendip ? MSH_PYR_110 : MSH_PYR_140; + case 7: return serendip ? MSH_PYR_149 : MSH_PYR_204; + case 8: return serendip ? MSH_PYR_194 : MSH_PYR_285; + case 9: return serendip ? MSH_PYR_245 : MSH_PYR_385; + default : Msg::Error("pyramid order %i unknown", order); return 0; + } + break; + default : Msg::Error("unknown element type %i", parentTag); return 0; } - -}; +} + + + #endif diff --git a/Numeric/polynomialBasis.cpp b/Numeric/polynomialBasis.cpp index f7d53bb6923e803a5e8a8e034fd4050630c6a019..c32c1adec670c0079e87130ad0246f33b8eacf65 100644 --- a/Numeric/polynomialBasis.cpp +++ b/Numeric/polynomialBasis.cpp @@ -43,6 +43,7 @@ static void printClosure(polynomialBasis::clCont &fullClosure, */ + fullMatrix<double> generate1DMonomials(int order) { fullMatrix<double> monomials(order + 1, 1); @@ -50,18 +51,7 @@ fullMatrix<double> generate1DMonomials(int order) return monomials; } -static fullMatrix<double> generate1DPoints(int order) -{ - fullMatrix<double> line(order + 1, 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; -} + static fullMatrix<double> generatePascalTriangle(int order) { @@ -77,6 +67,8 @@ static fullMatrix<double> generatePascalTriangle(int order) return monomials; } + + // generate the exterior hull of the Pascal triangle for Serendipity element static fullMatrix<double> generatePascalSerendipityTriangle(int order) @@ -107,6 +99,8 @@ static fullMatrix<double> generatePascalSerendipityTriangle(int order) return monomials; } + + // generate all monomials xi^m * eta^n with n and m <= order static fullMatrix<double> generatePascalQuad(int order) @@ -136,6 +130,8 @@ static fullMatrix<double> generatePascalQuad(int order) â‹® â‹® */ + + // generate all monomials xi^m * eta^n with n and m <= order static fullMatrix<double> generatePascalHex(int order, bool serendip) @@ -159,6 +155,8 @@ static fullMatrix<double> generatePascalHex(int order, bool serendip) return monomials; } + + static fullMatrix<double> generatePascalQuadSerendip(int order) { fullMatrix<double> monomials( (order)*4, 2); @@ -188,6 +186,8 @@ static fullMatrix<double> generatePascalQuadSerendip(int order) return monomials; } + + // generate the monomials subspace of all monomials of order exactly == p static fullMatrix<double> generateMonomialSubspace(int dim, int p) @@ -222,6 +222,8 @@ static fullMatrix<double> generateMonomialSubspace(int dim, int p) return monomials; } + + // generate external hull of the Pascal tetrahedron static fullMatrix<double> generatePascalSerendipityTetrahedron(int order) @@ -250,6 +252,8 @@ static fullMatrix<double> generatePascalSerendipityTetrahedron(int order) return monomials; } + + // generate Pascal tetrahedron static fullMatrix<double> generatePascalTetrahedron(int order) @@ -269,6 +273,8 @@ static fullMatrix<double> generatePascalTetrahedron(int order) return monomials; } + + // generate Pascal prism static fullMatrix<double> generatePascalPrism(int order) @@ -307,570 +313,7 @@ static fullMatrix<double> generatePascalPrism(int order) return monomials; } -static int nbdoftriangle(int order) { return (order + 1) * (order + 2) / 2; } - -//KH : caveat : node coordinates are not yet coherent with node numbering associated -// to numbering of principal vertices of face !!!! - -// uv surface - orientation v0-v2-v1 -static void nodepositionface0(int order, double *u, double *v, double *w) -{ - int ndofT = nbdoftriangle(order); - if (order == 0) { u[0] = 0.; v[0] = 0.; w[0] = 0.; return; } - - u[0]= 0.; v[0]= 0.; w[0] = 0.; - u[1]= 0.; v[1]= order; w[1] = 0.; - u[2]= order; v[2]= 0.; w[2] = 0.; - - // edges - for (int k = 0; k < (order - 1); k++){ - u[3 + k] = 0.; - v[3 + k] = k + 1; - w[3 + k] = 0.; - - u[3 + order - 1 + k] = k + 1; - v[3 + order - 1 + k] = order - 1 - k ; - w[3 + order - 1 + k] = 0.; - - u[3 + 2 * (order - 1) + k] = order - 1 - k; - v[3 + 2 * (order - 1) + k] = 0.; - w[3 + 2 * (order - 1) + k] = 0.; - } - - if (order > 2){ - int nbdoftemp = nbdoftriangle(order - 3); - nodepositionface0(order - 3, &u[3 + 3 * (order - 1)], &v[3 + 3 * (order - 1)], - &w[3 + 3* (order - 1)]); - for (int k = 0; k < nbdoftemp; k++){ - u[3 + k + 3 * (order - 1)] = u[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - v[3 + k + 3 * (order - 1)] = v[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - w[3 + k + 3 * (order - 1)] = w[3 + k + 3 * (order - 1)] * (order - 3); - } - } - for (int k = 0; k < ndofT; k++){ - u[k] = u[k] / order; - v[k] = v[k] / order; - w[k] = w[k] / order; - } -} - -// uw surface - orientation v0-v1-v3 -static void nodepositionface1(int order, double *u, double *v, double *w) -{ - int ndofT = nbdoftriangle(order); - if (order == 0) { u[0] = 0.; v[0] = 0.; w[0] = 0.; return; } - - u[0] = 0.; v[0]= 0.; w[0] = 0.; - u[1] = order; v[1]= 0.; w[1] = 0.; - u[2] = 0.; v[2]= 0.; w[2] = order; - // edges - for (int k = 0; k < (order - 1); k++){ - u[3 + k] = k + 1; - v[3 + k] = 0.; - w[3 + k] = 0.; - - u[3 + order - 1 + k] = order - 1 - k; - v[3 + order - 1 + k] = 0.; - w[3 + order - 1+ k ] = k + 1; - - u[3 + 2 * (order - 1) + k] = 0. ; - v[3 + 2 * (order - 1) + k] = 0.; - w[3 + 2 * (order - 1) + k] = order - 1 - k; - } - if (order > 2){ - int nbdoftemp = nbdoftriangle(order - 3); - nodepositionface1(order - 3, &u[3 + 3 * (order - 1)], &v[3 + 3 * (order -1 )], - &w[3 + 3 * (order - 1)]); - for (int k = 0; k < nbdoftemp; k++){ - u[3 + k + 3 * (order - 1)] = u[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - v[3 + k + 3 * (order - 1)] = v[3 + k + 3 * (order - 1)] * (order - 3); - w[3 + k + 3 * (order - 1)] = w[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - } - } - for (int k = 0; k < ndofT; k++){ - u[k] = u[k] / order; - v[k] = v[k] / order; - w[k] = w[k] / order; - } -} - -// vw surface - orientation v0-v3-v2 -static void nodepositionface2(int order, double *u, double *v, double *w) -{ - int ndofT = nbdoftriangle(order); - if (order == 0) { u[0] = 0.; v[0] = 0.; return; } - - u[0]= 0.; v[0]= 0.; w[0] = 0.; - u[1]= 0.; v[1]= 0.; w[1] = order; - u[2]= 0.; v[2]= order; w[2] = 0.; - // edges - for (int k = 0; k < (order - 1); k++){ - - u[3 + k] = 0.; - v[3 + k] = 0.; - w[3 + k] = k + 1; - - u[3 + order - 1 + k] = 0.; - v[3 + order - 1 + k] = k + 1; - w[3 + order - 1 + k] = order - 1 - k; - - u[3 + 2 * (order - 1) + k] = 0.; - v[3 + 2 * (order - 1) + k] = order - 1 - k; - w[3 + 2 * (order - 1) + k] = 0.; - } - if (order > 2){ - int nbdoftemp = nbdoftriangle(order - 3); - nodepositionface2(order - 3, &u[3 + 3 * (order - 1)], &v[3 + 3 * (order - 1)], - &w[3 + 3 * (order - 1)]); - for (int k = 0; k < nbdoftemp; k++){ - u[3 + k + 3 * (order - 1)] = u[3 + k + 3 * (order - 1)] * (order - 3); - v[3 + k + 3 * (order - 1)] = v[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - w[3 + k + 3 * (order - 1)] = w[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - } - } - for (int k = 0; k < ndofT; k++){ - u[k] = u[k] / order; - v[k] = v[k] / order; - w[k] = w[k] / order; - } -} - -// uvw surface - orientation v3-v1-v2 -static void nodepositionface3(int order, double *u, double *v, double *w) -{ - int ndofT = nbdoftriangle(order); - if (order == 0) { u[0] = 0.; v[0] = 0.; w[0] = 0.; return; } - - u[0]= 0.; v[0]= 0.; w[0] = order; - u[1]= order; v[1]= 0.; w[1] = 0.; - u[2]= 0.; v[2]= order; w[2] = 0.; - // edges - for (int k = 0; k < (order - 1); k++){ - - u[3 + k] = k + 1; - v[3 + k] = 0.; - w[3 + k] = order - 1 - k; - - u[3 + order - 1 + k] = order - 1 - k; - v[3 + order - 1 + k] = k + 1; - w[3 + order - 1 + k] = 0.; - - u[3 + 2 * (order - 1) + k] = 0.; - v[3 + 2 * (order - 1) + k] = order - 1 - k; - w[3 + 2 * (order - 1) + k] = k + 1; - } - if (order > 2){ - int nbdoftemp = nbdoftriangle(order - 3); - nodepositionface3(order - 3, &u[3 + 3 * (order - 1)], &v[3 + 3 * (order - 1)], - &w[3 + 3 * (order - 1)]); - for (int k = 0; k < nbdoftemp; k++){ - u[3 + k + 3 * (order - 1)] = u[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - v[3 + k + 3 * (order - 1)] = v[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - w[3 + k + 3 * (order - 1)] = w[3 + k + 3 * (order - 1)] * (order - 3) + 1.; - } - } - for (int k = 0; k < ndofT; k++){ - u[k] = u[k] / order; - v[k] = v[k] / order; - w[k] = w[k] / order; - } -} - -static fullMatrix<double> gmshGeneratePointsTetrahedron(int order, bool serendip) -{ - int nbPoints = - (serendip ? - 4 + 6 * std::max(0, order - 1) + 4 * std::max(0, (order - 2) * (order - 1) / 2) : - (order + 1) * (order + 2) * (order + 3) / 6); - - fullMatrix<double> point(nbPoints, 3); - - double overOrder = (order == 0 ? 1. : 1. / order); - - point(0, 0) = 0.; - point(0, 1) = 0.; - point(0, 2) = 0.; - - if (order > 0) { - point(1, 0) = order; - point(1, 1) = 0; - point(1, 2) = 0; - - point(2, 0) = 0.; - point(2, 1) = order; - point(2, 2) = 0.; - - point(3, 0) = 0.; - point(3, 1) = 0.; - point(3, 2) = order; - - // edges e5 and e6 switched in original version, opposite direction - // the template has been defined in table edges_tetra and faces_tetra (MElement.h) - - if (order > 1) { - for (int k = 0; k < (order - 1); k++) { - point(4 + k, 0) = k + 1; - point(4 + order - 1 + k, 0) = order - 1 - k; - point(4 + 2 * (order - 1) + k, 0) = 0.; - point(4 + 3 * (order - 1) + k, 0) = 0.; - // point(4 + 4 * (order - 1) + k, 0) = order - 1 - k; - // point(4 + 5 * (order - 1) + k, 0) = 0.; - point(4 + 4 * (order - 1) + k, 0) = 0.; - point(4 + 5 * (order - 1) + k, 0) = k+1; - - point(4 + k, 1) = 0.; - point(4 + order - 1 + k, 1) = k + 1; - point(4 + 2 * (order - 1) + k, 1) = order - 1 - k; - point(4 + 3 * (order - 1) + k, 1) = 0.; - // point(4 + 4 * (order - 1) + k, 1) = 0.; - // point(4 + 5 * (order - 1) + k, 1) = order - 1 - k; - point(4 + 4 * (order - 1) + k, 1) = k+1; - point(4 + 5 * (order - 1) + k, 1) = 0.; - - point(4 + k, 2) = 0.; - point(4 + order - 1 + k, 2) = 0.; - point(4 + 2 * (order - 1) + k, 2) = 0.; - point(4 + 3 * (order - 1) + k, 2) = order - 1 - k; - point(4 + 4 * (order - 1) + k, 2) = order - 1 - k; - point(4 + 5 * (order - 1) + k, 2) = order - 1 - k; - } - - if (order > 2) { - int ns = 4 + 6 * (order - 1); - int nbdofface = nbdoftriangle(order - 3); - - double *u = new double[nbdofface]; - double *v = new double[nbdofface]; - double *w = new double[nbdofface]; - - nodepositionface0(order - 3, u, v, w); - - // u-v plane - - for (int i = 0; i < nbdofface; i++){ - point(ns + i, 0) = u[i] * (order - 3) + 1.; - point(ns + i, 1) = v[i] * (order - 3) + 1.; - point(ns + i, 2) = w[i] * (order - 3); - } - - ns = ns + nbdofface; - - // u-w plane - - nodepositionface1(order - 3, u, v, w); - - for (int i=0; i < nbdofface; i++){ - point(ns + i, 0) = u[i] * (order - 3) + 1.; - point(ns + i, 1) = v[i] * (order - 3) ; - point(ns + i, 2) = w[i] * (order - 3) + 1.; - } - - // v-w plane - - ns = ns + nbdofface; - - nodepositionface2(order - 3, u, v, w); - - for (int i = 0; i < nbdofface; i++){ - point(ns + i, 0) = u[i] * (order - 3); - point(ns + i, 1) = v[i] * (order - 3) + 1.; - point(ns + i, 2) = w[i] * (order - 3) + 1.; - } - - // u-v-w plane - - ns = ns + nbdofface; - - nodepositionface3(order - 3, u, v, w); - - for (int i = 0; i < nbdofface; i++){ - point(ns + i, 0) = u[i] * (order - 3) + 1.; - point(ns + i, 1) = v[i] * (order - 3) + 1.; - point(ns + i, 2) = w[i] * (order - 3) + 1.; - } - - ns = ns + nbdofface; - - delete [] u; - delete [] v; - delete [] w; - - if (!serendip && order > 3) { - - fullMatrix<double> interior = gmshGeneratePointsTetrahedron(order - 4, false); - for (int k = 0; k < interior.size1(); k++) { - point(ns + k, 0) = 1. + interior(k, 0) * (order - 4); - point(ns + k, 1) = 1. + interior(k, 1) * (order - 4); - point(ns + k, 2) = 1. + interior(k, 2) * (order - 4); - } - } - } - } - } - - point.scale(overOrder); - return point; -} - -static fullMatrix<double> gmshGeneratePointsTriangle(int order, bool serendip) -{ - int nbPoints = serendip ? 3 * order : (order + 1) * (order + 2) / 2; - fullMatrix<double> point(nbPoints, 2); - - point(0, 0) = 0; - point(0, 1) = 0; - - if (order > 0) { - double dd = 1. / order; - - point(1, 0) = 1; - point(1, 1) = 0; - point(2, 0) = 0; - point(2, 1) = 1; - - int index = 3; - - if (order > 1) { - - double ksi = 0; - double eta = 0; - - for (int i = 0; i < order - 1; i++, index++) { - ksi += dd; - point(index, 0) = ksi; - point(index, 1) = eta; - } - - ksi = 1.; - - for (int i = 0; i < order - 1; i++, index++) { - ksi -= dd; - eta += dd; - point(index, 0) = ksi; - point(index, 1) = eta; - } - - eta = 1.; - ksi = 0.; - - for (int i = 0; i < order - 1; i++, index++) { - eta -= dd; - point(index, 0) = ksi; - point(index, 1) = eta; - } - - if (order > 2 && !serendip) { - fullMatrix<double> inner = gmshGeneratePointsTriangle(order - 3, serendip); - inner.scale(1. - 3. * dd); - inner.add(dd); - point.copy(inner, 0, nbPoints - index, 0, 2, index, 0); - } - } - } - return point; -} - -static fullMatrix<double> gmshGeneratePointsPrism(int order, bool serendip) -{ - const double prism18Pts[18][3] = { - {0, 0, -1}, // 0 - {1, 0, -1}, // 1 - {0, 1, -1}, // 2 - {0, 0, 1}, // 3 - {1, 0, 1}, // 4 - {0, 1, 1}, // 5 - {0.5, 0, -1}, // 6 - {0, 0.5, -1}, // 7 - {0, 0, 0}, // 8 - {0.5, 0.5, -1}, // 9 - {1, 0, 0}, // 10 - {0, 1, 0}, // 11 - {0.5, 0, 1}, // 12 - {0, 0.5, 1}, // 13 - {0.5, 0.5, 1}, // 14 - {0.5, 0, 0}, // 15 - {0, 0.5, 0}, // 16 - {0.5, 0.5, 0}, // 17 - }; - - int nbPoints = (order + 1)*(order + 1)*(order + 2)/2; - fullMatrix<double> point(nbPoints, 3); - - int index = 0; - fullMatrix<double> triPoints = gmshGeneratePointsTriangle(order,false); - fullMatrix<double> linePoints = generate1DPoints(order); - - if (order == 2) - for (int i =0; i<18; i++) - for (int j=0; j<3;j++) - point(i,j) = prism18Pts[i][j]; - else - for (int j = 0; j <linePoints.size1() ; j++) { - for (int i = 0; i < triPoints.size1(); i++) { - point(index,0) = triPoints(i,0); - point(index,1) = triPoints(i,1); - point(index,2) = linePoints(j,0); - index ++; - } - } - - return point; -} - -static fullMatrix<double> gmshGeneratePointsQuad(int order, bool serendip) -{ - int nbPoints = serendip ? order*4 : (order+1)*(order+1); - fullMatrix<double> point(nbPoints, 2); - - if (order > 0) { - point(0, 0) = -1; - point(0, 1) = -1; - point(1, 0) = 1; - point(1, 1) = -1; - point(2, 0) = 1; - point(2, 1) = 1; - point(3, 0) = -1; - point(3, 1) = 1; - - if (order > 1) { - int index = 4; - const static int edges[4][2]={{0,1},{1,2},{2,3},{3,0}}; - for (int iedge=0; iedge<4; iedge++) { - int p0 = edges[iedge][0]; - int p1 = edges[iedge][1]; - for (int i = 1; i < order; i++, index++) { - point(index, 0) = point(p0, 0) + i*(point(p1,0)-point(p0,0))/order; - point(index, 1) = point(p0, 1) + i*(point(p1,1)-point(p0,1))/order; - } - } - // FIXIT it was > 2 and I beleive it is >= 2 !! - if (order >= 2 && !serendip) { - fullMatrix<double> inner = gmshGeneratePointsQuad(order - 2, false); - inner.scale(1. - 2./order); - point.copy(inner, 0, nbPoints - index, 0, 2, index, 0); - } - } - } - else { - point(0, 0) = 0; - point(0, 1) = 0; - } - return point; -} - -static fullMatrix<double> gmshGeneratePointsHex(int order, bool serendip) -{ - int nbPoints = (order+1)*(order+1)*(order+1); - if (serendip) nbPoints -= (order-1)*(order-1)*(order-1); - fullMatrix<double> point(nbPoints, 3); - - // should be a public member of MHexahedron, just copied - static const int edges[12][2] = { - {0, 1}, - {0, 3}, - {0, 4}, - {1, 2}, - {1, 5}, - {2, 3}, - {2, 6}, - {3, 7}, - {4, 5}, - {4, 7}, - {5, 6}, - {6, 7} - }; - static const int faces[6][4] = { - {0, 3, 2, 1}, - {0, 1, 5, 4}, - {0, 4, 7, 3}, - {1, 2, 6, 5}, - {2, 3, 7, 6}, - {4, 5, 6, 7} - }; - - if (order > 0) { - point(0, 0) = -1; - point(0, 1) = -1; - point(0, 2) = -1; - point(1, 0) = 1; - point(1, 1) = -1; - point(1, 2) = -1; - point(2, 0) = 1; - point(2, 1) = 1; - point(2, 2) = -1; - point(3, 0) = -1; - point(3, 1) = 1; - point(3, 2) = -1; - - point(4, 0) = -1; - point(4, 1) = -1; - point(4, 2) = 1; - point(5, 0) = 1; - point(5, 1) = -1; - point(5, 2) = 1; - point(6, 0) = 1; - point(6, 1) = 1; - point(6, 2) = 1; - point(7, 0) = -1; - point(7, 1) = 1; - point(7, 2) = 1; - - if (order > 1) { - int index = 8; - for (int iedge=0; iedge<12; iedge++) { - int p0 = edges[iedge][0]; - int p1 = edges[iedge][1]; - for (int i = 1; i < order; i++, index++) { - point(index, 0) = point(p0, 0) + i*(point(p1,0)-point(p0,0))/order; - point(index, 1) = point(p0, 1) + i*(point(p1,1)-point(p0,1))/order; - point(index, 2) = point(p0, 2) + i*(point(p1,2)-point(p0,2))/order; - } - } - fullMatrix<double> fp = gmshGeneratePointsQuad(order - 2, false); - fp.scale(1. - 2./order); - for (int iface=0; iface<6; iface++) { - int p0 = faces[iface][0]; - int p1 = faces[iface][1]; - int p2 = faces[iface][2]; - int p3 = faces[iface][3]; - for (int i=0;i<fp.size1();i++, index++){ - const double u = fp(i,0); - const double v = fp(i,1); - const double newU = - 0.25*(1.-u)*(1.-v)*point(p0,0) + - 0.25*(1.+u)*(1.-v)*point(p1,0) + - 0.25*(1.+u)*(1.+v)*point(p2,0) + - 0.25*(1.-u)*(1.+v)*point(p3,0) ; - const double newV = - 0.25*(1.-u)*(1.-v)*point(p0,1) + - 0.25*(1.+u)*(1.-v)*point(p1,1) + - 0.25*(1.+u)*(1.+v)*point(p2,1) + - 0.25*(1.-u)*(1.+v)*point(p3,1) ; - const double newW = - 0.25*(1.-u)*(1.-v)*point(p0,2) + - 0.25*(1.+u)*(1.-v)*point(p1,2) + - 0.25*(1.+u)*(1.+v)*point(p2,2) + - 0.25*(1.-u)*(1.+v)*point(p3,2) ; - point(index, 0) = newU; - point(index, 1) = newV; - point(index, 2) = newW; - } - } - if (!serendip) { - fullMatrix<double> inner = gmshGeneratePointsHex(order - 2, false); - inner.scale(1. - 2./order); - point.copy(inner, 0, nbPoints - index, 0, 3, index, 0); - } - } - } - else if (order == 0){ - point(0, 0) = 0; - point(0, 1) = 0; - point(0, 2) = 0; - } - return point; -} static fullMatrix<double> generateLagrangeMonomialCoefficients (const fullMatrix<double>& monomial, const fullMatrix<double>& point) @@ -899,845 +342,386 @@ static fullMatrix<double> generateLagrangeMonomialCoefficients return coefficient; } -static void generate1dVertexClosure(polynomialBasis::clCont &closure, int order) -{ - closure.clear(); - closure.resize(2); - closure[0].push_back(0); - closure[1].push_back(order == 0 ? 0 : 1); - closure[0].type = MSH_PNT; - closure[1].type = MSH_PNT; -} -static void generate1dVertexClosureFull(polynomialBasis::clCont &closure, - std::vector<int> &closureRef, int order) -{ - closure.clear(); - closure.resize(2); - closure[0].push_back(0); - if (order != 0) { - closure[0].push_back(1); - closure[1].push_back(1); - } - closure[1].push_back(0); - for (int i = 0; i < order - 1; i++) { - closure[0].push_back(2 + i); - closure[1].push_back(2 + order - 2 - i); - } - closureRef.resize(2); - closureRef[0] = 0; - closureRef[1] = 0; -} -static void getFaceClosureTet(int iFace, int iSign, int iRotate, - polynomialBasis::closure &closure, int order) +polynomialBasis::polynomialBasis(int tag) : nodalBasis(tag) { - closure.clear(); - closure.resize((order + 1) * (order + 2) / 2); - closure.type = nodalBasis::getTag(TYPE_TRI, order, false); - switch (order){ - case 0: - closure[0] = 0; + switch (parentType) { + case TYPE_PNT : + monomials = generate1DMonomials(0); break; - default: - int face[4][3] = {{-3, -2, -1}, {1, -6, 4}, {-4, 5, 3}, {6, 2, -5}}; - int order1node[4][3] = {{0, 2, 1}, {0, 1, 3}, {0, 3, 2}, {3, 1, 2}}; - for (int i = 0; i < 3; ++i){ - int k = (3 + (iSign * i) + iRotate) % 3; //- iSign * iRotate - closure[i] = order1node[iFace][k]; - } - for (int i = 0;i < 3; ++i){ - int edgenumber = iSign * - face[iFace][(6 + i * iSign + (-1 + iSign) / 2 + iRotate) % 3]; //- iSign * iRotate - for (int k = 0; k < (order - 1); k++){ - if (edgenumber > 0) - closure[3 + i * (order - 1) + k] = - 4 + (edgenumber - 1) * (order - 1) + k; - else - closure[3 + i * (order - 1) + k] = - 4 + (-edgenumber) * (order - 1) - 1 - k; - } - } - int fi = 3 + 3 * (order - 1); - int ti = 4 + 6 * (order - 1); - int ndofff = (order - 3 + 2) * (order - 3 + 1) / 2; - ti = ti + iFace * ndofff; - for (int k = 0; k < order / 3; k++){ - int orderint = order - 3 - k * 3; - if (orderint > 0){ - for (int ci = 0; ci < 3 ; ci++){ - int shift = (3 + iSign * ci + iRotate) % 3; //- iSign * iRotate - closure[fi + ci] = ti + shift; - } - fi = fi + 3; ti = ti + 3; - for (int l = 0; l < orderint - 1; l++){ - for (int ei = 0; ei < 3; ei++){ - int edgenumber = (6 + ei * iSign + (-1 + iSign) / 2 + iRotate) % 3; - //- iSign * iRotate - if (iSign > 0) - closure[fi + ei * (orderint - 1) + l] = - ti + edgenumber * (orderint - 1) + l; - else - closure[fi + ei * (orderint - 1) + l] = - ti + (1 + edgenumber) * (orderint - 1) - 1 - l; - } - } - fi = fi + 3 * (orderint - 1); ti = ti + 3 * (orderint - 1); - } - else { - closure[fi] = ti; - ti++; - fi++; - } - } + case TYPE_LIN : + monomials = generate1DMonomials(order); + break; + case TYPE_TRI : + monomials = serendip ? generatePascalSerendipityTriangle(order) : + generatePascalTriangle(order); + break; + case TYPE_QUA : + monomials = serendip ? generatePascalQuadSerendip(order) : + generatePascalQuad(order); + break; + case TYPE_TET : + monomials = serendip ? generatePascalSerendipityTetrahedron(order) : + generatePascalTetrahedron(order); + break; + case TYPE_PRI : + monomials = generatePascalPrism(order); + break; + case TYPE_HEX : + monomials = generatePascalHex(order, serendip); break; } -} -static void generate2dEdgeClosureFull(polynomialBasis::clCont &closure, - std::vector<int> &closureRef, - int order, int nNod, bool serendip) -{ - closure.clear(); - closure.resize(2*nNod); - closureRef.resize(2*nNod); - int shift = 0; - for (int corder = order; corder>=0; corder -= (nNod == 3 ? 3 : 2)) { - if (corder == 0) { - for (int r = 0; r < nNod ; r++){ - closure[r].push_back(shift); - closure[r+nNod].push_back(shift); - } - break; - } - for (int r = 0; r < nNod ; r++){ - for (int j = 0; j < nNod; j++) { - closure[r].push_back(shift + (r + j) % nNod); - closure[r + nNod].push_back(shift + (r - j + 1 + nNod) % nNod); - } - } - shift += nNod; - int n = nNod*(corder-1); - for (int r = 0; r < nNod ; r++){ - for (int j = 0; j < n; j++){ - closure[r].push_back(shift + (j + (corder - 1) * r) % n); - closure[r + nNod].push_back(shift + (n - j - 1 + (corder - 1) * (r + 1)) % n); - } - } - shift += n; - if (serendip) break; - } - for (int r = 0; r < nNod*2 ; r++) { - closure[r].type = nodalBasis::getTag(TYPE_LIN, order); - closureRef[r] = 0; - } -} + coefficients = generateLagrangeMonomialCoefficients(monomials, points); -static void addEdgeNodes(polynomialBasis::clCont &closureFull, const int *edges, int order) -{ - if (order < 2) - return; - int numNodes = 0; - for (int i = 0; edges[i] >= 0; ++i) { - numNodes = std::max(numNodes, edges[i] + 1); - } - std::vector<std::vector<int> > nodes2edges(numNodes, std::vector<int>(numNodes, -1)); - for (int i = 0; edges[i] >= 0; i += 2) { - nodes2edges[edges[i]][edges[i + 1]] = i; - nodes2edges[edges[i + 1]][edges[i]] = i + 1; - } - for (unsigned int iClosure = 0; iClosure < closureFull.size(); iClosure++) { - std::vector<int> &cl = closureFull[iClosure]; - for (int iEdge = 0; edges[iEdge] >= 0; iEdge += 2) { - if (cl.empty()) - continue; - int n0 = cl[edges[iEdge]]; - int n1 = cl[edges[iEdge + 1]]; - int oEdge = nodes2edges[n0][n1]; - if (oEdge == -1) - Msg::Error("invalid p1 closure or invalid edges list"); - for (int i = 0 ; i < order - 1; i++) - cl.push_back(numNodes + oEdge/2 * (order - 1) + ((oEdge % 2) ? order - 2 - i : i)); - } - } } -static void generateFaceClosureTet(polynomialBasis::clCont &closure, int order) -{ - closure.clear(); - for (int iRotate = 0; iRotate < 3; iRotate++){ - for (int iSign = 1; iSign >= -1; iSign -= 2){ - for (int iFace = 0; iFace < 4; iFace++){ - polynomialBasis::closure closure_face; - getFaceClosureTet(iFace, iSign, iRotate, closure_face, order); - closure.push_back(closure_face); - } - } - } -} -static void generateFaceClosureTetFull(polynomialBasis::clCont &closureFull, - std::vector<int> &closureRef, - int order, bool serendip) -{ - closureFull.clear(); - //input : - static const short int faces[4][3] = {{0,1,2}, {0,3,1}, {0,2,3}, {3,2,1}}; - static const int edges[] = {0, 1, 1, 2, 2, 0, 3, 0, 3, 2, 3, 1, -1}; - static const int faceOrientation[6] = {0,1,2,5,3,4}; - closureFull.resize(24); - closureRef.resize(24); - for (int i = 0; i < 24; i ++) - closureRef[i] = 0; - if (order == 0) { - for (int i = 0; i < 24; i ++) { - closureFull[i].push_back(0); - } - return; - } - //Mapping for the p1 nodes - polynomialBasis::clCont closure; - generateFaceClosureTet(closure, 1); - for (unsigned int i = 0; i < closureFull.size(); i++) { - std::vector<int> &clFull = closureFull[i]; - std::vector<int> &cl = closure[i]; - clFull.resize(4, -1); - closureRef[i] = 0; - for (unsigned int j = 0; j < cl.size(); j ++) - clFull[closure[0][j]] = cl[j]; - for (int j = 0; j < 4; j ++) - if (clFull[j] == -1) - clFull[j] = (6 - clFull[(j + 1) % 4] - clFull[(j + 2) % 4] - clFull[(j + 3) % 4]); - } - int nodes2Faces[4][4][4]; - for (int i = 0; i < 4; i++) { - for (int iRotate = 0; iRotate < 3; iRotate ++) { - short int n0 = faces[i][(3 - iRotate) % 3]; - short int n1 = faces[i][(4 - iRotate) % 3]; - short int n2 = faces[i][(5 - iRotate) % 3]; - nodes2Faces[n0][n1][n2] = i * 6 + iRotate; - nodes2Faces[n0][n2][n1] = i * 6 + iRotate + 3; - } - } - polynomialBasis::clCont closureTriangles; - std::vector<int> closureTrianglesRef; - if (order >= 3) - generate2dEdgeClosureFull(closureTriangles, closureTrianglesRef, order - 3, 3, false); - addEdgeNodes(closureFull, edges, order); - for (unsigned int iClosure = 0; iClosure < closureFull.size(); iClosure++) { - //faces - std::vector<int> &cl = closureFull[iClosure]; - if (order >= 3) { - for (int iFace = 0; iFace < 4; iFace ++) { - int n0 = cl[faces[iFace][0]]; - int n1 = cl[faces[iFace][1]]; - int n2 = cl[faces[iFace][2]]; - short int id = nodes2Faces[n0][n1][n2]; - short int iTriClosure = faceOrientation [id % 6]; - short int idFace = id/6; - int nOnFace = closureTriangles[iTriClosure].size(); - for (int i = 0; i < nOnFace; i++) { - cl.push_back(4 + 6 * (order - 1) + idFace * nOnFace + - closureTriangles[iTriClosure][i]); - } - } - } - } - if (order >= 4 && !serendip) { - polynomialBasis::clCont insideClosure; - std::vector<int> fakeClosureRef; - generateFaceClosureTetFull(insideClosure, fakeClosureRef, order - 4, false); - for (unsigned int i = 0; i < closureFull.size(); i ++) { - unsigned int shift = closureFull[i].size(); - for (unsigned int j = 0; j < insideClosure[i].size(); j++) - closureFull[i].push_back(insideClosure[i][j] + shift); - } - } -} -void rotateHex(int iFace, int iRot, int iSign, double uI, double vI, - double &uO, double &vO, double &wO) +polynomialBasis::~polynomialBasis() { - if (iSign<0){ - double tmp=uI; - uI=vI; - vI=tmp; - } - for (int i=0; i < iRot; i++){ - double tmp=uI; - uI=-vI; - vI=tmp; - } - switch (iFace) { - case 0: uO = vI; vO = uI; wO=-1; break; - case 1: uO = uI; vO = -1; wO=vI; break; - case 2: uO =-1; vO = vI; wO=uI; break; - case 3: uO = 1; vO = uI; wO=vI; break; - case 4: uO =-uI; vO = 1; wO=vI; break; - case 5: uO =uI; vO = vI; wO=1; break; - } } -void rotateHexFull(int iFace, int iRot, int iSign, double uI, double vI, double wI, double &uO, double &vO, double &wO) -{ - switch (iFace) { - case 0: uO = uI; vO = vI; wO = wI; break; - case 1: uO = wI; vO = uI; wO = vI; break; - case 2: uO = vI; vO = wI; wO = uI; break; - case 3: uO = wI; vO = vI; wO =-uI; break; - case 4: uO = wI; vO =-uI; wO =-vI; break; - case 5: uO = vI; vO = uI; wO =-wI; break; - } - for (int i = 0; i < iRot; i++){ - double tmp = uO; - uO = -vO; - vO = tmp; - } - if (iSign<0){ - double tmp = uO; - uO = vO; - vO = tmp; - } -} -inline static double pow2(double x) -{ - return x * x; -} -/* -static void checkClosure(int tag) { - printf("TYPE = %i\n", tag); - const polynomialBasis &fs = *polynomialBases::find(tag); - for (int i = 0; i < fs.closures.size(); ++i) { - const std::vector<int> &clRef = fs.closures[fs.closureRef[i]]; - const std::vector<int> &cl = fs.closures[i]; - const std::vector<int> &clFull = fs.fullClosures[i]; - printf("i = %i\n", i); - for (int j = 0; j < cl.size(); ++j) { - printf("%3i ", clFull[clRef[j]]); - } - printf("\n"); - for (int j = 0; j < cl.size(); ++j) { - printf("%3i ", cl[j]); - } - printf("\n"); - } -} -*/ +int polynomialBasis::getNumShapeFunctions() const { return coefficients.size1(); } -static void generateFaceClosureHex(polynomialBasis::clCont &closure, int order, - bool serendip, const fullMatrix<double> &points) -{ - closure.clear(); - const polynomialBasis &fsFace = *polynomialBases::find - (nodalBasis::getTag(TYPE_QUA, order, serendip)); - for (int iRotate = 0; iRotate < 4; iRotate++){ - for (int iSign = 1; iSign >= -1; iSign -= 2){ - for (int iFace = 0; iFace < 6; iFace++) { - polynomialBasis::closure cl; - cl.type = fsFace.type; - cl.resize(fsFace.points.size1()); - for (unsigned int iNode = 0; iNode < cl.size(); ++iNode) { - double u,v,w; - rotateHex(iFace, iRotate, iSign, fsFace.points(iNode, 0), - fsFace.points(iNode, 1), u, v, w); - cl[iNode] = 0; - double D = std::numeric_limits<double>::max(); - for (int jNode = 0; jNode < points.size1(); ++jNode) { - double d = pow2(points(jNode, 0) - u) + pow2(points(jNode, 1) - v) + - pow2(points(jNode, 2) - w); - if (d < D) { - cl[iNode] = jNode; - D = d; - } - } - } - closure.push_back(cl); - } - } - } -} -static void generateFaceClosureHexFull(polynomialBasis::clCont &closure, - std::vector<int> &closureRef, - int order, bool serendip, - const fullMatrix<double> &points) -{ - closure.clear(); - int clId = 0; - for (int iRotate = 0; iRotate < 4; iRotate++){ - for (int iSign = 1; iSign >= -1; iSign -= 2){ - for (int iFace = 0; iFace < 6; iFace++) { - polynomialBasis::closure cl; - cl.resize(points.size1()); - for (int iNode = 0; iNode < points.size1(); ++iNode) { - double u,v,w; - rotateHexFull(iFace, iRotate, iSign, points(iNode, 0), points(iNode, 1), - points(iNode, 2), u, v, w); - int J = 0; - double D = std::numeric_limits<double>::max(); - for (int jNode = 0; jNode < points.size1(); ++jNode) { - double d = pow2(points(jNode, 0) - u) + pow2(points(jNode, 1) - v) + - pow2(points(jNode, 2) - w); - if (d < D) { - J = jNode; - D = d; - } - } - cl[J] = iNode; - } - closure.push_back(cl); - closureRef.push_back(0); - clId ++; - } - } - } -} -static void getFaceClosurePrism(int iFace, int iSign, int iRotate, - polynomialBasis::closure &closure, int order) +void polynomialBasis::f(double u, double v, double w, double *sf) const { - if (order > 2) - Msg::Error("FaceClosure not implemented for prisms of order %d",order); - bool isTriangle = iFace<2; - int nNodes = isTriangle ? (order+1)*(order+2)/2 : (order+1)*(order+1); - closure.clear(); - if (isTriangle && iRotate > 2) return; - closure.resize(nNodes); - if (order==0) { - closure[0] = 0; - return; - } - int order1node[5][4] = {{0, 2, 1, -1}, {3, 4, 5, -1}, {0, 1, 4, 3}, {0, 3, 5, 2}, - {1, 2, 5, 4}}; - int order2node[5][5] = {{7, 9, 6, -1, -1}, {12, 14, 13, -1, -1}, {6, 10, 12, 8, 15}, - {8, 13, 11, 7, 16}, {9, 11, 14, 10, 17}}; - // int order2node[5][4] = {{7, 9, 6, -1}, {12, 14, 13, -1}, {6, 10, 12, 8}, - // {8, 13, 11, 7}, {9, 11, 14, 10}}; - int nVertex = isTriangle ? 3 : 4; - closure.type = nodalBasis::getTag(isTriangle ? TYPE_TRI : TYPE_QUA, order); - for (int i = 0; i < nVertex; ++i){ - int k = (nVertex + (iSign * i) + iRotate) % nVertex; //- iSign * iRotate - closure[i] = order1node[iFace][k]; - } - if (order==2) { - for (int i = 0; i < nVertex; ++i){ - int k = (nVertex + (iSign==-1?-1:0) + (iSign * i) + iRotate) % nVertex; - //- iSign * iRotate - closure[nVertex+i] = order2node[iFace][k]; + double p[1256]; + evaluateMonomials(u, v, w, p); + for (int i = 0; i < coefficients.size1(); i++) { + sf[i] = 0.0; + for (int j = 0; j < coefficients.size2(); j++) { + sf[i] += coefficients(i, j) * p[j]; } - if (!isTriangle) - closure[nNodes-1] = order2node[iFace][4]; // center } } -static void generateFaceClosurePrism(polynomialBasis::clCont &closure, int order) + + +void polynomialBasis::f(fullMatrix<double> &coord, fullMatrix<double> &sf) const { - closure.clear(); - for (int iRotate = 0; iRotate < 4; iRotate++){ - for (int iSign = 1; iSign >= -1; iSign -= 2){ - for (int iFace = 0; iFace < 5; iFace++){ - polynomialBasis::closure closure_face; - getFaceClosurePrism(iFace, iSign, iRotate, closure_face, order); - closure.push_back(closure_face); - } - } + double p[1256]; + sf.resize (coord.size1(), coefficients.size1()); + for (int iPoint=0; iPoint< coord.size1(); iPoint++) { + evaluateMonomials(coord(iPoint,0), coord(iPoint,1), coord(iPoint,2), p); + for (int i = 0; i < coefficients.size1(); i++) + for (int j = 0; j < coefficients.size2(); j++) + sf(iPoint,i) += coefficients(i, j) * p[j]; } } -static void generateFaceClosurePrismFull(polynomialBasis::clCont &closureFull, - std::vector<int> &closureRef, int order) -{ - polynomialBasis::clCont closure; - closureFull.clear(); - closureFull.resize(40); - closureRef.resize(40); - generateFaceClosurePrism(closure, 1); - int ref3 = -1, ref4a = -1, ref4b = -1; - for (unsigned int i = 0; i < closure.size(); i++) { - std::vector<int> &clFull = closureFull[i]; - std::vector<int> &cl = closure[i]; - if (cl.size() == 0) - continue; - clFull.resize(6, -1); - int &ref = cl.size() == 3 ? ref3 : (cl[0] / 3 + cl[1] / 3) % 2 ? ref4b : ref4a; - if (ref == -1) - ref = i; - closureRef[i] = ref; - for (unsigned int j = 0; j < cl.size(); j ++) - clFull[closure[ref][j]] = cl[j]; - for (int j = 0; j < 6; j ++) { - if (clFull[j] == -1) { - int k = ((j / 3) + 1) % 2 * 3; - int sum = (clFull[k + (j + 1) % 3] + clFull[k + (j + 2) % 3]); - clFull[j] = ((sum / 6 + 1) % 2) * 3 + (12 - sum) % 3; - } - } - } - static const int edges[] = {0, 1, 0, 2, 0, 3, 1, 2, 1, 4, 2, 5, - 3, 4, 3, 5, 4, 5, -1}; - addEdgeNodes(closureFull, edges, order); - if ( order < 2 ) - return; - // face center nodes for p2 prism - static const int faces[5][4] = {{0, 2, 1, -1}, {3, 4, 5, -1}, {0, 1, 4, 3}, - {0, 3, 5, 2}, {1, 2, 5, 4}}; - - if ( order == 2 ) { - int nextFaceNode = 15; - int numFaces = 5; - int numFaceNodes = 4; - std::map<int,int> nodeSum2Face; - for (int iFace = 0; iFace < numFaces ; iFace ++) { - int nodeSum = 0; - for (int iNode = 0; iNode < numFaceNodes; iNode++ ) { - nodeSum += faces[iFace][iNode]; - } - nodeSum2Face[nodeSum] = iFace; - } - for (unsigned int i = 0; i < closureFull.size(); i++ ) { - if (closureFull[i].empty()) - continue; - for (int iFace = 0; iFace < numFaces; iFace++ ) { - int nodeSum = 0; - for (int iNode = 0; iNode < numFaceNodes; iNode++) - nodeSum += faces[iFace][iNode] < 0 ? faces[iFace][iNode] : - closureFull[i][ faces[iFace][iNode] ]; - std::map<int,int>::iterator it = nodeSum2Face.find(nodeSum); - if (it == nodeSum2Face.end() ) - Msg::Error("Prism face not found"); - int mappedFaceId = it->second; - if ( mappedFaceId > 1) { - closureFull[i].push_back(nextFaceNode + mappedFaceId - 2); - } - } - } - } else { - Msg::Error("Prisms of order %d not implemented",order); - } -} -static void generate2dEdgeClosure(polynomialBasis::clCont &closure, int order, int nNod = 3) +void polynomialBasis::df(fullMatrix<double> &coord, fullMatrix<double> &dfm) const { - closure.clear(); - closure.resize(2*nNod); - for (int j = 0; j < nNod ; j++){ - closure[j].push_back(j); - closure[j].push_back((j+1)%nNod); - closure[nNod+j].push_back((j+1)%nNod); - closure[nNod+j].push_back(j); - for (int i=0; i < order-1; i++){ - closure[j].push_back( nNod + (order-1)*j + i ); - closure[nNod+j].push_back(nNod + (order-1)*(j+1) -i -1); + double dfv[1256][3]; + dfm.resize (coefficients.size1(), coord.size1() * 3, false); + int ii = 0; + int dimCoord = coord.size2(); + for (int iPoint=0; iPoint< coord.size1(); iPoint++) { + df(coord(iPoint,0), dimCoord > 1 ? coord(iPoint, 1) : 0., dimCoord > 2 ? coord(iPoint, 2) : 0., dfv); + for (int i = 0; i < coefficients.size1(); i++) { + dfm(i, iPoint * 3 + 0) = dfv[i][0]; + dfm(i, iPoint * 3 + 1) = dfv[i][1]; + dfm(i, iPoint * 3 + 2) = dfv[i][2]; + ++ii; } - closure[j].type = closure[nNod+j].type = nodalBasis::getTag(TYPE_LIN, order); } } -static void generateClosureOrder0(polynomialBasis::clCont &closure, int nb) -{ - closure.clear(); - closure.resize(nb); - for (int i=0; i < nb; i++) { - closure[i].push_back(0); - closure[i].type = MSH_PNT; - } -} -std::map<int, polynomialBasis> polynomialBases::fs; - -void polynomialBasis::initialize() +void polynomialBasis::df(double u, double v, double w, double grads[][3]) const { - switch(parentType) { - case TYPE_PNT: - monomials = generate1DMonomials(0); - break; - case TYPE_LIN: - monomials = generate1DMonomials(order); - generate1dVertexClosure(closures, order); - generate1dVertexClosureFull(fullClosures, closureRef, order); - break; - case TYPE_TRI: - monomials = serendip ? generatePascalSerendipityTriangle(order) : - generatePascalTriangle(order); - if (order == 0) { - generateClosureOrder0(closures, 6); - generateClosureOrder0(fullClosures, 6); - closureRef.resize(6,0); - } - else { - generate2dEdgeClosure(closures, order); - generate2dEdgeClosureFull(fullClosures, closureRef, order, 3, serendip); - } - break; - case TYPE_QUA: - monomials = serendip ? generatePascalQuadSerendip(order) : - generatePascalQuad(order); - if (order == 0) { - generateClosureOrder0(closures, 8); - generateClosureOrder0(fullClosures, 8); - closureRef.resize(8, 0); - } - else { - generate2dEdgeClosure(closures, order, 4); - generate2dEdgeClosureFull(fullClosures, closureRef, order, 4, serendip); - } - break; - case TYPE_TET: - monomials = serendip ? generatePascalSerendipityTetrahedron(order) : - generatePascalTetrahedron(order); - if (order == 0) { - generateClosureOrder0(closures,24); - generateClosureOrder0(fullClosures, 24); - closureRef.resize(24, 0); - } - else { - generateFaceClosureTet(closures, order); - generateFaceClosureTetFull(fullClosures, closureRef, order, serendip); + switch (monomials.size2()) { + case 1: + for (int i = 0; i < coefficients.size1(); i++){ + grads[i][0] = 0; + grads[i][1] = 0; + grads[i][2] = 0; + for(int j = 0; j < coefficients.size2(); j++){ + if (monomials(j, 0) > 0) + grads[i][0] += coefficients(i, j) * + pow_int(u, (int)(monomials(j, 0) - 1)) * monomials(j, 0); } - break; - case TYPE_PRI: - monomials = generatePascalPrism(order); - if (order == 0) { - generateClosureOrder0(closures,48); - generateClosureOrder0(fullClosures,48); - closureRef.resize(48, 0); + } + break; + case 2: + for (int i = 0; i < coefficients.size1(); i++){ + grads[i][0] = 0; + grads[i][1] = 0; + grads[i][2] = 0; + for(int j = 0; j < coefficients.size2(); j++){ + if (monomials(j, 0) > 0) + grads[i][0] += coefficients(i, j) * + pow_int(u, (int)(monomials(j, 0) - 1)) * monomials(j, 0) * + pow_int(v, (int)monomials(j, 1)); + if (monomials(j, 1) > 0) + grads[i][1] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0)) * + pow_int(v, (int)(monomials(j, 1) - 1)) * monomials(j, 1); } - else { - generateFaceClosurePrism(closures, order); - generateFaceClosurePrismFull(fullClosures, closureRef, order); + } + break; + case 3: + for (int i = 0; i < coefficients.size1(); i++){ + grads[i][0] = 0; + grads[i][1] = 0; + grads[i][2] = 0; + for(int j = 0; j < coefficients.size2(); j++){ + if (monomials(j, 0) > 0) + grads[i][0] += coefficients(i, j) * + pow_int(u, (int)(monomials(j, 0) - 1)) * monomials(j, 0) * + pow_int(v, (int)monomials(j, 1)) * + pow_int(w, (int)monomials(j, 2)); + if (monomials(j, 1) > 0) + grads[i][1] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0)) * + pow_int(v, (int)(monomials(j, 1) - 1)) * monomials(j, 1) * + pow_int(w, (int)monomials(j, 2)); + if (monomials(j, 2) > 0) + grads[i][2] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0)) * + pow_int(v, (int)monomials(j, 1)) * + pow_int(w, (int)(monomials(j, 2) - 1)) * monomials(j, 2); } - break; - case TYPE_HEX: - monomials = generatePascalHex(order, serendip); - generateFaceClosureHex(closures, order, serendip, points); - generateFaceClosureHexFull(fullClosures, closureRef, order, serendip, points); - break; + } + break; } - - coefficients = generateLagrangeMonomialCoefficients(monomials, points); - } +} -const polynomialBasis *polynomialBases::find(int tag) + +void polynomialBasis::ddf(double u, double v, double w, double hess[][3][3]) const { - std::map<int, polynomialBasis>::const_iterator it = fs.find(tag); - if (it != fs.end()) return &it->second; - - polynomialBasis F; - F.type = tag; - switch (tag) { - case MSH_PNT : F.parentType = TYPE_PNT; F.order = 0; F.serendip = false; break; - case MSH_LIN_1 : F.parentType = TYPE_LIN; F.order = 0; F.serendip = false; break; - case MSH_LIN_2 : F.parentType = TYPE_LIN; F.order = 1; F.serendip = false; break; - case MSH_LIN_3 : F.parentType = TYPE_LIN; F.order = 2; F.serendip = false; break; - case MSH_LIN_4 : F.parentType = TYPE_LIN; F.order = 3; F.serendip = false; break; - case MSH_LIN_5 : F.parentType = TYPE_LIN; F.order = 4; F.serendip = false; break; - case MSH_LIN_6 : F.parentType = TYPE_LIN; F.order = 5; F.serendip = false; break; - case MSH_LIN_7 : F.parentType = TYPE_LIN; F.order = 6; F.serendip = false; break; - case MSH_LIN_8 : F.parentType = TYPE_LIN; F.order = 7; F.serendip = false; break; - case MSH_LIN_9 : F.parentType = TYPE_LIN; F.order = 8; F.serendip = false; break; - case MSH_LIN_10 : F.parentType = TYPE_LIN; F.order = 9; F.serendip = false; break; - case MSH_LIN_11 : F.parentType = TYPE_LIN; F.order = 10;F.serendip = false; break; - case MSH_TRI_1 : F.parentType = TYPE_TRI; F.order = 0; F.serendip = false; break; - case MSH_TRI_3 : F.parentType = TYPE_TRI; F.order = 1; F.serendip = false; break; - case MSH_TRI_6 : F.parentType = TYPE_TRI; F.order = 2; F.serendip = false; break; - case MSH_TRI_10 : F.parentType = TYPE_TRI; F.order = 3; F.serendip = false; break; - case MSH_TRI_15 : F.parentType = TYPE_TRI; F.order = 4; F.serendip = false; break; - case MSH_TRI_21 : F.parentType = TYPE_TRI; F.order = 5; F.serendip = false; break; - case MSH_TRI_28 : F.parentType = TYPE_TRI; F.order = 6; F.serendip = false; break; - case MSH_TRI_36 : F.parentType = TYPE_TRI; F.order = 7; F.serendip = false; break; - case MSH_TRI_45 : F.parentType = TYPE_TRI; F.order = 8; F.serendip = false; break; - case MSH_TRI_55 : F.parentType = TYPE_TRI; F.order = 9; F.serendip = false; break; - case MSH_TRI_66 : F.parentType = TYPE_TRI; F.order = 10;F.serendip = false; break; - case MSH_TRI_9 : F.parentType = TYPE_TRI; F.order = 3; F.serendip = true; break; - case MSH_TRI_12 : F.parentType = TYPE_TRI; F.order = 4; F.serendip = true; break; - case MSH_TRI_15I : F.parentType = TYPE_TRI; F.order = 5; F.serendip = true; break; - case MSH_TRI_18 : F.parentType = TYPE_TRI; F.order = 6; F.serendip = true; break; - case MSH_TRI_21I : F.parentType = TYPE_TRI; F.order = 7; F.serendip = true; break; - case MSH_TRI_24 : F.parentType = TYPE_TRI; F.order = 8; F.serendip = true; break; - case MSH_TRI_27 : F.parentType = TYPE_TRI; F.order = 9; F.serendip = true; break; - case MSH_TRI_30 : F.parentType = TYPE_TRI; F.order = 10;F.serendip = true; break; - case MSH_TET_1 : F.parentType = TYPE_TET; F.order = 0; F.serendip = false; break; - case MSH_TET_4 : F.parentType = TYPE_TET; F.order = 1; F.serendip = false; break; - case MSH_TET_10 : F.parentType = TYPE_TET; F.order = 2; F.serendip = false; break; - case MSH_TET_20 : F.parentType = TYPE_TET; F.order = 3; F.serendip = false; break; - case MSH_TET_35 : F.parentType = TYPE_TET; F.order = 4; F.serendip = false; break; - case MSH_TET_56 : F.parentType = TYPE_TET; F.order = 5; F.serendip = false; break; - case MSH_TET_84 : F.parentType = TYPE_TET; F.order = 6; F.serendip = false; break; - case MSH_TET_120 : F.parentType = TYPE_TET; F.order = 7; F.serendip = false; break; - case MSH_TET_165 : F.parentType = TYPE_TET; F.order = 8; F.serendip = false; break; - case MSH_TET_220 : F.parentType = TYPE_TET; F.order = 9; F.serendip = false; break; - case MSH_TET_286 : F.parentType = TYPE_TET; F.order = 10;F.serendip = false; break; - case MSH_TET_34 : F.parentType = TYPE_TET; F.order = 4; F.serendip = true; break; - case MSH_TET_52 : F.parentType = TYPE_TET; F.order = 5; F.serendip = true; break; - case MSH_TET_74 : F.parentType = TYPE_TET; F.order = 6; F.serendip = true; break; - case MSH_TET_100 : F.parentType = TYPE_TET; F.order = 7; F.serendip = true; break; - case MSH_TET_130 : F.parentType = TYPE_TET; F.order = 8; F.serendip = true; break; - case MSH_TET_164 : F.parentType = TYPE_TET; F.order = 9; F.serendip = true; break; - case MSH_TET_202 : F.parentType = TYPE_TET; F.order = 10;F.serendip = true; break; - case MSH_QUA_1 : F.parentType = TYPE_QUA; F.order = 0; F.serendip = false; break; - case MSH_QUA_4 : F.parentType = TYPE_QUA; F.order = 1; F.serendip = false; break; - case MSH_QUA_9 : F.parentType = TYPE_QUA; F.order = 2; F.serendip = false; break; - case MSH_QUA_16 : F.parentType = TYPE_QUA; F.order = 3; F.serendip = false; break; - case MSH_QUA_25 : F.parentType = TYPE_QUA; F.order = 4; F.serendip = false; break; - case MSH_QUA_36 : F.parentType = TYPE_QUA; F.order = 5; F.serendip = false; break; - case MSH_QUA_49 : F.parentType = TYPE_QUA; F.order = 6; F.serendip = false; break; - case MSH_QUA_64 : F.parentType = TYPE_QUA; F.order = 7; F.serendip = false; break; - case MSH_QUA_81 : F.parentType = TYPE_QUA; F.order = 8; F.serendip = false; break; - case MSH_QUA_100 : F.parentType = TYPE_QUA; F.order = 9; F.serendip = false; break; - case MSH_QUA_121 : F.parentType = TYPE_QUA; F.order = 10;F.serendip = false; break; - case MSH_QUA_8 : F.parentType = TYPE_QUA; F.order = 2; F.serendip = true; break; - case MSH_QUA_12 : F.parentType = TYPE_QUA; F.order = 3; F.serendip = true; break; - case MSH_QUA_16I : F.parentType = TYPE_QUA; F.order = 4; F.serendip = true; break; - case MSH_QUA_20 : F.parentType = TYPE_QUA; F.order = 5; F.serendip = true; break; - case MSH_QUA_24 : F.parentType = TYPE_QUA; F.order = 6; F.serendip = true; break; - case MSH_QUA_28 : F.parentType = TYPE_QUA; F.order = 7; F.serendip = true; break; - case MSH_QUA_32 : F.parentType = TYPE_QUA; F.order = 8; F.serendip = true; break; - case MSH_QUA_36I : F.parentType = TYPE_QUA; F.order = 9; F.serendip = true; break; - case MSH_QUA_40 : F.parentType = TYPE_QUA; F.order = 10;F.serendip = true; break; - case MSH_PRI_1 : F.parentType = TYPE_PRI; F.order = 0; F.serendip = false; break; - case MSH_PRI_6 : F.parentType = TYPE_PRI; F.order = 1; F.serendip = false; break; - case MSH_PRI_18 : F.parentType = TYPE_PRI; F.order = 2; F.serendip = false; break; - case MSH_HEX_8 : F.parentType = TYPE_HEX; F.order = 1; F.serendip = false; break; - case MSH_HEX_27 : F.parentType = TYPE_HEX; F.order = 2; F.serendip = false; break; - case MSH_HEX_64 : F.parentType = TYPE_HEX; F.order = 3; F.serendip = false; break; - case MSH_HEX_125 : F.parentType = TYPE_HEX; F.order = 4; F.serendip = false; break; - case MSH_HEX_216 : F.parentType = TYPE_HEX; F.order = 5; F.serendip = false; break; - case MSH_HEX_343 : F.parentType = TYPE_HEX; F.order = 6; F.serendip = false; break; - case MSH_HEX_512 : F.parentType = TYPE_HEX; F.order = 7; F.serendip = false; break; - case MSH_HEX_729 : F.parentType = TYPE_HEX; F.order = 8; F.serendip = false; break; - case MSH_HEX_1000: F.parentType = TYPE_HEX; F.order = 9; F.serendip = false; break; - case MSH_HEX_20 : F.parentType = TYPE_HEX; F.order = 2; F.serendip = false; break; - case MSH_HEX_56 : F.parentType = TYPE_HEX; F.order = 3; F.serendip = true; break; - case MSH_HEX_98 : F.parentType = TYPE_HEX; F.order = 4; F.serendip = true; break; - case MSH_HEX_152 : F.parentType = TYPE_HEX; F.order = 5; F.serendip = true; break; - case MSH_HEX_222 : F.parentType = TYPE_HEX; F.order = 6; F.serendip = true; break; - case MSH_HEX_296 : F.parentType = TYPE_HEX; F.order = 7; F.serendip = true; break; - case MSH_HEX_386 : F.parentType = TYPE_HEX; F.order = 8; F.serendip = true; break; - case MSH_HEX_488 : F.parentType = TYPE_HEX; F.order = 9; F.serendip = true; break; - default : - Msg::Error("Unknown function space %d: reverting to TET_4", tag); - F.parentType = TYPE_TET; F.order = 1; F.serendip = false; break; - } + switch (monomials.size2()) { + case 1: + for (int i = 0; i < coefficients.size1(); i++){ + hess[i][0][0] = hess[i][0][1] = hess[i][0][2] = 0; + hess[i][1][0] = hess[i][1][1] = hess[i][1][2] = 0; + hess[i][2][0] = hess[i][2][1] = hess[i][2][2] = 0; - switch (F.parentType) { - case TYPE_PNT : - F.numFaces = 1; - F.dimension = 0; - F.monomials = generate1DMonomials(0); - F.points = generate1DPoints(0); - break; - case TYPE_LIN : - F.numFaces = 2; - F.dimension = 1; - F.monomials = generate1DMonomials(F.order); - F.points = generate1DPoints(F.order); - generate1dVertexClosure(F.closures, F.order); - generate1dVertexClosureFull(F.fullClosures, F.closureRef, F.order); - break; - case TYPE_TRI : - F.numFaces = 3; - F.dimension = 2; - F.monomials = F.serendip ? generatePascalSerendipityTriangle(F.order) : - generatePascalTriangle(F.order); - F.points = gmshGeneratePointsTriangle(F.order, F.serendip); - if (F.order == 0) { - generateClosureOrder0(F.closures, 6); - generateClosureOrder0(F.fullClosures, 6); - F.closureRef.resize(6, 0); - } - else { - generate2dEdgeClosure(F.closures, F.order); - generate2dEdgeClosureFull(F.fullClosures, F.closureRef, F.order, 3, F.serendip); - } - break; - case TYPE_QUA : - F.numFaces = 4; - F.dimension = 2; - F.monomials = F.serendip ? generatePascalQuadSerendip(F.order) : - generatePascalQuad(F.order); - F.points = gmshGeneratePointsQuad(F.order, F.serendip); - if (F.order == 0) { - generateClosureOrder0(F.closures, 8); - generateClosureOrder0(F.fullClosures, 8); - F.closureRef.resize(8, 0); - } - else { - generate2dEdgeClosure(F.closures, F.order, 4); - generate2dEdgeClosureFull(F.fullClosures, F.closureRef, F.order, 4, F.serendip); + for(int j = 0; j < coefficients.size2(); j++){ + if (monomials(j, 0) > 1) // second derivative !=0 + hess[i][0][0] += coefficients(i, j) * pow_int(u, (int)(monomials(j, 0) - 2)) * + monomials(j, 0) * (monomials(j, 0) - 1); + } } break; - case TYPE_TET : - F.numFaces = 4; - F.dimension = 3; - F.monomials = F.serendip ? generatePascalSerendipityTetrahedron(F.order) : - generatePascalTetrahedron(F.order); - F.points = gmshGeneratePointsTetrahedron(F.order, F.serendip); - if (F.order == 0) { - generateClosureOrder0(F.closures,24); - generateClosureOrder0(F.fullClosures, 24); - F.closureRef.resize(24, 0); - } - else { - generateFaceClosureTet(F.closures, F.order); - generateFaceClosureTetFull(F.fullClosures, F.closureRef, F.order, F.serendip); + case 2: + for (int i = 0; i < coefficients.size1(); i++){ + hess[i][0][0] = hess[i][0][1] = hess[i][0][2] = 0; + hess[i][1][0] = hess[i][1][1] = hess[i][1][2] = 0; + hess[i][2][0] = hess[i][2][1] = hess[i][2][2] = 0; + for(int j = 0; j < coefficients.size2(); j++){ + if (monomials(j, 0) > 1) // second derivative !=0 + hess[i][0][0] += coefficients(i, j) * pow_int(u, (int)(monomials(j, 0) - 2)) * + monomials(j, 0) * (monomials(j, 0) - 1) * pow_int(v, (int)monomials(j, 1)); + if ((monomials(j, 1) > 0) && (monomials(j, 0) > 0)) + hess[i][0][1] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0) - 1) * monomials(j, 0) * + pow_int(v, (int)monomials(j, 1) - 1) * monomials(j, 1); + if (monomials(j, 1) > 1) + hess[i][1][1] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0)) * + pow_int(v, (int)monomials(j, 1) - 2) * monomials(j, 1) * (monomials(j, 1) - 1); + } + hess[i][1][0] = hess[i][0][1]; } break; - case TYPE_PRI : - F.numFaces = 5; - F.dimension = 3; - F.monomials = generatePascalPrism(F.order); - F.points = gmshGeneratePointsPrism(F.order, F.serendip); - if (F.order == 0) { - generateClosureOrder0(F.closures,48); - generateClosureOrder0(F.fullClosures,48); - F.closureRef.resize(48, 0); - } - else { - generateFaceClosurePrism(F.closures, F.order); - generateFaceClosurePrismFull(F.fullClosures, F.closureRef, F.order); + case 3: + for (int i = 0; i < coefficients.size1(); i++){ + hess[i][0][0] = hess[i][0][1] = hess[i][0][2] = 0; + hess[i][1][0] = hess[i][1][1] = hess[i][1][2] = 0; + hess[i][2][0] = hess[i][2][1] = hess[i][2][2] = 0; + for(int j = 0; j < coefficients.size2(); j++){ + if (monomials(j, 0) > 1) + hess[i][0][0] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0) - 2) * monomials(j, 0) * (monomials(j, 0)-1) * + pow_int(v, (int)monomials(j, 1)) * + pow_int(w, (int)monomials(j, 2)); + + if ((monomials(j, 0) > 0) && (monomials(j, 1) > 0)) + hess[i][0][1] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0) - 1) * monomials(j, 0) * + pow_int(v, (int)monomials(j, 1) - 1) * monomials(j, 1) * + pow_int(w, (int)monomials(j, 2)); + if ((monomials(j, 0) > 0) && (monomials(j, 2) > 0)) + hess[i][0][2] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0) - 1) * monomials(j, 0) * + pow_int(v, (int)monomials(j, 1)) * + pow_int(w, (int)monomials(j, 2) - 1) * monomials(j, 2); + if (monomials(j, 1) > 1) + hess[i][1][1] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0)) * + pow_int(v, (int)monomials(j, 1) - 2) * monomials(j, 1) * (monomials(j, 1)-1) * + pow_int(w, (int)monomials(j, 2)); + if ((monomials(j, 1) > 0) && (monomials(j, 2) > 0)) + hess[i][1][2] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0)) * + pow_int(v, (int)monomials(j, 1) - 1) * monomials(j, 1) * + pow_int(w, (int)monomials(j, 2) - 1) * monomials(j, 2); + if (monomials(j, 2) > 1) + hess[i][2][2] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0)) * + pow_int(v, (int)monomials(j, 1)) * + pow_int(w, (int)monomials(j, 2) - 2) * monomials(j, 2) * (monomials(j, 2) - 1); + } + hess[i][1][0] = hess[i][0][1]; + hess[i][2][0] = hess[i][0][2]; + hess[i][2][1] = hess[i][1][2]; } break; - case TYPE_HEX : - F.numFaces = 6; - F.dimension = 3; - F.monomials = generatePascalHex(F.order, F.serendip); - F.points = gmshGeneratePointsHex(F.order, F.serendip); - generateFaceClosureHex(F.closures, F.order, F.serendip, F.points); - generateFaceClosureHexFull(F.fullClosures, F.closureRef, F.order, F.serendip, F.points); - break; } - F.coefficients = generateLagrangeMonomialCoefficients(F.monomials, F.points); - fs.insert(std::make_pair(tag, F)); - return &fs[tag]; } -std::map<std::pair<int, int>, fullMatrix<double> > polynomialBases::injector; - -const fullMatrix<double> &polynomialBases::findInjector(int tag1, int tag2) -{ - std::pair<int,int> key(tag1,tag2); - std::map<std::pair<int, int>, fullMatrix<double> >::const_iterator it = - injector.find(key); - if (it != injector.end()) return it->second; - - const polynomialBasis& fs1 = *find(tag1); - const polynomialBasis& fs2 = *find(tag2); - fullMatrix<double> inj(fs1.points.size1(), fs2.points.size1()); - double sf[1256]; +void polynomialBasis::dddf(double u, double v, double w, double third[][3][3][3]) const +{ + switch (monomials.size2()) { + case 1: + for (int i = 0; i < coefficients.size1(); i++){ + for (int p=0; p<3; p++) + for (int q=0; q<3; q++) + for (int r=0; r<3; r++) + third[i][p][q][r] = 0.; - for (int i = 0; i < fs1.points.size1(); i++) { - fs2.f(fs1.points(i, 0), fs1.points(i, 1), fs1.points(i, 2), sf); - for (int j = 0; j < fs2.points.size1(); j++) inj(i, j) = sf[j]; + for(int j = 0; j < coefficients.size2(); j++){ + if (monomials(j, 0) > 2) // third derivative !=0 + third[i][0][0][0] += coefficients(i, j) * pow_int(u, (int)(monomials(j, 0) - 3)) * + monomials(j, 0) * (monomials(j, 0) - 1)*(monomials(j, 0) - 2); + } + } + break; + case 2: + for (int i = 0; i < coefficients.size1(); i++){ + for (int p=0; p<3; p++) + for (int q=0; q<3; q++) + for (int r=0; r<3; r++) + third[i][p][q][r] = 0.; + for(int j = 0; j < coefficients.size2(); j++){ + if (monomials(j, 0) > 2) // second derivative !=0 + third[i][0][0][0] += coefficients(i, j) * + pow_int(u, (int)(monomials(j, 0) - 3))*monomials(j, 0) * (monomials(j, 0) - 1) *(monomials(j, 0) - 2) * + pow_int(v, (int)monomials(j, 1)); + if ((monomials(j, 0) > 1) && (monomials(j, 1) > 0)) + third[i][0][0][1] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0) - 2) * monomials(j, 0)*(monomials(j, 0) - 1) * + pow_int(v, (int)monomials(j, 1) - 1) * monomials(j, 1); + if ((monomials(j, 0) > 0) && (monomials(j, 1) > 1)) + third[i][0][1][1] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0) - 1) *monomials(j, 0)* + pow_int(v, (int)monomials(j, 1) - 2) * monomials(j, 1) * (monomials(j, 1) - 1); + if (monomials(j, 1) > 2) + third[i][1][1][1] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0)) * + pow_int(v, (int)monomials(j, 1) - 3) * monomials(j, 1) * (monomials(j, 1) - 1)*(monomials(j, 1) - 2); + } + third[i][0][1][0] = third[i][0][0][1]; + third[i][1][0][0] = third[i][0][0][1]; + third[i][1][0][1] = third[i][0][1][1]; + third[i][1][1][0] = third[i][0][1][1]; + } + break; + case 3: + for (int i = 0; i < coefficients.size1(); i++){ + for (int p=0; p<3; p++) + for (int q=0; q<3; q++) + for (int r=0; r<3; r++) + third[i][p][q][r] = 0.; + for(int j = 0; j < coefficients.size2(); j++){ + if (monomials(j, 0) > 2) // second derivative !=0 + third[i][0][0][0] += coefficients(i, j) * + pow_int(u, (int)(monomials(j, 0) - 3)) *monomials(j, 0) * (monomials(j, 0) - 1)*(monomials(j, 0) - 2) * + pow_int(v, (int)monomials(j, 1))* + pow_int(w, (int)monomials(j, 2)); + + if ((monomials(j, 0) > 1) && (monomials(j, 1) > 0)) + third[i][0][0][1] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0) - 2) * monomials(j, 0)*(monomials(j, 0) - 1) * + pow_int(v, (int)monomials(j, 1) - 1) * monomials(j, 1)* + pow_int(w, (int)monomials(j, 2)); + + if ((monomials(j, 0) > 1) && (monomials(j, 2) > 0)) + third[i][0][0][2] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0) - 2) * monomials(j, 0)*(monomials(j, 0) - 1) * + pow_int(v, (int)monomials(j, 1)) * + pow_int(w, (int)monomials(j, 2) - 1)* monomials(j, 2); + + if ((monomials(j, 0) > 0) && (monomials(j, 1) > 1)) + third[i][0][1][1] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0) - 1) *monomials(j, 0)* + pow_int(v, (int)monomials(j, 1) - 2) * monomials(j, 1) * (monomials(j, 1) - 1)* + pow_int(w, (int)monomials(j, 2)); + + if ((monomials(j, 0) > 0) && (monomials(j, 1) > 0)&& (monomials(j, 2) > 0)) + third[i][0][1][2] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0) - 1) *monomials(j, 0)* + pow_int(v, (int)monomials(j, 1) - 1) *monomials(j, 1) * + pow_int(w, (int)monomials(j, 2) - 1) *monomials(j, 2); + + if ((monomials(j, 0) > 0) && (monomials(j, 2) > 1)) + third[i][0][2][2] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0) - 1) *monomials(j, 0)* + pow_int(v, (int)monomials(j, 1))* + pow_int(w, (int)monomials(j, 2) - 2) * monomials(j, 2) * (monomials(j, 2) - 1); + if ((monomials(j, 1) > 2)) + third[i][1][1][1] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0)) * + pow_int(v, (int)monomials(j, 1)-3) * monomials(j, 1) * (monomials(j, 1) - 1)*(monomials(j, 1) - 2)* + pow_int(w, (int)monomials(j, 2)); + + if ((monomials(j, 1) > 1) && (monomials(j, 2) > 0)) + third[i][1][1][2] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0)) * + pow_int(v, (int)monomials(j, 1)-2) * monomials(j, 1) * (monomials(j, 1) - 1)* + pow_int(w, (int)monomials(j, 2) - 1) *monomials(j, 2) ; + + if ((monomials(j, 1) > 0) && (monomials(j, 2) > 1)) + third[i][1][2][2] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0)) * + pow_int(v, (int)monomials(j, 1)-1) *monomials(j, 1)* + pow_int(w, (int)monomials(j, 2) - 2) * monomials(j, 2) * (monomials(j, 2) - 1) ; + + if ((monomials(j, 2) > 2)) + third[i][2][2][2] += coefficients(i, j) * + pow_int(u, (int)monomials(j, 0)) * + pow_int(v, (int)monomials(j, 1))* + pow_int(w, (int)monomials(j, 2) - 3) * monomials(j, 2) * (monomials(j, 2) - 1)*(monomials(j, 2) - 2); + + + } + third[i][0][1][0] = third[i][0][0][1]; + third[i][1][0][0] = third[i][0][0][1]; + + third[i][2][0][0] = third[i][0][0][2]; + third[i][0][2][0] = third[i][0][0][2]; + + third[i][1][0][1] = third[i][0][1][1]; + third[i][1][1][0] = third[i][0][1][1]; + + third[i][0][2][1] = third[i][0][1][2]; + third[i][1][0][2] = third[i][0][1][2]; + third[i][1][2][0] = third[i][0][1][2]; + third[i][2][1][0] = third[i][0][1][2]; + third[i][2][0][1] = third[i][0][1][2]; + + third[i][2][2][0] = third[i][0][2][2]; + third[i][2][0][2] = third[i][0][2][2]; + + third[i][1][2][1] = third[i][1][1][2]; + third[i][2][1][1] = third[i][1][1][2]; + + third[i][2][2][1] = third[i][1][2][2]; + third[i][2][1][2] = third[i][1][2][2]; + } + break; } - - injector.insert(std::make_pair(key, inj)); - return injector[key]; } diff --git a/Numeric/polynomialBasis.h b/Numeric/polynomialBasis.h index 17078d4e3e9f800731861e1cc7b193f2ca694c1e..4444efbb899053ac4368494879d8fc25e20f0f17 100644 --- a/Numeric/polynomialBasis.h +++ b/Numeric/polynomialBasis.h @@ -74,7 +74,7 @@ fullMatrix<double> generate1DMonomials(int order); class polynomialBasis : public nodalBasis { // integrationOrder, closureId => df/dXi - mutable std::map<int,std::vector<fullMatrix<double> > > _dfAtFace; +// mutable std::map<int,std::vector<fullMatrix<double> > > _dfAtFace; public: // for now the only implemented polynomial basis are nodal poly // basis, we use the type of the corresponding gmsh element as type @@ -85,372 +85,33 @@ class polynomialBasis : public nodalBasis fullMatrix<double> monomials; fullMatrix<double> coefficients; - void initialize(); + polynomialBasis(int tag); + ~polynomialBasis(); - inline int getNumShapeFunctions() const {return coefficients.size1();} - // for a given face/edge, with both a sign and a rotation, give an - // ordered list of nodes on this face/edge - inline int getClosureType(int id) const - { - return closures[id].type; - } - inline const std::vector<int> &getClosure(int id) const - { - return closures[id]; - } - inline const std::vector<int> &getFullClosure(int id) const - { - return fullClosures[id]; - } - inline int getClosureId(int iFace, int iSign=1, int iRot=0) const - { - return iFace + numFaces*(iSign == 1 ? 0 : 1) + 2*numFaces*iRot; - } - inline void breakClosureId(int i, int &iFace, int &iSign, int &iRot) const - { - iFace = i % numFaces; - i = (i - iFace)/numFaces; - iSign = i % 2; - iRot = (i - iSign) / 2; - } - inline void evaluateMonomials(double u, double v, double w, double p[]) const - { - for (int j = 0; j < monomials.size1(); j++) { - p[j] = pow_int(u, (int)monomials(j, 0)); - if (monomials.size2() > 1) p[j] *= pow_int(v, (int)monomials(j, 1)); - if (monomials.size2() > 2) p[j] *= pow_int(w, (int)monomials(j, 2)); - } - } - inline void f(double u, double v, double w, double *sf) const - { - double p[1256]; - evaluateMonomials(u, v, w, p); - for (int i = 0; i < coefficients.size1(); i++) { - sf[i] = 0.0; - for (int j = 0; j < coefficients.size2(); j++) { - sf[i] += coefficients(i, j) * p[j]; - } - } - } - inline void f(fullMatrix<double> &coord, fullMatrix<double> &sf) const - { - double p[1256]; - sf.resize (coord.size1(), coefficients.size1()); - for (int iPoint=0; iPoint< coord.size1(); iPoint++) { - evaluateMonomials(coord(iPoint,0), coord(iPoint,1), coord(iPoint,2), p); - for (int i = 0; i < coefficients.size1(); i++) - for (int j = 0; j < coefficients.size2(); j++) - sf(iPoint,i) += coefficients(i, j) * p[j]; - } - } - inline void df(fullMatrix<double> &coord, fullMatrix<double> &dfm) const - { - double dfv[1256][3]; - dfm.resize (coefficients.size1(), coord.size1() * 3, false); - int ii = 0; - int dimCoord = coord.size2(); - for (int iPoint=0; iPoint< coord.size1(); iPoint++) { - df(coord(iPoint,0), dimCoord > 1 ? coord(iPoint, 1) : 0., dimCoord > 2 ? coord(iPoint, 2) : 0., dfv); - for (int i = 0; i < coefficients.size1(); i++) { - dfm(i, iPoint * 3 + 0) = dfv[i][0]; - dfm(i, iPoint * 3 + 1) = dfv[i][1]; - dfm(i, iPoint * 3 + 2) = dfv[i][2]; - ++ii; - } - } - } - inline void df(double u, double v, double w, double grads[][3]) const - { - switch (monomials.size2()) { - case 1: - for (int i = 0; i < coefficients.size1(); i++){ - grads[i][0] = 0; - grads[i][1] = 0; - grads[i][2] = 0; - for(int j = 0; j < coefficients.size2(); j++){ - if (monomials(j, 0) > 0) - grads[i][0] += coefficients(i, j) * - pow_int(u, (int)(monomials(j, 0) - 1)) * monomials(j, 0); - } - } - break; - case 2: - for (int i = 0; i < coefficients.size1(); i++){ - grads[i][0] = 0; - grads[i][1] = 0; - grads[i][2] = 0; - for(int j = 0; j < coefficients.size2(); j++){ - if (monomials(j, 0) > 0) - grads[i][0] += coefficients(i, j) * - pow_int(u, (int)(monomials(j, 0) - 1)) * monomials(j, 0) * - pow_int(v, (int)monomials(j, 1)); - if (monomials(j, 1) > 0) - grads[i][1] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0)) * - pow_int(v, (int)(monomials(j, 1) - 1)) * monomials(j, 1); - } - } - break; - case 3: - for (int i = 0; i < coefficients.size1(); i++){ - grads[i][0] = 0; - grads[i][1] = 0; - grads[i][2] = 0; - for(int j = 0; j < coefficients.size2(); j++){ - if (monomials(j, 0) > 0) - grads[i][0] += coefficients(i, j) * - pow_int(u, (int)(monomials(j, 0) - 1)) * monomials(j, 0) * - pow_int(v, (int)monomials(j, 1)) * - pow_int(w, (int)monomials(j, 2)); - if (monomials(j, 1) > 0) - grads[i][1] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0)) * - pow_int(v, (int)(monomials(j, 1) - 1)) * monomials(j, 1) * - pow_int(w, (int)monomials(j, 2)); - if (monomials(j, 2) > 0) - grads[i][2] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0)) * - pow_int(v, (int)monomials(j, 1)) * - pow_int(w, (int)(monomials(j, 2) - 1)) * monomials(j, 2); - } - } - break; - } - } - inline void ddf(double u, double v, double w, double hess[][3][3]) const - { - switch (monomials.size2()) { - case 1: - for (int i = 0; i < coefficients.size1(); i++){ - hess[i][0][0] = hess[i][0][1] = hess[i][0][2] = 0; - hess[i][1][0] = hess[i][1][1] = hess[i][1][2] = 0; - hess[i][2][0] = hess[i][2][1] = hess[i][2][2] = 0; - - for(int j = 0; j < coefficients.size2(); j++){ - if (monomials(j, 0) > 1) // second derivative !=0 - hess[i][0][0] += coefficients(i, j) * pow_int(u, (int)(monomials(j, 0) - 2)) * - monomials(j, 0) * (monomials(j, 0) - 1); - } - } - break; - case 2: - for (int i = 0; i < coefficients.size1(); i++){ - hess[i][0][0] = hess[i][0][1] = hess[i][0][2] = 0; - hess[i][1][0] = hess[i][1][1] = hess[i][1][2] = 0; - hess[i][2][0] = hess[i][2][1] = hess[i][2][2] = 0; - for(int j = 0; j < coefficients.size2(); j++){ - if (monomials(j, 0) > 1) // second derivative !=0 - hess[i][0][0] += coefficients(i, j) * pow_int(u, (int)(monomials(j, 0) - 2)) * - monomials(j, 0) * (monomials(j, 0) - 1) * pow_int(v, (int)monomials(j, 1)); - if ((monomials(j, 1) > 0) && (monomials(j, 0) > 0)) - hess[i][0][1] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0) - 1) * monomials(j, 0) * - pow_int(v, (int)monomials(j, 1) - 1) * monomials(j, 1); - if (monomials(j, 1) > 1) - hess[i][1][1] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0)) * - pow_int(v, (int)monomials(j, 1) - 2) * monomials(j, 1) * (monomials(j, 1) - 1); - } - hess[i][1][0] = hess[i][0][1]; - } - break; - case 3: - for (int i = 0; i < coefficients.size1(); i++){ - hess[i][0][0] = hess[i][0][1] = hess[i][0][2] = 0; - hess[i][1][0] = hess[i][1][1] = hess[i][1][2] = 0; - hess[i][2][0] = hess[i][2][1] = hess[i][2][2] = 0; - for(int j = 0; j < coefficients.size2(); j++){ - if (monomials(j, 0) > 1) - hess[i][0][0] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0) - 2) * monomials(j, 0) * (monomials(j, 0)-1) * - pow_int(v, (int)monomials(j, 1)) * - pow_int(w, (int)monomials(j, 2)); - - if ((monomials(j, 0) > 0) && (monomials(j, 1) > 0)) - hess[i][0][1] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0) - 1) * monomials(j, 0) * - pow_int(v, (int)monomials(j, 1) - 1) * monomials(j, 1) * - pow_int(w, (int)monomials(j, 2)); - if ((monomials(j, 0) > 0) && (monomials(j, 2) > 0)) - hess[i][0][2] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0) - 1) * monomials(j, 0) * - pow_int(v, (int)monomials(j, 1)) * - pow_int(w, (int)monomials(j, 2) - 1) * monomials(j, 2); - if (monomials(j, 1) > 1) - hess[i][1][1] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0)) * - pow_int(v, (int)monomials(j, 1) - 2) * monomials(j, 1) * (monomials(j, 1)-1) * - pow_int(w, (int)monomials(j, 2)); - if ((monomials(j, 1) > 0) && (monomials(j, 2) > 0)) - hess[i][1][2] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0)) * - pow_int(v, (int)monomials(j, 1) - 1) * monomials(j, 1) * - pow_int(w, (int)monomials(j, 2) - 1) * monomials(j, 2); - if (monomials(j, 2) > 1) - hess[i][2][2] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0)) * - pow_int(v, (int)monomials(j, 1)) * - pow_int(w, (int)monomials(j, 2) - 2) * monomials(j, 2) * (monomials(j, 2) - 1); - } - hess[i][1][0] = hess[i][0][1]; - hess[i][2][0] = hess[i][0][2]; - hess[i][2][1] = hess[i][1][2]; - } - break; - } - } - inline void dddf(double u, double v, double w, double third[][3][3][3]) const - { - switch (monomials.size2()) { - case 1: - for (int i = 0; i < coefficients.size1(); i++){ - for (int p=0; p<3; p++) - for (int q=0; q<3; q++) - for (int r=0; r<3; r++) - third[i][p][q][r] = 0.; + virtual void f(double u, double v, double w, double *sf) const; + virtual void f(fullMatrix<double> &coord, fullMatrix<double> &sf) const; + virtual void df(fullMatrix<double> &coord, fullMatrix<double> &dfm) const; + virtual void df(double u, double v, double w, double grads[][3]) const; + virtual void ddf(double u, double v, double w, double hess[][3][3]) const; + virtual void dddf(double u, double v, double w, double third[][3][3][3]) const; - for(int j = 0; j < coefficients.size2(); j++){ - if (monomials(j, 0) > 2) // third derivative !=0 - third[i][0][0][0] += coefficients(i, j) * pow_int(u, (int)(monomials(j, 0) - 3)) * - monomials(j, 0) * (monomials(j, 0) - 1)*(monomials(j, 0) - 2); - } - } - break; - case 2: - for (int i = 0; i < coefficients.size1(); i++){ - for (int p=0; p<3; p++) - for (int q=0; q<3; q++) - for (int r=0; r<3; r++) - third[i][p][q][r] = 0.; - for(int j = 0; j < coefficients.size2(); j++){ - if (monomials(j, 0) > 2) // second derivative !=0 - third[i][0][0][0] += coefficients(i, j) * - pow_int(u, (int)(monomials(j, 0) - 3))*monomials(j, 0) * (monomials(j, 0) - 1) *(monomials(j, 0) - 2) * - pow_int(v, (int)monomials(j, 1)); - if ((monomials(j, 0) > 1) && (monomials(j, 1) > 0)) - third[i][0][0][1] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0) - 2) * monomials(j, 0)*(monomials(j, 0) - 1) * - pow_int(v, (int)monomials(j, 1) - 1) * monomials(j, 1); - if ((monomials(j, 0) > 0) && (monomials(j, 1) > 1)) - third[i][0][1][1] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0) - 1) *monomials(j, 0)* - pow_int(v, (int)monomials(j, 1) - 2) * monomials(j, 1) * (monomials(j, 1) - 1); - if (monomials(j, 1) > 2) - third[i][1][1][1] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0)) * - pow_int(v, (int)monomials(j, 1) - 3) * monomials(j, 1) * (monomials(j, 1) - 1)*(monomials(j, 1) - 2); - } - third[i][0][1][0] = third[i][0][0][1]; - third[i][1][0][0] = third[i][0][0][1]; - third[i][1][0][1] = third[i][0][1][1]; - third[i][1][1][0] = third[i][0][1][1]; - } - break; - case 3: - for (int i = 0; i < coefficients.size1(); i++){ - for (int p=0; p<3; p++) - for (int q=0; q<3; q++) - for (int r=0; r<3; r++) - third[i][p][q][r] = 0.; - for(int j = 0; j < coefficients.size2(); j++){ - if (monomials(j, 0) > 2) // second derivative !=0 - third[i][0][0][0] += coefficients(i, j) * - pow_int(u, (int)(monomials(j, 0) - 3)) *monomials(j, 0) * (monomials(j, 0) - 1)*(monomials(j, 0) - 2) * - pow_int(v, (int)monomials(j, 1))* - pow_int(w, (int)monomials(j, 2)); + virtual int getNumShapeFunctions() const; - if ((monomials(j, 0) > 1) && (monomials(j, 1) > 0)) - third[i][0][0][1] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0) - 2) * monomials(j, 0)*(monomials(j, 0) - 1) * - pow_int(v, (int)monomials(j, 1) - 1) * monomials(j, 1)* - pow_int(w, (int)monomials(j, 2)); + inline void evaluateMonomials(double u, double v, double w, double p[]) const; - if ((monomials(j, 0) > 1) && (monomials(j, 2) > 0)) - third[i][0][0][2] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0) - 2) * monomials(j, 0)*(monomials(j, 0) - 1) * - pow_int(v, (int)monomials(j, 1)) * - pow_int(w, (int)monomials(j, 2) - 1)* monomials(j, 2); - - if ((monomials(j, 0) > 0) && (monomials(j, 1) > 1)) - third[i][0][1][1] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0) - 1) *monomials(j, 0)* - pow_int(v, (int)monomials(j, 1) - 2) * monomials(j, 1) * (monomials(j, 1) - 1)* - pow_int(w, (int)monomials(j, 2)); - - if ((monomials(j, 0) > 0) && (monomials(j, 1) > 0)&& (monomials(j, 2) > 0)) - third[i][0][1][2] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0) - 1) *monomials(j, 0)* - pow_int(v, (int)monomials(j, 1) - 1) *monomials(j, 1) * - pow_int(w, (int)monomials(j, 2) - 1) *monomials(j, 2); - - if ((monomials(j, 0) > 0) && (monomials(j, 2) > 1)) - third[i][0][2][2] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0) - 1) *monomials(j, 0)* - pow_int(v, (int)monomials(j, 1))* - pow_int(w, (int)monomials(j, 2) - 2) * monomials(j, 2) * (monomials(j, 2) - 1); - if ((monomials(j, 1) > 2)) - third[i][1][1][1] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0)) * - pow_int(v, (int)monomials(j, 1)-3) * monomials(j, 1) * (monomials(j, 1) - 1)*(monomials(j, 1) - 2)* - pow_int(w, (int)monomials(j, 2)); - - if ((monomials(j, 1) > 1) && (monomials(j, 2) > 0)) - third[i][1][1][2] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0)) * - pow_int(v, (int)monomials(j, 1)-2) * monomials(j, 1) * (monomials(j, 1) - 1)* - pow_int(w, (int)monomials(j, 2) - 1) *monomials(j, 2) ; - - if ((monomials(j, 1) > 0) && (monomials(j, 2) > 1)) - third[i][1][2][2] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0)) * - pow_int(v, (int)monomials(j, 1)-1) *monomials(j, 1)* - pow_int(w, (int)monomials(j, 2) - 2) * monomials(j, 2) * (monomials(j, 2) - 1) ; - - if ((monomials(j, 2) > 2)) - third[i][2][2][2] += coefficients(i, j) * - pow_int(u, (int)monomials(j, 0)) * - pow_int(v, (int)monomials(j, 1))* - pow_int(w, (int)monomials(j, 2) - 3) * monomials(j, 2) * (monomials(j, 2) - 1)*(monomials(j, 2) - 2); - - - } - third[i][0][1][0] = third[i][0][0][1]; - third[i][1][0][0] = third[i][0][0][1]; - - third[i][2][0][0] = third[i][0][0][2]; - third[i][0][2][0] = third[i][0][0][2]; - - third[i][1][0][1] = third[i][0][1][1]; - third[i][1][1][0] = third[i][0][1][1]; - - third[i][0][2][1] = third[i][0][1][2]; - third[i][1][0][2] = third[i][0][1][2]; - third[i][1][2][0] = third[i][0][1][2]; - third[i][2][1][0] = third[i][0][1][2]; - third[i][2][0][1] = third[i][0][1][2]; +}; - third[i][2][2][0] = third[i][0][2][2]; - third[i][2][0][2] = third[i][0][2][2]; - third[i][1][2][1] = third[i][1][1][2]; - third[i][2][1][1] = third[i][1][1][2]; - third[i][2][2][1] = third[i][1][2][2]; - third[i][2][1][2] = third[i][1][2][2]; - } - break; - } +inline void polynomialBasis::evaluateMonomials(double u, double v, double w, double p[]) const +{ + for (int j = 0; j < monomials.size1(); j++) { + p[j] = pow_int(u, (int)monomials(j, 0)); + if (monomials.size2() > 1) p[j] *= pow_int(v, (int)monomials(j, 1)); + if (monomials.size2() > 2) p[j] *= pow_int(w, (int)monomials(j, 2)); } -}; +} + -class polynomialBases -{ - private: - static std::map<int, polynomialBasis> fs; - static std::map<std::pair<int, int>, fullMatrix<double> > injector; - public : - static const polynomialBasis *find(int); - static const fullMatrix<double> &findInjector(int, int); -}; #endif diff --git a/Numeric/pyramidalBasis.cpp b/Numeric/pyramidalBasis.cpp index 5c0bbe25c0dd3d39386747873fed9ace04263ee8..24a382d29ad734a8399de1c2bd01ba0ba224c368 100644 --- a/Numeric/pyramidalBasis.cpp +++ b/Numeric/pyramidalBasis.cpp @@ -4,17 +4,14 @@ // bugs and problems to <gmsh@geuz.org>. #include "pyramidalBasis.h" +#include "pointsGenerators.h" -pyramidalBasis::pyramidalBasis() -{ -} -void pyramidalBasis::initialize() +pyramidalBasis::pyramidalBasis(int tag) : nodalBasis(tag) { - BergotBasis bb(order); - bergot = bb; + bergot = new BergotBasis(order); int n = order+1; int num_points = n*(n+1)*(2*n+1)/6; @@ -28,31 +25,98 @@ void pyramidalBasis::initialize() fullMatrix<double> VDM = fullMatrix<double>(num_points, num_points); for (int j = 0; j < num_points; j++) { double f[num_points]; - bergot.f(points(j,0), points(j,1), points(j, 2), f); + bergot->f(points(j,0), points(j,1), points(j, 2), f); for (int i = 0; i < num_points; i++) { VDM(i,j) = f[i]; } } VDM.invert(*VDMinv); + } + + +pyramidalBasis::~pyramidalBasis() +{ + delete bergot; +} + + + inline void pyramidalBasis::f(double u, double v, double w, double *val) const { - int n = order+1; - int num_points = n*(n+1)*(2*n+1)/6; - double f[n*n*n]; - bergot.f(u,v,w, f); + const int N = bergot->size(); + + double f[N]; + bergot->f(u, v, w, f); + + for (int i = 0; i < N; i++) { + val[i] = 0.; + for (int j = 0; j < N; j++) val[i] += (*VDMinv)(i,j)*f[j]; + } + +} + + + +inline void pyramidalBasis::f(fullMatrix<double> &coord, fullMatrix<double> &sf) +{ + + const int N = bergot->size(), NPts = coord.size1(); + + sf.resize(NPts, N); + double f[N]; + fullVector<double> fVect(f,N); - for (int i = 0; i < num_points; i++) { - val[i] = 0.0; - for (int j = 0; j < num_points; j++) { - val[i] += (*VDMinv)(i,j)*f[j]; + for (int iPt=0; iPt<NPts; iPt++) { + bergot->f(coord(iPt,0), coord(iPt,0), coord(iPt,0), f); + for (int i = 0; i < N; i++) { + sf(iPt,i) = 0.; + for (int j = 0; j < N; j++) sf(iPt,i) += (*VDMinv)(i,j)*f[j]; } } + } + + inline void pyramidalBasis::df(double u, double v, double w, double grads[][3]) const { + const int N = bergot->size(); + + double df[N][3]; + bergot->df(u, v, w, df); + + for (int i = 0; i < N; i++) { + grads[i][0] = 0.; grads[i][1] = 0.; grads[i][2] = 0.; + for (int j = 0; j < N; j++) { + grads[i][0] += (*VDMinv)(i,j)*df[j][0]; + grads[i][1] += (*VDMinv)(i,j)*df[j][1]; + grads[i][2] += (*VDMinv)(i,j)*df[j][2]; + } + } + +} + + + +inline void pyramidalBasis::df(fullMatrix<double> &coord, fullMatrix<double> &dfm) const +{ + + const int N = bergot->size(), NPts = coord.size1(); + + double dfv[N][3]; + dfm.resize (NPts, 3*N, false); + + for (int iPt=0; iPt<NPts; iPt++) { + df(coord(iPt,0), coord(iPt,1), coord(iPt,2), dfv); + for (int i = 0; i < N; i++) { + dfm(i, 3*iPt+0) = dfv[i][0]; + dfm(i, 3*iPt+1) = dfv[i][1]; + dfm(i, 3*iPt+2) = dfv[i][2]; + } + } + } diff --git a/Numeric/pyramidalBasis.h b/Numeric/pyramidalBasis.h index 2b5b52aa6a6ba49b0f594a08e274a66815bec1eb..929ff85f85739e1bee1d49f4538299cc81c20822 100644 --- a/Numeric/pyramidalBasis.h +++ b/Numeric/pyramidalBasis.h @@ -11,6 +11,8 @@ #include "nodalBasis.h" #include "BergotBasis.h" + + class pyramidalBasis: public nodalBasis { private: @@ -18,16 +20,19 @@ class pyramidalBasis: public nodalBasis fullMatrix<double>* VDMinv; // Orthogonal basis for the pyramid - BergotBasis bergot; + BergotBasis *bergot; public: - pyramidalBasis(); - - inline void f(double u, double v, double w, double *val) const; - inline void df(double u, double v, double w, double grads[][3]) const; + pyramidalBasis(int tag); + ~pyramidalBasis(); - void initialize(); + virtual void f(double u, double v, double w, double *val) const; + virtual void f(fullMatrix<double> &coord, fullMatrix<double> &sf); + virtual void df(double u, double v, double w, double grads[][3]) const; + virtual void df(fullMatrix<double> &coord, fullMatrix<double> &dfm) const; }; + + #endif diff --git a/Post/PViewDataList.cpp b/Post/PViewDataList.cpp index 35575f7369510447334ce69169796256d4aaacfe..335edf3da5c5f3b12f1e492742b1b4164f151e16 100644 --- a/Post/PViewDataList.cpp +++ b/Post/PViewDataList.cpp @@ -6,7 +6,7 @@ #include "PViewDataList.h" #include "GmshMessage.h" #include "GmshDefines.h" -#include "polynomialBasis.h" +#include "BasisFactory.h" #include "Numeric.h" #include "SmoothData.h" #include "Context.h" @@ -883,11 +883,11 @@ void PViewDataList::setOrder2(int type) case TYPE_TET: typeMSH = MSH_TET_10; break; case TYPE_HEX: typeMSH = MSH_HEX_27; break; case TYPE_PRI: typeMSH = MSH_PRI_18; break; - case TYPE_PYR: typeMSH = MSH_PYR_14; break; +// case TYPE_PYR: typeMSH = MSH_PYR_14; break; } - const polynomialBasis *fs = polynomialBases::find(typeMSH); + const polynomialBasis *fs = (polynomialBasis*)BasisFactory::create(typeMSH); if(!fs){ - Msg::Error("Could not find function space for element type %d", typeMSH); + Msg::Error("Could not find polynomial function space for element type %d", typeMSH); return; } setInterpolationMatrices(type, fs->coefficients, fs->monomials, diff --git a/contrib/DiscreteIntegration/Integration3D.cpp b/contrib/DiscreteIntegration/Integration3D.cpp index 5a488939754d6b65e37fae30449eb95f621ca9bf..478fd0cace1de5f701bee190b07ffcaa56c202a0 100644 --- a/contrib/DiscreteIntegration/Integration3D.cpp +++ b/contrib/DiscreteIntegration/Integration3D.cpp @@ -620,7 +620,7 @@ DI_Element & DI_Element::operator= (const DI_Element &rhs){ void DI_Element::getShapeFunctions(double u, double v, double w, double s[], int o) const { //printf("type elem =%d order =%d\n", type(), o); - const polynomialBasis* fs = getFunctionSpace(o); + const nodalBasis* fs = getFunctionSpace(o); if(fs) fs->f(u, v, w, s); else Msg::Error("Function space not implemented for this type of element"); } @@ -628,7 +628,7 @@ void DI_Element::getShapeFunctions(double u, double v, double w, double s[], int void DI_Element::getGradShapeFunctions(double u, double v, double w, double s[][3], int o) const { - const polynomialBasis* fs = getFunctionSpace(o); + const nodalBasis* fs = getFunctionSpace(o); if(fs) fs->df(u, v, w, s); else Msg::Error("Function space not implemented for this type of element"); } @@ -642,7 +642,7 @@ void DI_Element::setPolynomialOrder (int o) { if(o == 1) return; - const polynomialBasis *fs = getFunctionSpace(o); + const nodalBasis *fs = getFunctionSpace(o); if(!fs) Msg::Error("Function space not implemented for this type of element"); mid_ = new DI_Point[nbMid()]; @@ -668,7 +668,7 @@ void DI_Element::setPolynomialOrder (int o, const DI_Element *e, const std::vect if(o == 1) return; - const polynomialBasis *fs = getFunctionSpace(o); + const nodalBasis *fs = getFunctionSpace(o); if(!fs) Msg::Error("Function space not implemented for this type of element"); mid_ = new DI_Point[nbMid()]; @@ -1042,10 +1042,10 @@ bool DI_ElementLessThan::operator()(const DI_Element *e1, const DI_Element *e2) } // DI_Line methods -------------------------------------------------------------------------------- -const polynomialBasis* DI_Line::getFunctionSpace(int o) const{ +const nodalBasis* DI_Line::getFunctionSpace(int o) const{ int order = (o == -1) ? getPolynomialOrder() : o; int tag = polynomialBasis::getTag(TYPE_LIN, order); - return polynomialBases::find(tag); + return BasisFactory::create(tag); } void DI_Line::computeIntegral() { @@ -1062,11 +1062,11 @@ void DI_Line::computeIntegral() { // } } // DI_Triangle methods ---------------------------------------------------------------------------- -const polynomialBasis* DI_Triangle::getFunctionSpace(int o) const +const nodalBasis* DI_Triangle::getFunctionSpace(int o) const { int order = (o == -1) ? getPolynomialOrder() : o; int tag = polynomialBasis::getTag(TYPE_TRI, order); - return polynomialBases::find(tag); + return BasisFactory::create(tag); } void DI_Triangle::computeIntegral() { integral_ = TriSurf(pt(0), pt(1), pt(2)); @@ -1087,10 +1087,10 @@ double DI_Triangle::quality() const { } // DI_Quad methods -------------------------------------------------------------------------------- -const polynomialBasis* DI_Quad::getFunctionSpace(int o) const{ +const nodalBasis* DI_Quad::getFunctionSpace(int o) const{ int order = (o == -1) ? getPolynomialOrder() : o; int tag = polynomialBasis::getTag(TYPE_QUA, order); - return polynomialBases::find(tag); + return BasisFactory::create(tag); } void DI_Quad::computeIntegral() { @@ -1111,10 +1111,10 @@ void DI_Quad::computeIntegral() { } // DI_Tetra methods ------------------------------------------------------------------------------- -const polynomialBasis* DI_Tetra::getFunctionSpace(int o) const{ +const nodalBasis* DI_Tetra::getFunctionSpace(int o) const{ int order = (o == -1) ? getPolynomialOrder() : o; int tag = polynomialBasis::getTag(TYPE_TET, order); - return polynomialBases::find(tag); + return BasisFactory::create(tag); } void DI_Tetra::computeIntegral() { @@ -1126,10 +1126,10 @@ double DI_Tetra::quality() const { // Hexahedron methods ----------------------------------------------------------------------------- -const polynomialBasis* DI_Hexa::getFunctionSpace(int o) const{ +const nodalBasis* DI_Hexa::getFunctionSpace(int o) const{ int order = (o == -1) ? getPolynomialOrder() : o; int tag = polynomialBasis::getTag(TYPE_HEX, order); - return polynomialBases::find(tag); + return BasisFactory::create(tag); } void DI_Hexa::computeIntegral() { integral_ = TetraVol(pt(0), pt(1), pt(3), pt(4)) + TetraVol(pt(1), pt(4), pt(5), pt(7)) diff --git a/contrib/DiscreteIntegration/Integration3D.h b/contrib/DiscreteIntegration/Integration3D.h index fdc1b93f8a397733adb7a8ee4985633acdf25e4f..c791cfc1fba67c07781382aed74dd52d2e0e4ed4 100644 --- a/contrib/DiscreteIntegration/Integration3D.h +++ b/contrib/DiscreteIntegration/Integration3D.h @@ -9,7 +9,7 @@ #include <map> #include <cmath> #include "gmshLevelset.h" -#include "polynomialBasis.h" +#include "BasisFactory.h" #include "GmshDefines.h" // Element type @@ -48,8 +48,8 @@ class DI_Point DI_Point (double x, double y, double z, const DI_Element *e, const std::vector<gLevelset *> &RPNi) : x_(x), y_(y), z_(z) {computeLs(e, RPNi);} virtual ~DI_Point(){} - virtual const polynomialBasis* getFunctionSpace(int o) const - { return polynomialBases::find(MSH_PNT); } + virtual const nodalBasis* getFunctionSpace(int o) const + { return BasisFactory::create(MSH_PNT); } virtual void getShapeFunctions(double u, double v, double w, double s[], int o) { s[0] = 1.; @@ -245,7 +245,7 @@ class DI_Element if(pts_) delete [] pts_; if(mid_) delete [] mid_; } - virtual const polynomialBasis* getFunctionSpace(int order=-1) const { return 0; } + virtual const nodalBasis* getFunctionSpace(int order=-1) const { return 0; } // return type virtual int type() const = 0; // return the dimension of the element @@ -410,7 +410,7 @@ class DI_Line : public DI_Element inline int nbVert() const {return 2;} inline int nbMid() const {return polOrder_ - 1;} inline int nbEdg() const {return 1;} - virtual const polynomialBasis* getFunctionSpace(int o=-1) const; + virtual const nodalBasis* getFunctionSpace(int o=-1) const; void computeIntegral(); inline double refIntegral() const {return 2.;} void getRefIntegrationPoints (const int polynomialOrder, @@ -477,7 +477,7 @@ class DI_Triangle : public DI_Element return 0.5 * (polOrder_ - 1) * (polOrder_ + 4); } inline int nbEdg() const {return 3;} - virtual const polynomialBasis* getFunctionSpace(int o=-1) const; + virtual const nodalBasis* getFunctionSpace(int o=-1) const; void computeIntegral(); inline double refIntegral() const {return 0.5;} void getRefIntegrationPoints (const int polynomialOrder, @@ -561,7 +561,7 @@ class DI_Quad : public DI_Element return (polOrder_ - 1) * (polOrder_ + 3); } inline int nbEdg() const {return 4;} - virtual const polynomialBasis* getFunctionSpace(int o=-1) const; + virtual const nodalBasis* getFunctionSpace(int o=-1) const; void computeIntegral(); inline double refIntegral() const {return 4.;} void getRefIntegrationPoints (const int polynomialOrder, @@ -643,7 +643,7 @@ class DI_Tetra : public DI_Element return (polOrder_ + 1) * (polOrder_ + 2) * (polOrder_ + 3) / 6 - 4; } inline int nbEdg() const {return 6;} - virtual const polynomialBasis* getFunctionSpace(int o=-1) const; + virtual const nodalBasis* getFunctionSpace(int o=-1) const; void computeIntegral(); inline double refIntegral() const {return 1. / 6.;} inline void getRefIntegrationPoints (const int polynomialOrder, @@ -745,7 +745,7 @@ class DI_Hexa : public DI_Element return (polOrder_ + 1) * (polOrder_ + 1) * (polOrder_ + 1) - 8; } inline int nbEdg() const {return 12;} - virtual const polynomialBasis* getFunctionSpace(int o=-1) const; + virtual const nodalBasis* getFunctionSpace(int o=-1) const; void computeIntegral(); inline double refIntegral() const {return 8.;} void getRefIntegrationPoints (const int polynomialOrder, diff --git a/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp b/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp index e940e8b3951b390ea1331087a49b14e757a3cdad..a37d265549d5d42dd52a683a2c1775de6fae214c 100644 --- a/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp +++ b/contrib/HighOrderMeshOptimizer/OptHomMesh.cpp @@ -150,10 +150,6 @@ SVector3 Mesh::getNormalEl(int iEl) return n; break; } - case TYPE_TET: { - return SVector3(0.); - break; - } default: std::cout << "ERROR: getNormalEl: Unknown element type" << std::endl; break; diff --git a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp index 610a41b858b5f6ffb0095e267cd824bde472627a..b713254b1e1bda8282e80ea24da9ee8e1f0d97c1 100644 --- a/contrib/HighOrderMeshOptimizer/OptHomRun.cpp +++ b/contrib/HighOrderMeshOptimizer/OptHomRun.cpp @@ -329,6 +329,9 @@ void HighOrderMeshOptimizer (GModel *gm, OptHomParameters &p) OptHomMessage("Optimizing a blob %i/%i composed of %4d elements", i+1, toOptimize.size(), toOptimize[i].first.size()); fflush(stdout); OptHOM temp(&entity, toOptimize[i].first, toOptimize[i].second, method); +std::ostringstream ossI1; +ossI1 << "initial_" << entity.tag() << "ITER_" << i << ".msh"; +temp.mesh.writeMSH(ossI1.str().c_str()); int success = temp.optimize(p.weightFixed, p.weightFree, p.BARRIER_MIN, p.BARRIER_MAX, false, samples, p.itMax, p.optPassMax); if (success >= 0 && p.BARRIER_MIN_METRIC > 0) { OptHomMessage("Jacobian optimization succeed, starting svd optimization");