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 // Contributor(s):
7 //   Amaury Johnen
8 //
9 
10 #include "incompleteBasis.h"
11 #include "BasisFactory.h"
12 #include "ElementType.h"
13 
_computeCoefficientsTriangle()14 void incompleteBasis::_computeCoefficientsTriangle()
15 {
16   if(order < 3) {
17     coefficients.resize(0, 0);
18     return;
19   }
20 
21   int szInc = getNumShapeFunctions();
22   int szComp = completeBasis->getNumShapeFunctions();
23   coefficients.resize(szComp - szInc, szInc, true);
24 
25   std::map<std::pair<int, int>, int> coord2idx;
26   for(int i = 0; i < szInc; ++i) {
27     int u = static_cast<int>(points(i, 0) * order + .5);
28     int v = static_cast<int>(points(i, 1) * order + .5);
29     coord2idx[std::make_pair(u, v)] = i;
30   }
31 
32   int &n = order;
33   fullMatrix<double> pts = completeBasis->getReferenceNodes();
34   for(int i = 0; i < szComp - szInc; ++i) {
35     double xi = pts(szInc + i, 0);
36     double eta = pts(szInc + i, 1);
37     int u = static_cast<int>(xi * order + .5);
38     int v = static_cast<int>(eta * order + .5);
39 
40     coefficients(i, coord2idx[std::make_pair(u + v, 0)]) = xi;
41     coefficients(i, coord2idx[std::make_pair(n, 0)]) = -xi;
42     coefficients(i, coord2idx[std::make_pair(n - v, v)]) = xi;
43     coefficients(i, coord2idx[std::make_pair(u, n - u)]) = eta;
44     coefficients(i, coord2idx[std::make_pair(0, n)]) = -eta;
45     coefficients(i, coord2idx[std::make_pair(0, u + v)]) = eta;
46     coefficients(i, coord2idx[std::make_pair(0, v)]) = 1 - xi - eta;
47     coefficients(i, coord2idx[std::make_pair(0, 0)]) = -(1 - xi - eta);
48     coefficients(i, coord2idx[std::make_pair(u, 0)]) = 1 - xi - eta;
49   }
50 
51   coefficients.print("coefficients");
52 }
53 
incompleteBasis(int tag)54 incompleteBasis::incompleteBasis(int tag)
55   // If the element is complete, compute the incomplete basis anyway
56   : nodalBasis(ElementType::getType(ElementType::getParentType(tag),
57                                     ElementType::getOrder(tag), true)),
58     completeBasis(nullptr), polyBasis(nullptr)
59 {
60   int tagComplete = ElementType::getType(parentType, order, false);
61   switch(parentType) {
62   case TYPE_LIN:
63   case TYPE_PNT:
64   case TYPE_QUA:
65   case TYPE_HEX: polyBasis = new polynomialBasis(type); break;
66   case TYPE_TET:
67   case TYPE_PRI:
68   case TYPE_PYR:
69     completeBasis = BasisFactory::getNodalBasis(tagComplete);
70     break;
71   case TYPE_TRI:
72     completeBasis = BasisFactory::getNodalBasis(tagComplete);
73     _computeCoefficientsTriangle();
74     break;
75   }
76 }
77 
~incompleteBasis()78 incompleteBasis::~incompleteBasis() { delete polyBasis; }
79 
f(double u,double v,double w,double * sf) const80 void incompleteBasis::f(double u, double v, double w, double *sf) const
81 {
82   if(polyBasis)
83     polyBasis->f(u, v, w, sf);
84   else {
85     double csf[1331];
86     completeBasis->f(u, v, w, csf);
87     int szInc = getNumShapeFunctions();
88     for(int i = 0; i < szInc; ++i) {
89       sf[i] = csf[i];
90       for(int j = 0; j < coefficients.size1(); ++j) {
91         sf[i] += csf[szInc + j] * coefficients(j, i);
92       }
93     }
94   }
95 }
96 
f(const fullMatrix<double> & coord,fullMatrix<double> & sf) const97 void incompleteBasis::f(const fullMatrix<double> &coord,
98                         fullMatrix<double> &sf) const
99 {
100   if(polyBasis)
101     polyBasis->f(coord, sf);
102   else {
103     completeBasis->f(coord, sf);
104     int szInc = getNumShapeFunctions();
105     for(int k = 0; k < sf.size1(); ++k) {
106       for(int i = 0; i < szInc; ++i) {
107         for(int j = 0; j < coefficients.size1(); ++j) {
108           sf(k, i) += sf(k, szInc + j) * coefficients(j, i);
109         }
110       }
111     }
112     sf.resize(sf.size1(), szInc, false);
113   }
114 }
115 
df(const fullMatrix<double> & coord,fullMatrix<double> & dfm) const116 void incompleteBasis::df(const fullMatrix<double> &coord,
117                          fullMatrix<double> &dfm) const
118 {
119   if(polyBasis)
120     polyBasis->df(coord, dfm);
121   else {
122     completeBasis->df(coord, dfm);
123     int szInc = getNumShapeFunctions();
124     for(int k = 0; k < dfm.size1(); ++k) {
125       for(int i = 0; i < szInc; ++i) {
126         for(int j = 0; j < coefficients.size1(); ++j) {
127           dfm(k, i) += dfm(k, szInc + j) * coefficients(j, i);
128         }
129       }
130     }
131     dfm.resize(dfm.size1(), szInc, false);
132   }
133 }
134 
df(double u,double v,double w,double grads[][3]) const135 void incompleteBasis::df(double u, double v, double w, double grads[][3]) const
136 {
137   if(polyBasis)
138     polyBasis->df(u, v, w, grads);
139   else {
140     double cgrads[1331][3];
141     completeBasis->df(u, v, w, cgrads);
142     int szInc = getNumShapeFunctions();
143     for(int i = 0; i < szInc; ++i) {
144       grads[i][0] = cgrads[i][0];
145       grads[i][1] = cgrads[i][1];
146       grads[i][2] = cgrads[i][2];
147       for(int j = 0; j < coefficients.size1(); ++j) {
148         grads[i][0] = cgrads[szInc + j][0] * coefficients(j, i);
149         grads[i][1] = cgrads[szInc + j][1] * coefficients(j, i);
150         grads[i][2] = cgrads[szInc + j][2] * coefficients(j, i);
151       }
152     }
153   }
154 }
155 
ddf(double u,double v,double w,double hess[][3][3]) const156 void incompleteBasis::ddf(double u, double v, double w,
157                           double hess[][3][3]) const
158 {
159   if(polyBasis)
160     polyBasis->ddf(u, v, w, hess);
161   else {
162     double chess[1331][3][3];
163     completeBasis->ddf(u, v, w, chess);
164     int szInc = getNumShapeFunctions();
165     for(int i = 0; i < szInc; ++i) {
166       for(int k = 0; k < 3; ++k) {
167         for(int l = 0; l < 3; ++l) { hess[i][k][l] = chess[i][k][l]; }
168       }
169       for(int j = 0; j < coefficients.size1(); ++j) {
170         for(int k = 0; k < 3; ++k) {
171           for(int l = 0; l < 3; ++l) {
172             hess[i][k][l] = chess[szInc + j][k][l] * coefficients(j, i);
173           }
174         }
175       }
176     }
177   }
178 }
179 
dddf(double u,double v,double w,double third[][3][3][3]) const180 void incompleteBasis::dddf(double u, double v, double w,
181                            double third[][3][3][3]) const
182 {
183   if(polyBasis)
184     polyBasis->dddf(u, v, w, third);
185   else {
186     double cthird[1331][3][3][3];
187     completeBasis->dddf(u, v, w, cthird);
188     int szInc = getNumShapeFunctions();
189     for(int i = 0; i < szInc; ++i) {
190       for(int k = 0; k < 3; ++k) {
191         for(int l = 0; l < 3; ++l) {
192           for(int m = 0; m < 3; ++m) { third[i][k][l][m] = cthird[i][k][l][m]; }
193         }
194       }
195       for(int j = 0; j < coefficients.size1(); ++j) {
196         for(int k = 0; k < 3; ++k) {
197           for(int l = 0; l < 3; ++l) {
198             for(int m = 0; m < 3; ++m) {
199               third[i][k][l][m] =
200                 cthird[szInc + j][k][l][m] * coefficients(j, i);
201             }
202           }
203         }
204       }
205     }
206   }
207 }
208