proteus 1.9.0
C/C++/Fortran libraries
Loading...
Searching...
No Matches
equivalent_polynomials_utils.h
Go to the documentation of this file.
1#ifndef EQUIVALENT_POYNOMIALS_UTILS
2#define EQUIVALENT_POYNOMIALS_UTILS
4{
5 template<int nSpace>
6 inline void _calculate_normal(double* phys_nodes_cut, double* level_set_normal);
7
8 template<>
9 inline void _calculate_normal<1>(double* phys_nodes_cut, double* level_set_normal)
10 {
11 const unsigned int nSpace(1);
12 level_set_normal[0] = 1.0;
13 }
14
15 template<>
16 inline void _calculate_normal<2>(double* phys_nodes_cut, double* level_set_normal)
17 {
18 const unsigned int nSpace(2);
19 double level_set_tangent[2];
20 for(unsigned int I=0; I < nSpace; I++)
21 {
22 level_set_tangent[I] = phys_nodes_cut[3+I] - phys_nodes_cut[I];//nodes always 3D
23 }
24 level_set_normal[0] = level_set_tangent[1];
25 level_set_normal[1] = - level_set_tangent[0];
26 double norm = std::sqrt(level_set_normal[0]*level_set_normal[0] +
27 level_set_normal[1]*level_set_normal[1]);
28 if (norm > 0.0)
29 for(unsigned int I=0; I < nSpace; I++)
30 level_set_normal[I] /= norm;
31 else
32 {
33 for(unsigned int I=0; I < nSpace; I++)
34 level_set_normal[I] =0.0;
35 level_set_normal[1] = 1.0;
36 }
37 }
38
39 template<>
40 inline void _calculate_normal<3>(double* phys_nodes_cut, double* level_set_normal)
41 {
42 const unsigned int nSpace(3);
43 double level_set_tangent_a[3], level_set_tangent_b[3];
44 for(unsigned int I=0; I < nSpace; I++)
45 {
46 level_set_tangent_a[I] = phys_nodes_cut[3+I] - phys_nodes_cut[I];
47 level_set_tangent_b[I] = phys_nodes_cut[6+I] - phys_nodes_cut[I];
48 }
49 level_set_normal[0] = level_set_tangent_a[1]*level_set_tangent_b[2]
50 - level_set_tangent_a[2]*level_set_tangent_b[1];
51 level_set_normal[1] = - level_set_tangent_a[0]*level_set_tangent_b[2]
52 + level_set_tangent_a[2]*level_set_tangent_b[0];
53 level_set_normal[2] = level_set_tangent_a[0]*level_set_tangent_b[1]
54 - level_set_tangent_a[1]*level_set_tangent_b[0];
55 double norm = std::sqrt(level_set_normal[0]*level_set_normal[0] +
56 level_set_normal[1]*level_set_normal[1] +
57 level_set_normal[2]*level_set_normal[2]);
58 if (norm > 0.0)
59 for(unsigned int I=0; I < nSpace; I++)
60 level_set_normal[I] /= norm;
61 else
62 {
63 for(unsigned int I=0; I < nSpace; I++)
64 level_set_normal[I] =0.0;
65 level_set_normal[2] =1.0;
66 }
67 assert(std::fabs(1.0-level_set_normal[0]*level_set_normal[0] - level_set_normal[1]*level_set_normal[1] - level_set_normal[2]*level_set_normal[2]) < 1.0e-8);
68 }
69
70 inline void _calculate_normal_quad(double* phys_nodes_cut_quad_01,
71 double* phys_nodes_cut_quad_02,
72 double* phys_nodes_cut_quad_31,
73 double* phys_nodes_cut_quad_32,
74 double* level_set_normal)
75 {
76 const unsigned int nSpace(3);
77 double level_set_tangent_a[3], level_set_tangent_b[3], level_set_tangent_c[3], level_set_normal_2[3];
78 for(unsigned int I=0; I < nSpace; I++)
79 {
80 level_set_tangent_a[I] = phys_nodes_cut_quad_02[I] - phys_nodes_cut_quad_01[I];
81 level_set_tangent_b[I] = phys_nodes_cut_quad_32[I] - phys_nodes_cut_quad_01[I];
82 level_set_tangent_c[I] = phys_nodes_cut_quad_31[I] - phys_nodes_cut_quad_01[I];
83 }
84 level_set_normal[0] = level_set_tangent_a[1]*level_set_tangent_b[2] - level_set_tangent_a[2]*level_set_tangent_b[1];
85 level_set_normal[1] = - level_set_tangent_a[0]*level_set_tangent_b[2] + level_set_tangent_a[2]*level_set_tangent_b[0];
86 level_set_normal[2] = level_set_tangent_a[0]*level_set_tangent_b[1] - level_set_tangent_a[1]*level_set_tangent_b[0];
87 double norm = std::sqrt(level_set_normal[0]*level_set_normal[0] +
88 level_set_normal[1]*level_set_normal[1] +
89 level_set_normal[2]*level_set_normal[2]);
90 if (norm > 0.0)
91 {
92 for(unsigned int I=0; I < nSpace; I++)
93 level_set_normal[I] = level_set_normal[I] / norm;
94 }
95 else
96 {
97 for(unsigned int I=0; I < nSpace; I++)
98 level_set_normal[I] =0.0;
99 level_set_normal[2] = 1.0;
100 }
101 assert(std::fabs(1.0-level_set_normal[0]*level_set_normal[0] - level_set_normal[1]*level_set_normal[1] - level_set_normal[2]*level_set_normal[2]) < 1.0e-8);
102 }
103
104 template<int nP>
105 inline void _calculate_polynomial_1D(double* xi, double* C_H, double* C_ImH, double* C_D, double& _H, double& _ImH, double& _D)
106 {
107 _H = 0.0;
108 _ImH = 0.0;
109 _D = 0.0;
110 unsigned int iDOF = 0;
111 double x_pow_i=1.0;
112 for(unsigned int i=0; i < nP+1; i++, iDOF++)
113 {
114 double psi=x_pow_i;
115 _H += C_H[iDOF]*psi;
116 _ImH += C_ImH[iDOF]*psi;
117 _D += C_D[iDOF]*psi;
118 x_pow_i *= xi[0];
119 }
120 }
121
122 // calculate_edge_H / evaluate_edge_poly: the SCIFEM edge-restricted moment-fit Heaviside
123 // (ADR.h's ifem_boundaries facet term). Not a duplicate of _calculate_polynomial_1D above,
124 // despite the similar Horner loop: that function EVALUATES an already-computed (C_H,C_ImH,C_D)
125 // triple for a genuinely 1D *element* (Simplex<1,...>); calculate_edge_H instead COMPUTES a
126 // single H-only fit (via _set_Ainv<1,nP>/_calculate_b<1,nP> from
127 // equivalent_polynomials_coefficients.h) for one *edge* of a 2D/3D element, with the
128 // orientation-safe sign handling a facet needs. Orientation-safe: returns the fit for the
129 // indicator of {phi > 0} whichever way round the edge is parametrized. phi0/phi1 must have
130 // opposite signs (the edge must actually be cut).
131 template <int nP>
132 inline void calculate_edge_H(double phi0, double phi1, double C_H[nP + 1])
133 {
134 double theta = -phi0 / (phi1 - phi0);
135 double Ainv[(nP + 1) * (nP + 1)];
136 _set_Ainv<1, nP>(Ainv);
137 double b_H[nP + 1], b_ImH[nP + 1], b_dH[nP + 1];
138 _calculate_b<1, nP>(&theta, b_H, b_ImH, b_dH);
139 // _calculate_b assumes H=1 for t>theta (phi increasing along t); use the complementary
140 // moments when phi decreases instead, so C_H always fits the indicator of {phi>0}.
141 const double *b = (phi1 > phi0) ? b_H : b_ImH;
142 for (int i = 0; i <= nP; i++)
143 {
144 C_H[i] = 0.0;
145 for (int j = 0; j <= nP; j++)
146 C_H[i] += Ainv[i * (nP + 1) + j] * b[j];
147 }
148 }
149
150 template <int nP>
151 inline double evaluate_edge_poly(const double C[nP + 1], double t)
152 {
153 double val = 0.0, tpow = 1.0;
154 for (int i = 0; i <= nP; i++)
155 {
156 val += C[i] * tpow;
157 tpow *= t;
158 }
159 return val;
160 }
161
162 template<int nP>
163 inline void _calculate_polynomial_2D(double* xi, double* C_H, double* C_ImH, double* C_D, double& _H, double& _ImH, double& _D)
164 {
165 _H = 0.0;
166 _ImH = 0.0;
167 _D = 0.0;
168 unsigned int iDOF = 0;
169 double x_pow_i=1.0;
170 for(unsigned int i=0; i < nP+1; i++)
171 {
172 double y_pow_j=1.0;
173 for(unsigned int j=0; j < nP+1-i; j++, iDOF++)
174 {
175 double psi=x_pow_i*y_pow_j;
176 _H += C_H[iDOF]*psi;
177 _ImH += C_ImH[iDOF]*psi;
178 _D += C_D[iDOF]*psi;
179 y_pow_j *= xi[1];
180 }
181 x_pow_i *= xi[0];
182 }
183 }
184
185 template<int nP>
186 inline void _calculate_polynomial_3D(double* xi, double* C_H, double* C_ImH, double* C_D, double& _H, double& _ImH, double& _D)
187 {
188 _H = 0.0;
189 _ImH = 0.0;
190 _D = 0.0;
191 unsigned int iDOF = 0;
192 double x_pow_i=1.0;
193 for(unsigned int i=0; i < nP+1; i++)
194 {
195 double y_pow_j=1.0;
196 for(unsigned int j=0; j < nP+1-i; j++)
197 {
198 double x_pow_i_y_pow_j=x_pow_i*y_pow_j, z_pow_k=1.0;
199 for(unsigned int k=0; k < nP+1-i-j; k++, iDOF++)
200 {
201 double psi=x_pow_i_y_pow_j*z_pow_k;
202 _H += C_H[iDOF]*psi;
203 _ImH += C_ImH[iDOF]*psi;
204 _D += C_D[iDOF]*psi;
205 z_pow_k *= xi[2];
206 }
207 y_pow_j *= xi[1];
208 }
209 x_pow_i *= xi[0];
210 }
211 }
212
213 const int XX(0),XY(1),XZ(2),YX(3),YY(4),YZ(5),ZX(6),ZY(7),ZZ(8);
214
215 template<int nSpace>
216 inline double det(const double* A);
217
218 template<>
219 inline double det<1>(const double* A)
220 {
221 return A[0];
222 }
223
224 template<>
225 inline double det<2>(const double* A)
226 {
227 return A[0]*A[3] - A[1]*A[2];
228 }
229
230 template<>
231 inline double det<3>(const double* A)
232 {
233 return A[XX]*(A[YY]*A[ZZ] - A[YZ]*A[ZY]) -
234 A[XY]*(A[YX]*A[ZZ] - A[YZ]*A[ZX]) +
235 A[XZ]*(A[YX]*A[ZY] - A[YY]*A[ZX]);
236 }
237
238 template<int nSpace>
239 inline void inv(const double* A, double* Ainv);
240
241 template<>
242 inline void inv<1>(const double* A, double* Ainv)
243 {
244 Ainv[0] = 1.0/A[0];
245 }
246
247 template<>
248 inline void inv<2>(const double* A, double* Ainv)
249 {
250 double oneOverDet = 1.0/det<2>(A);
251 Ainv[0] = oneOverDet*A[3];
252 Ainv[1] = -oneOverDet*A[1];
253 Ainv[2] = -oneOverDet*A[2];
254 Ainv[3] = oneOverDet*A[0];
255 assert(fabs(Ainv[0]*A[0]+Ainv[1]*A[2]-1.0) < 1.0e-10);
256 assert(fabs(Ainv[0]*A[1]+Ainv[1]*A[3]) < 1.0e-10);
257 assert(fabs(Ainv[2]*A[0]+Ainv[3]*A[2]) < 1.0e-10);
258 assert(fabs(Ainv[2]*A[1]+Ainv[3]*A[3]-1.0) < 1.0e-10);
259 }
260
261 template<>
262 inline void inv<3>(const double* A, double* Ainv)
263 {
264 double oneOverDet = 1.0/det<3>(A);
265 Ainv[XX] = oneOverDet*(A[YY]*A[ZZ] - A[YZ]*A[ZY]);
266 Ainv[YX] = oneOverDet*(A[YZ]*A[ZX] - A[YX]*A[ZZ]);
267 Ainv[ZX] = oneOverDet*(A[YX]*A[ZY] - A[YY]*A[ZX]);
268 Ainv[XY] = oneOverDet*(A[ZY]*A[XZ] - A[ZZ]*A[XY]);
269 Ainv[YY] = oneOverDet*(A[ZZ]*A[XX] - A[ZX]*A[XZ]);
270 Ainv[ZY] = oneOverDet*(A[ZX]*A[XY] - A[ZY]*A[XX]);
271 Ainv[XZ] = oneOverDet*(A[XY]*A[YZ] - A[XZ]*A[YY]);
272 Ainv[YZ] = oneOverDet*(A[XZ]*A[YX] - A[XX]*A[YZ]);
273 Ainv[ZZ] = oneOverDet*(A[XX]*A[YY] - A[XY]*A[YX]);
274 }
275}//equivalent_polynomials
276#endif
Double psi
Definition Headers.h:78
void _calculate_polynomial_2D(double *xi, double *C_H, double *C_ImH, double *C_D, double &_H, double &_ImH, double &_D)
void inv(const double *A, double *Ainv)
void _calculate_normal_quad(double *phys_nodes_cut_quad_01, double *phys_nodes_cut_quad_02, double *phys_nodes_cut_quad_31, double *phys_nodes_cut_quad_32, double *level_set_normal)
double evaluate_edge_poly(const double C[nP+1], double t)
void _calculate_polynomial_1D(double *xi, double *C_H, double *C_ImH, double *C_D, double &_H, double &_ImH, double &_D)
void calculate_edge_H(double phi0, double phi1, double C_H[nP+1])
double det(const double *A)
void _set_Ainv(double *Ainv)
void _calculate_polynomial_3D(double *xi, double *C_H, double *C_ImH, double *C_D, double &_H, double &_ImH, double &_D)
void _calculate_normal(double *phys_nodes_cut, double *level_set_normal)
void _calculate_b(double *X_0, double *b_H, double *b_ImH, double *b_dH)