1 // Gmsh - Copyright (C) 1997-2021 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #ifndef NODALBASIS_H
7 #define NODALBASIS_H
8 
9 #include "fullMatrix.h"
10 #include "GmshDefines.h"
11 
12 class nodalBasis {
13 public:
14   int type, parentType, order, dimension, numFaces;
15   bool serendip;
16   fullMatrix<double> points;
17 
nodalBasis()18   nodalBasis() {}
19   nodalBasis(int tag);
~nodalBasis()20   virtual ~nodalBasis() {}
21   virtual int getNumShapeFunctions() const = 0;
22   int getNumBubbleShapeFunctions() const;
getReferenceNodes(fullMatrix<double> & nodes)23   void getReferenceNodes(fullMatrix<double> &nodes) const { nodes = points; }
getReferenceNodes()24   const fullMatrix<double> &getReferenceNodes() const { return points; }
25 
26   // compute the matrix that projects the provided points on the current control
27   // points
28   bool forwardTransformation(const fullMatrix<double> &otherPoints,
29                              fullMatrix<double> &projection,
30                              int elementType = -1) const;
31 
32   // compute the renumbering vector to map the provided points on the current
33   // control points
34   bool forwardRenumbering(const fullMatrix<double> &otherPoints, int *renum,
35                           int elemenType = -1) const;
36 
37   // Basis functions & gradients evaluation
38   virtual void f(double u, double v, double w, double *sf) const = 0;
39   virtual void f(const fullMatrix<double> &coord,
40                  fullMatrix<double> &sf) const = 0;
41   virtual void f(double u, double v, double w, int i, double *sf) const = 0;
42   virtual void df(double u, double v, double w, double grads[][3]) const = 0;
43   virtual void df(const fullMatrix<double> &coord,
44                   fullMatrix<double> &dfm) const = 0;
45   virtual void df(double u, double v, double w, int i,
46                   double grad[3]) const = 0;
ddf(double u,double v,double w,double grads[][3][3])47   virtual void ddf(double u, double v, double w, double grads[][3][3]) const
48   {
49     Msg::Error("ddf not implemented for this basis");
50   }
dddf(double u,double v,double w,double grads[][3][3][3])51   virtual void dddf(double u, double v, double w, double grads[][3][3][3]) const
52   {
53     Msg::Error("dddf not implemented for this basis");
54   }
55 
56   // closures is the list of the nodes of each face, in the order of the
57   // polynomialBasis of the face; fullClosures is mapping of the nodes of the
58   // element that rotates the element so that the considered face becomes the
59   // first one in the right orientation; For element, like prisms that have
60   // different kind of faces, fullCLosure[i] rotates the element so that the
61   // considered face becomes the closureRef[i]-th face (the first triangle or
62   // the first quad face)
63   class closure : public std::vector<int> {
64   public:
65     int type;
66   };
67   typedef std::vector<closure> clCont;
68   clCont closures, fullClosures;
69   std::vector<int> closureRef;
70 
71   // for a given face/edge, with both a sign and a rotation, give an ordered
72   // list of nodes on this face/edge
getClosureType(int id)73   virtual int getClosureType(int id) const { return closures[id].type; }
getClosure(int id)74   virtual const std::vector<int> &getClosure(int id) const
75   {
76     return closures[id];
77   }
getFullClosure(int id)78   virtual const std::vector<int> &getFullClosure(int id) const
79   {
80     return fullClosures[id];
81   }
82   inline int getClosureId(int iFace, int iSign = 1, int iRot = 0) const;
83   inline void breakClosureId(int i, int &iFace, int &iSign, int &iRot) const;
84 };
85 
getClosureId(int iFace,int iSign,int iRot)86 inline int nodalBasis::getClosureId(int iFace, int iSign, int iRot) const
87 {
88   return iFace + numFaces * (iSign == 1 ? 0 : 1) + 2 * numFaces * iRot;
89 }
90 
breakClosureId(int i,int & iFace,int & iSign,int & iRot)91 inline void nodalBasis::breakClosureId(int i, int &iFace, int &iSign,
92                                        int &iRot) const
93 {
94   iFace = i % numFaces;
95   i = (i - iFace) / numFaces;
96   iSign = i % 2;
97   iRot = (i - iSign) / 2;
98 }
99 
100 #endif
101