GCC Code Coverage Report


Directory: ./
File: FiniteElement/elementVector.cpp
Date: 2024-04-14 07:32:34
Exec Total Coverage
Lines: 349 1472 23.7%
Branches: 389 2962 13.1%

Line Branch Exec Source
1 // ______ ______ _ _ _____ ______
2 // | ____| ____| | (_)/ ____| | ____|
3 // | |__ | |__ | | _| (___ ___| |__
4 // | __| | __| | | | |\___ \ / __| __|
5 // | | | |____| |____| |____) | (__| |____
6 // |_| |______|______|_|_____/ \___|______|
7 // Finite Elements for Life Sciences and Engineering
8 //
9 // License: LGL2.1 License
10 // FELiScE default license: LICENSE in root folder
11 //
12 // Main authors: J. Foulon & J-F. Gerbeau & V. Martin & Miguel Fernandez
13 //
14
15 // System includes
16 #include <numeric>
17
18 // External includes
19
20 // Project includes
21 #include "FiniteElement/elementVector.hpp"
22 #include "Geometry/curvatures.hpp"
23
24 namespace felisce
25 {
26
27 324810 ElementVector::ElementVector(const std::vector<const CurBaseFiniteElement*>& fe, const std::vector<std::size_t>& nbr) :
28
5/10
✓ Branch 9 taken 324810 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 324810 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 324810 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 324810 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 324810 times.
✗ Branch 22 not taken.
957945 m_vec( std::inner_product(fe.begin(),fe.end(),nbr.begin(), 0, std::plus<std::size_t>(), [](auto a, auto b){ return a->numDof()*b; }) )
29 {
30
1/2
✓ Branch 1 taken 324810 times.
✗ Branch 2 not taken.
324810 m_vec.clear();
31
32 // TODO are the following used whenever there is one finite element??
33 // If not would be better allocate the memory using an ad hoc method
34
2/2
✓ Branch 1 taken 16565 times.
✓ Branch 2 taken 308245 times.
324810 if (fe.size() == 1) {
35
1/2
✓ Branch 3 taken 16565 times.
✗ Branch 4 not taken.
16565 m_tmpVecDof.resize(fe[0]->numDof());
36
1/2
✓ Branch 3 taken 16565 times.
✗ Branch 4 not taken.
16565 m_tmpVecDof.resize(fe[0]->numCoor());
37
1/2
✓ Branch 5 taken 16565 times.
✗ Branch 6 not taken.
16565 m_tmpMatDof.resize(fe[0]->numCoor(),fe[0]->numCoor());
38
1/2
✓ Branch 3 taken 16565 times.
✗ Branch 4 not taken.
16565 m_tmpVecCoor.resize(fe[0]->numCoor());
39 }
40
41 //
42 324810 std::size_t sum = std::accumulate(nbr.begin(),nbr.end(), 0);
43
1/2
✓ Branch 1 taken 324810 times.
✗ Branch 2 not taken.
324810 m_numRow.resize(sum);
44
1/2
✓ Branch 1 taken 324810 times.
✗ Branch 2 not taken.
324810 m_firstRow.resize(sum);
45 //
46 324810 std::size_t first = 0;
47 324810 std::size_t start = 0;
48 324810 std::size_t end = 0;
49
2/2
✓ Branch 1 taken 633135 times.
✓ Branch 2 taken 324810 times.
957945 for (std::size_t i=0; i<nbr.size(); i++) {
50 633135 end += nbr[i];
51
2/2
✓ Branch 0 taken 1524365 times.
✓ Branch 1 taken 633135 times.
2157500 for (std::size_t n=start; n<end; n++){
52 1524365 m_numRow[ n ]=fe[i]->numDof();
53 1524365 m_firstRow[ n ]=first;
54 1524365 first += fe[i]->numDof();
55 }
56 633135 start += nbr[i];
57 }
58 324810 }
59
60 /***********************************************************************************/
61 /***********************************************************************************/
62
63 ElementVector::ElementVector(const CurBaseFiniteElement& fe1, const std::size_t nbr1) :
64 ElementVector(std::vector<const CurBaseFiniteElement*>{&fe1},
65 std::vector<std::size_t>{nbr1})
66 {
67
68 }
69
70 /***********************************************************************************/
71 /***********************************************************************************/
72
73 ElementVector::ElementVector(const CurBaseFiniteElement& fe1, const std::size_t nbr1,
74 const CurBaseFiniteElement& fe2, const std::size_t nbr2) :
75 ElementVector(std::vector<const CurBaseFiniteElement*>{&fe1,&fe2},
76 std::vector<std::size_t>{nbr1,nbr2})
77 {
78
79 }
80
81 /***********************************************************************************/
82 /***********************************************************************************/
83
84 ElementVector::ElementVector(const CurBaseFiniteElement& fe1, const std::size_t nbr1,
85 const CurBaseFiniteElement& fe2, const std::size_t nbr2,
86 const CurBaseFiniteElement& fe3, const std::size_t nbr3) :
87 ElementVector(std::vector<const CurBaseFiniteElement*>{&fe1,&fe2,&fe3},
88 std::vector<std::size_t>{nbr1,nbr2,nbr3})
89 {
90
91 }
92
93 /***********************************************************************************/
94 /***********************************************************************************/
95
96 8163406 void ElementVector::source(const double coef, const CurBaseFiniteElement& fe,const ElementField& elfield,const int iblock,const int numComp)
97 {
98 double tmp;
99
3/4
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 399837 times.
✓ Branch 3 taken 7763548 times.
✗ Branch 4 not taken.
8163406 switch(elfield.type()) {
100 21 case CONSTANT_FIELD:
101
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 21 times.
58 for(int icomp=0; icomp<numComp; icomp++) {
102
1/2
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
37 UBlasVectorRange vec = vecBlock(iblock+icomp);
103
2/2
✓ Branch 1 taken 82 times.
✓ Branch 2 taken 37 times.
119 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
104
2/4
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 82 times.
✗ Branch 5 not taken.
82 tmp = elfield.val(icomp,0) * fe.weightMeas(ig);
105
2/2
✓ Branch 1 taken 534 times.
✓ Branch 2 taken 82 times.
616 for(int idof=0; idof<fe.numDof(); idof++) {
106
2/4
✓ Branch 2 taken 534 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 534 times.
✗ Branch 6 not taken.
534 vec(idof) += coef * tmp * fe.phi[ig](idof);
107 }
108 }
109 37 }
110 21 break;
111 399837 case QUAD_POINT_FIELD:
112
2/2
✓ Branch 0 taken 1059172 times.
✓ Branch 1 taken 399837 times.
1459009 for(int icomp=0; icomp<numComp; icomp++) {
113
1/2
✓ Branch 1 taken 1059172 times.
✗ Branch 2 not taken.
1059172 UBlasVectorRange vec = vecBlock(iblock+icomp);
114
2/2
✓ Branch 1 taken 8600254 times.
✓ Branch 2 taken 1059172 times.
9659426 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
115
2/4
✓ Branch 1 taken 8600254 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8600254 times.
✗ Branch 5 not taken.
8600254 tmp = elfield.val(icomp,ig) * fe.weightMeas(ig);
116
2/2
✓ Branch 1 taken 37817090 times.
✓ Branch 2 taken 8600254 times.
46417344 for(int idof=0; idof<fe.numDof(); idof++) {
117
2/4
✓ Branch 2 taken 37817090 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 37817090 times.
✗ Branch 6 not taken.
37817090 vec(idof) += coef * tmp * fe.phi[ig](idof);
118 }
119 }
120 1059172 }
121 399837 break;
122 7763548 case DOF_FIELD:
123
2/2
✓ Branch 0 taken 21273472 times.
✓ Branch 1 taken 7763548 times.
29037020 for(int icomp=0; icomp<numComp; icomp++) {
124
1/2
✓ Branch 1 taken 21273472 times.
✗ Branch 2 not taken.
21273472 UBlasVectorRange vec = vecBlock(iblock+icomp);
125
2/2
✓ Branch 1 taken 124146625 times.
✓ Branch 2 taken 21273472 times.
145420097 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
126 124146625 tmp = 0.0;
127
2/2
✓ Branch 1 taken 528122752 times.
✓ Branch 2 taken 124146625 times.
652269377 for(int idof=0; idof<fe.numDof(); idof++) {
128
2/4
✓ Branch 2 taken 528122752 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 528122752 times.
✗ Branch 6 not taken.
528122752 tmp += fe.phi[ig](idof) * elfield.val(icomp,idof);
129 }
130
2/2
✓ Branch 1 taken 528122752 times.
✓ Branch 2 taken 124146625 times.
652269377 for(int idof=0; idof<fe.numDof(); idof++) {
131
3/6
✓ Branch 2 taken 528122752 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 528122752 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 528122752 times.
✗ Branch 9 not taken.
528122752 vec(idof) += coef * tmp * fe.phi[ig](idof) * fe.weightMeas(ig);
132 }
133 }
134 21273472 }
135 7763548 break;
136 // Default case should appear with a warning at compile time instead of an error in runtime
137 // (that's truly the point of using enums as switch cases)
138 // default:
139 // FEL_ERROR("Operator 'source' not yet implemented with this type of element fields");
140 }
141 8163406 }
142
143 /***********************************************************************************/
144 /***********************************************************************************/
145
146 void ElementVector::source_lumped(const double coef, const CurvilinearFiniteElement& fe,const ElementField& elfield,const int iblock,const int numComp)
147 {
148 double tmp;
149 switch(elfield.type()) {
150 case CONSTANT_FIELD:
151 for(int icomp=0; icomp<numComp; icomp++) {
152 UBlasVectorRange vec = vecBlock(iblock+icomp);
153 tmp = elfield.val(icomp,0) * fe.measure()/fe.numDof();
154 for(int idof=0; idof<fe.numDof(); idof++) {
155 vec(idof) += coef * tmp;
156 }
157 }
158 break;
159 case DOF_FIELD:
160 for(int icomp=0; icomp<numComp; icomp++) {
161 UBlasVectorRange vec = vecBlock(iblock+icomp);
162 for(int idof=0; idof<fe.numDof(); idof++) {
163 vec(idof) += coef * elfield.val(icomp,idof) * fe.measure()/fe.numDof();
164 }
165 }
166 break;
167 // Default case should appear with a warning at compile time instead of an error in runtime
168 // (that's truly the point of using enums as switch cases)
169 default:
170 FEL_ERROR("Operator 'source lumped' not yet implemented with this type of element fields");
171 }
172 }
173
174 /***********************************************************************************/
175 /***********************************************************************************/
176
177 172288 void ElementVector::sourceForComp(const double coef, const CurvilinearFiniteElement& fe,const ElementField& elfield,const int iblock, const int iComp)
178 {
179 double tmp;
180
1/2
✓ Branch 1 taken 172288 times.
✗ Branch 2 not taken.
172288 UBlasVectorRange vec = vecBlock(iblock);
181
2/4
✓ Branch 1 taken 165808 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6480 times.
✗ Branch 4 not taken.
172288 switch(elfield.type()) {
182 165808 case CONSTANT_FIELD:
183
2/2
✓ Branch 1 taken 550216 times.
✓ Branch 2 taken 165808 times.
716024 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
184
2/4
✓ Branch 1 taken 550216 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 550216 times.
✗ Branch 5 not taken.
550216 tmp = elfield.val(iComp,0) * fe.weightMeas(ig);
185
2/2
✓ Branch 1 taken 1610912 times.
✓ Branch 2 taken 550216 times.
2161128 for(int idof=0; idof<fe.numDof(); idof++) {
186
2/4
✓ Branch 2 taken 1610912 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1610912 times.
✗ Branch 6 not taken.
1610912 vec(idof) += coef * tmp * fe.phi[ig](idof);
187 }
188 }
189 165808 break;
190 case QUAD_POINT_FIELD:
191 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
192 tmp = elfield.val(iComp,ig) * fe.weightMeas(ig);
193 for(int idof=0; idof<fe.numDof(); idof++) {
194 vec(idof) += coef * tmp * fe.phi[ig](idof);
195 }
196 }
197 break;
198 6480 case DOF_FIELD:
199
2/2
✓ Branch 1 taken 19440 times.
✓ Branch 2 taken 6480 times.
25920 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
200 19440 tmp = 0.0;
201
2/2
✓ Branch 1 taken 38880 times.
✓ Branch 2 taken 19440 times.
58320 for(int idof=0; idof<fe.numDof(); idof++) {
202
2/4
✓ Branch 2 taken 38880 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 38880 times.
✗ Branch 6 not taken.
38880 tmp += fe.phi[ig](idof) * elfield.val(iComp,idof);
203 }
204
2/2
✓ Branch 1 taken 38880 times.
✓ Branch 2 taken 19440 times.
58320 for(int idof=0; idof<fe.numDof(); idof++) {
205
3/6
✓ Branch 2 taken 38880 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 38880 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 38880 times.
✗ Branch 9 not taken.
38880 vec(idof) += coef * tmp * fe.phi[ig](idof) * fe.weightMeas(ig);
206 }
207 }
208 6480 break;
209 // Default case should appear with a warning at compile time instead of an error in runtime
210 // (that's truly the point of using enums as switch cases)
211 // default:
212 // FEL_ERROR("Operator 'source' not yet implemented with this type of element fields");
213 }
214 172288 }
215
216 /***********************************************************************************/
217 /***********************************************************************************/
218
219 63280 void ElementVector::f_phi_i_scalar_n(const double coef,const CurvilinearFiniteElement& fe,const ElementField& elfield,const int iblock)
220 {
221 double tmp;
222
1/4
✓ Branch 1 taken 63280 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
63280 switch(elfield.type()) {
223 63280 case CONSTANT_FIELD:
224
2/2
✓ Branch 1 taken 184088 times.
✓ Branch 2 taken 63280 times.
247368 for(int icomp=0; icomp<fe.numCoor(); icomp++) {
225
1/2
✓ Branch 1 taken 184088 times.
✗ Branch 2 not taken.
184088 UBlasVectorRange vec = vecBlock(iblock+icomp);
226
2/2
✓ Branch 1 taken 595606 times.
✓ Branch 2 taken 184088 times.
779694 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
227
3/6
✓ Branch 1 taken 595606 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 595606 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 595606 times.
✗ Branch 9 not taken.
595606 tmp = coef * elfield.val(0,0) * fe.normal[ig](icomp) * fe.weightMeas(ig);
228
2/2
✓ Branch 1 taken 1879172 times.
✓ Branch 2 taken 595606 times.
2474778 for(int idof=0; idof<fe.numDof(); idof++) {
229
2/4
✓ Branch 2 taken 1879172 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1879172 times.
✗ Branch 6 not taken.
1879172 vec(idof) += tmp * fe.phi[ig](idof);
230 }
231 }
232 184088 }
233 63280 break;
234 case QUAD_POINT_FIELD:
235 for(int icomp=0; icomp<fe.numCoor(); icomp++) {
236 UBlasVectorRange vec = vecBlock(iblock+icomp);
237 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
238 tmp = coef * elfield.val(0,ig) * fe.normal[ig](icomp) * fe.weightMeas(ig);
239 for(int idof=0; idof<fe.numDof(); idof++) {
240 vec(idof) += tmp * fe.phi[ig](idof);
241 }
242 }
243 }
244 break;
245 case DOF_FIELD:
246 for(int icomp=0; icomp<fe.numCoor(); icomp++) {
247 UBlasVectorRange vec = vecBlock(iblock+icomp);
248 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
249 tmp = 0.0;
250 for(int jdof=0; jdof<fe.numDof(); jdof++) {
251 tmp += fe.phi[ig](jdof) * elfield.val(0,jdof);
252 }
253 for(int idof=0; idof<fe.numDof(); idof++) {
254 vec(idof) += coef * tmp * fe.phi[ig](idof) * fe.normal[ig](icomp)* fe.weightMeas(ig);
255 }
256 }
257 }
258 break;
259 // Default case should appear with a warning at compile time instead of an error in runtime
260 // (that's truly the point of using enums as switch cases)
261 default:
262 FEL_ERROR("Operator 'f_phi_i_scalar_n' not yet implemented with this type of element fields");
263 }
264 63280 }
265
266 /***********************************************************************************/
267 /***********************************************************************************/
268
269 void ElementVector::f_phi_i_scalar_piola_n(const double coef,const CurvilinearFiniteElement& fe,const ElementField& elf,const ElementField& elfd,const int iblock)
270 {
271 (void)coef;
272 (void)fe;
273 (void)elf;
274 (void)elfd;
275 (void)iblock;
276 //FEL_CHECK(fe.numCoor() == 3,"ElementVector::f_phi_i_scalar_JF_T_n: works only in 3D");
277
278 // double det, val, p = elf.val(0,0);
279 // std::vector<UBlasMatrix> piola;
280 // UBlasMatrix F, mLU;
281 // UBlasPermutationMatrix pm(fe.numCoor());
282 // piola.resize(fe.numQuadraturePoint());
283
284 // for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
285 // // evaluate piola at quadrature point
286 // piola[ig].resize(fe.numCoor(),fe.numCoor());
287 // F.clear();
288 // for(int l=0; l<fe.numDof(); ++l)
289 // for(int i=0; i<fe.numCoor(); ++i) {
290 // val = elfd.val(i,l); // d_i at node l
291 // for(int j=0; i<fe.numCoor(); ++i)
292 // F(i,j) += val*fe.dPhi[ig](j,l);
293 // }
294 // mLU = F;
295 // int ierr = lu_factorize(mLU, pm);
296 // FEL_CHECK(ierr==0,"LU factorization failed in f_phi_i_scalar_piola_n");
297 // det = 1.;
298 // for (std::size_t i=0; i < pm.size(); i++) {
299 // if (pm(i) != i)
300 // det *= -1.;
301 // det *= mLU(i,i);
302 // }
303 // F.assign(identity_matrix<double>(fe.numCoor()));
304 // lu_substitute(mLu,pm,F);
305 // piola[ig] = det * transpose(F);
306 // }
307
308 // for(int icomp=0; icomp<3; icomp++) {
309 // UBlasVectorRange vec = vecBlock(iblock+icomp);
310 // for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
311 // // evaluate F at quadrature point
312 // F.clear();
313 // for(int l=0; l<fe.numDof(); ++l)
314 // for(int i=0; i<3; ++i) {
315 // val = elfield.val(i,l) // d_i at node l
316 // for(int j=0; i<3; ++i)
317 // F(i,j) += val*fe.dPhi[ig](j,l);
318 // tmp = coef * p * fe.normal[ig](icomp) * fe.weightMeas(ig);
319 // for(int idof=0; idof<fe.numDof(); idof++) {
320 // vec(idof) += tmp * fe.phi[ig](idof);
321 // }
322 // }
323 // }
324 }
325
326 /***********************************************************************************/
327 /***********************************************************************************/
328
329 void ElementVector::penalty_contact_phi_i_scalar_n(const double coef,const std::vector<double>& normal, const CurvilinearFiniteElement& fe, const ElementField& disp, const ElementField& gap)
330 {
331 FEL_CHECK(disp.type() == DOF_FIELD,"ElementVector::penalty_contact_phi_i_scalar_n: wrong disp field type");
332 FEL_CHECK(gap.type() == QUAD_POINT_FIELD,"ElementVector::penalty_contact_phi_i_scalar_n: wrong gap field type");
333 double tmp;
334 const double hK2inv = 1./(fe.diameter()*fe.diameter());
335 for(int icomp=0; icomp<fe.numCoor(); icomp++) {
336 UBlasVectorRange vec = vecBlock(icomp);
337 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
338 tmp = 0.0;
339 // disp at coor point
340 for(int jcomp=0; jcomp<fe.numCoor(); jcomp++)
341 for(int jdof=0; jdof<fe.numDof(); jdof++)
342 tmp += fe.phi[ig](jdof)*disp.val(jcomp,jdof)*normal[jcomp];
343 // gap
344 tmp -= gap.val(0,ig);
345 // tmp contains (u \cdot n - g) at quand node ig
346 if (0 <= tmp ) {
347 for(int idof=0; idof<fe.numDof(); idof++) {
348 //std::cout << coef * (tmp-0.5) * fe.phi[ig](idof) * normal[icomp]* fe.weightMeas(ig) << std::endl;
349 vec(idof) += coef * hK2inv* tmp * fe.phi[ig](idof) * normal[icomp]* fe.weightMeas(ig);
350 }
351 }
352 }
353 }
354 }
355
356 /***********************************************************************************/
357 /***********************************************************************************/
358
359 3840 void ElementVector::penalty_phi_i_scalar_n(const double coef, CurvilinearFiniteElement& fe, const ElementField& vel, std::size_t iblock)
360 {
361
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3840 times.
3840 FEL_CHECK(vel.type() == DOF_FIELD,"ElementVector::penalty_phi_i_scalar_n: wrong vel field type");
362 double tmp;
363 3840 const double penalty = 1./coef;
364
2/2
✓ Branch 1 taken 7680 times.
✓ Branch 2 taken 3840 times.
11520 for(int icoor=0; icoor<fe.numCoor(); icoor++) {
365
1/2
✓ Branch 1 taken 7680 times.
✗ Branch 2 not taken.
7680 UBlasVectorRange vec = vecBlock(icoor+iblock);
366
2/2
✓ Branch 1 taken 23040 times.
✓ Branch 2 taken 7680 times.
30720 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
367 23040 tmp = 0.;
368
2/2
✓ Branch 1 taken 46080 times.
✓ Branch 2 taken 23040 times.
69120 for(int jcomp=0; jcomp<fe.numCoor(); jcomp++)
369
2/2
✓ Branch 1 taken 92160 times.
✓ Branch 2 taken 46080 times.
138240 for(int jdof=0; jdof<fe.numDof(); jdof++)
370
3/6
✓ Branch 2 taken 92160 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 92160 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 92160 times.
✗ Branch 10 not taken.
92160 tmp -= fe.phi[ig](jdof)*vel.val(jcomp,jdof)*fe.normal[ig][jcomp]; // compute u_dot_n
371
2/2
✓ Branch 0 taken 6132 times.
✓ Branch 1 taken 16908 times.
23040 if ( tmp >= 0. ) {
372
2/2
✓ Branch 1 taken 12264 times.
✓ Branch 2 taken 6132 times.
18396 for(int idof=0; idof<fe.numDof(); idof++)
373
4/8
✓ Branch 2 taken 12264 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 12264 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 12264 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 12264 times.
✗ Branch 13 not taken.
12264 vec(idof) += penalty*tmp*fe.phi[ig](idof)*fe.normal[ig][icoor]*fe.weightMeas(ig);
374 }
375 }
376 7680 }
377 3840 }
378
379 /***********************************************************************************/
380 /***********************************************************************************/
381
382 void ElementVector::nitsche_contact_phi_i_scalar_n(double gamma,const std::vector<double>& normal, const CurvilinearFiniteElement& fe, const ElementField& disp, const ElementField& gap, const ElementField& lambda)
383 {
384 FEL_CHECK(disp.type() == DOF_FIELD,"ElementVector::penalty_contact_phi_i_scalar_n: wrong disp field type");
385 FEL_CHECK(gap.type() == QUAD_POINT_FIELD,"ElementVector::penalty_contact_phi_i_scalar_n: wrong gap field type");
386 double tmp;
387 const double penalty = gamma / (fe.diameter()*fe.diameter());
388 const double penalty_inv = fe.diameter()*fe.diameter()/gamma;
389 for(int icomp=0; icomp<fe.numCoor(); icomp++) {
390 UBlasVectorRange vec = vecBlock(icomp);
391 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
392 tmp = 0.0;
393 // disp.n + 1/ gamma * lambda at coor point
394 for(int jcomp=0; jcomp<fe.numCoor(); jcomp++)
395 for(int jdof=0; jdof<fe.numDof(); jdof++)
396 tmp += fe.phi[ig](jdof)*(disp.val(jcomp,jdof)+ penalty_inv*lambda.val(jcomp,jdof)) *normal[jcomp];
397 // gap
398 tmp -= gap.val(0,ig);
399 // tmp contains (u \cdot n - g + 1/gamma \lambda ) at quand node ig
400 if (0 <= tmp ) {
401 for(int idof=0; idof<fe.numDof(); idof++) {
402 vec(idof) += penalty * tmp * fe.phi[ig](idof) * normal[icomp]* fe.weightMeas(ig);
403 }
404 }
405 }
406 }
407 }
408
409 /***********************************************************************************/
410 /***********************************************************************************/
411
412 void ElementVector::nitsche_contact_phi_i_scalar_n(double gamma, const CurvilinearFiniteElement& fe, const ElementField& disp, const ElementField& gap, const ElementField& normal, const ElementField& lambda)
413 {
414 FEL_CHECK(disp.type() == DOF_FIELD,"ElementVector::penalty_contact_phi_i_scalar_n: wrong disp field type");
415 FEL_CHECK(gap.type() == QUAD_POINT_FIELD,"ElementVector::penalty_contact_phi_i_scalar_n: wrong gap field type");
416 double tmp;
417 const double penalty = gamma / (fe.diameter()*fe.diameter());
418 const double penalty_inv = fe.diameter()*fe.diameter()/gamma;
419 for(int icomp=0; icomp<fe.numCoor(); icomp++) {
420 UBlasVectorRange vec = vecBlock(icomp);
421 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
422 tmp = 0.0;
423 // disp.n + 1/ gamma * lambda at coor point
424 for(int jcomp=0; jcomp<fe.numCoor(); jcomp++)
425 for(int jdof=0; jdof<fe.numDof(); jdof++)
426 tmp += fe.phi[ig](jdof)*(disp.val(jcomp,jdof)+ penalty_inv*lambda.val(jcomp,jdof)) *normal.val(jcomp,ig);
427 // gap
428 tmp -= gap.val(0,ig);
429 // tmp contains (u \cdot n - g + 1/gamma \lambda ) at quand node ig
430 if (0 <= tmp ) {
431 for(int idof=0; idof<fe.numDof(); idof++) {
432 vec(idof) += penalty * tmp * fe.phi[ig](idof) * normal.val(icomp,ig)* fe.weightMeas(ig);
433 }
434 }
435 }
436 }
437 }
438
439 /***********************************************************************************/
440 /***********************************************************************************/
441
442 void ElementVector::f_n_dot_phi_i(const double coef,const CurvilinearFiniteElement& fe1,const CurvilinearFiniteElement& fe2,const ElementField& elfield,const int iblock)
443 {
444 double tmp;
445 FEL_CHECK(fe1.numQuadraturePoint() == fe2.numQuadraturePoint(),"ElementVector::f_n_dot_phi_i: The quadrature rules must be the same for the two elements");
446 switch(elfield.type()) {
447 case CONSTANT_FIELD:
448 for(int icomp=0; icomp<fe1.numCoor(); icomp++) {
449 UBlasVectorRange vec = vecBlock(iblock+icomp);
450 for(int ig=0; ig<fe1.numQuadraturePoint(); ig++) {
451 tmp = coef * elfield.val(0,0) * fe1.normal[ig](icomp) * fe1.weightMeas(ig);
452 for(int idof=0; idof<fe1.numDof(); idof++) {
453 vec(idof) += tmp * fe1.phi[ig](idof);
454 }
455 }
456 }
457 break;
458 case QUAD_POINT_FIELD:
459 for(int icomp=0; icomp<fe1.numCoor(); icomp++) {
460 UBlasVectorRange vec = vecBlock(iblock+icomp);
461 for(int ig=0; ig<fe1.numQuadraturePoint(); ig++) {
462 tmp = coef * elfield.val(0,ig) * fe1.normal[ig](icomp) * fe1.weightMeas(ig);
463 for(int idof=0; idof<fe1.numDof(); idof++) {
464 vec(idof) += tmp * fe1.phi[ig](idof);
465 }
466 }
467 }
468 break;
469 case DOF_FIELD:
470 for(int icomp=0; icomp<fe1.numCoor(); icomp++) {
471 UBlasVectorRange vec = vecBlock(iblock+icomp);
472 for(int ig=0; ig<fe1.numQuadraturePoint(); ig++) {
473 tmp = 0.0;
474 for(int jdof=0; jdof<fe2.numDof(); jdof++) {
475 tmp += fe2.phi[ig](jdof) * elfield.val(0,jdof);
476 }
477 for(int idof=0; idof<fe1.numDof(); idof++) {
478 vec(idof) += coef * tmp * fe1.phi[ig](idof) * fe1.normal[ig](icomp)* fe1.weightMeas(ig);
479 }
480 }
481 }
482 break;
483 // Default case should appear with a warning at compile time instead of an error in runtime
484 // (that's truly the point of using enums as switch cases)
485 // default:
486 // FEL_ERROR("Operator 'f_n_dot_phi_i' not yet implemented with this type of element fields");
487 }
488 }
489
490 /***********************************************************************************/
491 /***********************************************************************************/
492
493 void ElementVector::f_dot_n_phi_i(const double coef,const CurvilinearFiniteElement& fe1,const CurvilinearFiniteElement& fe2, const ElementField& elfield,const int iblock)
494 {
495 double tmp,f_dot_n;
496 FEL_CHECK(fe1.numQuadraturePoint() == fe2.numQuadraturePoint(),"ElementVector::f_dot_n_phi_i: The quadrature rules must be the same for the two elements");
497 UBlasVectorRange vec = vecBlock(iblock);
498 switch(elfield.type()) {
499 case CONSTANT_FIELD:
500 for(int icomp=0; icomp<fe1.numCoor(); icomp++) {
501 // UBlasVectorRange vec = vecBlock(iblock + icomp)
502 for(int ig=0; ig<fe2.numQuadraturePoint(); ig++) {
503 tmp = coef * elfield.val(0,0) * fe1.normal[ig](icomp) * fe2.weightMeas(ig);
504 for(int idof=0; idof<fe2.numDof(); idof++) {
505 vec(idof) += tmp * fe2.phi[ig](idof);
506 }
507 }
508 }
509 break;
510 case QUAD_POINT_FIELD:
511 for(int icomp=0; icomp<fe1.numCoor(); icomp++) {
512 // UBlasVectorRange vec = vecBlock(iblock + icomp)
513 for(int ig=0; ig<fe2.numQuadraturePoint(); ig++) {
514 tmp = coef * elfield.val(0,ig) * fe1.normal[ig](icomp) * fe2.weightMeas(ig);
515 for(int idof=0; idof<fe2.numDof(); idof++) {
516 vec(idof) += tmp * fe2.phi[ig](idof);
517 }
518 }
519 }
520 break;
521 case DOF_FIELD:
522 for(int ig=0; ig<fe2.numQuadraturePoint(); ig++) {
523 f_dot_n = 0;
524 for(int icomp=0; icomp<fe1.numCoor(); icomp++) {
525 tmp = 0.0;
526 for(int jdof=0; jdof<fe1.numDof(); jdof++) {
527 tmp += fe1.phi[ig](jdof) * elfield.val(icomp,jdof);
528 }
529 f_dot_n += tmp * fe1.normal[ig](icomp);
530 }
531 for(int idof=0; idof<fe2.numDof(); idof++) {
532 vec(idof) += coef * f_dot_n * fe2.phi[ig](idof) * fe2.weightMeas(ig);
533 }
534 }
535 break;
536 // Default case should appear with a warning at compile time instead of an error in runtime
537 // (that's truly the point of using enums as switch cases)
538 // default:
539 // FEL_ERROR("Operator 'f_dot_n_phi_i' not yet implemented with this type of element fields");
540 }
541 }
542
543 /***********************************************************************************/
544 /***********************************************************************************/
545
546 void ElementVector::g_dot_n_f_phi_i(const double coef, const CurrentFiniteElement& fe, const ElementField& elt_f, const ElementField& elt_g, const ElementField& elt_n, felInt iblock, felInt numComp)
547 {
548 FEL_ASSERT(elt_f.type() == QUAD_POINT_FIELD);
549 FEL_ASSERT(elt_g.type() == DOF_FIELD);
550 FEL_ASSERT(elt_n.type() == CONSTANT_FIELD);
551
552 double tmp;
553 double g_dot_n = 0.0;
554
555 for(int icomp=0; icomp<numComp; icomp++) {
556 UBlasVectorRange vec = vecBlock(iblock + icomp);
557 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
558 g_dot_n = 0;
559 for(int jcomp=0; jcomp<fe.numCoor(); jcomp++) {
560 tmp = 0.0;
561 for(int jdof=0; jdof<fe.numDof(); jdof++) {
562 tmp += fe.phi[ig](jdof) * elt_g.val(jcomp, jdof);
563 }
564 g_dot_n += tmp * elt_n.val(jcomp, 0);
565 }
566
567 if(g_dot_n < 0)
568 for(int idof=0; idof<fe.numDof(); idof++)
569 vec(idof) += coef * g_dot_n * elt_f.val(icomp, ig) * fe.phi[ig](idof) * fe.weightMeas(ig);
570 }
571 }
572 }
573
574 /***********************************************************************************/
575 /***********************************************************************************/
576
577 void ElementVector::grad_vec2_dot_vec1_dot_phi_i(const double coef, const ElementField& vec1, const ElementField& vec2, const CurrentFiniteElement& fe, const int iblock, const int numComp)
578 {
579 // Mot implemented for other type yet
580 FEL_ASSERT(vec1.type() == CONSTANT_FIELD);
581
582 double tmpval1, tmpval2;
583
584 switch(vec2.type()) {
585 case CONSTANT_FIELD:
586 // nothing to do
587 break;
588
589 case QUAD_POINT_FIELD:
590 // cannot compute the derivative of vec2 at integration points
591 FEL_ERROR("grad_vec2_dot_vec1_dot_phi_i does not work with vec2 defined at integration points");
592 break;
593
594 case DOF_FIELD:
595 for(felInt iComp=0; iComp<numComp; ++iComp) {
596 UBlasVectorRange vec = vecBlock(iblock + iComp);
597 for(felInt idof=0; idof<fe.numDof(); ++idof) {
598 for(felInt ig=0; ig<fe.numQuadraturePoint(); ++ig) {
599 tmpval2 = 0.0;
600 for(felInt icoor=0; icoor<fe.numRefCoor(); ++icoor) {
601 tmpval1 = 0.0;
602 for(felInt jdof=0; jdof<fe.numDof(); ++jdof) {
603 tmpval1 += vec2.val(iComp, jdof) * fe.dPhi[ig](icoor, jdof);
604 }
605 tmpval2 += tmpval1 * vec1.val(icoor, 0);
606 }
607 vec(idof) += tmpval2 * coef * fe.phi[ig](idof) * fe.weightMeas(ig);
608 }
609 }
610 }
611 break;
612 }
613 }
614
615 /***********************************************************************************/
616 /***********************************************************************************/
617
618 4112 void ElementVector::eps_vec2_dot_vec1_dot_phi_i(const double coef, const ElementField& vec1, const ElementField& vec2, const CurrentFiniteElement& fe, const int iblock, const int numComp)
619 {
620 // Not implemented for other type yet
621
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4112 times.
4112 FEL_ASSERT(vec1.type() == CONSTANT_FIELD);
622
623 double tmpval1, tmpval2;
624
625
1/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4112 times.
✗ Branch 4 not taken.
4112 switch(vec2.type()) {
626 case CONSTANT_FIELD:
627 // nothing to do
628 break;
629
630 case QUAD_POINT_FIELD:
631 // cannot compute the derivative of vec2 at integration points
632 FEL_ERROR("eps_vec2_dot_vec1_dot_phi_i does not work with vec2 defined at integration points");
633 break;
634
635 4112 case DOF_FIELD:
636
2/2
✓ Branch 0 taken 8224 times.
✓ Branch 1 taken 4112 times.
12336 for(felInt iComp=0; iComp<numComp; ++iComp) {
637
1/2
✓ Branch 1 taken 8224 times.
✗ Branch 2 not taken.
8224 UBlasVectorRange vec = vecBlock(iblock + iComp);
638
2/2
✓ Branch 1 taken 24672 times.
✓ Branch 2 taken 8224 times.
32896 for(felInt idof=0; idof<fe.numDof(); ++idof) {
639
2/2
✓ Branch 1 taken 74016 times.
✓ Branch 2 taken 24672 times.
98688 for(felInt ig=0; ig<fe.numQuadraturePoint(); ++ig) {
640 74016 tmpval2 = 0.0;
641
2/2
✓ Branch 1 taken 148032 times.
✓ Branch 2 taken 74016 times.
222048 for(felInt icoor=0; icoor<fe.numRefCoor(); ++icoor) {
642 148032 tmpval1 = 0.0;
643
2/2
✓ Branch 1 taken 444096 times.
✓ Branch 2 taken 148032 times.
592128 for(felInt jdof=0; jdof<fe.numDof(); ++jdof) {
644
2/4
✓ Branch 1 taken 444096 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 444096 times.
✗ Branch 6 not taken.
444096 tmpval1 += vec2.val(iComp, jdof) * fe.dPhi[ig](icoor, jdof);
645
2/4
✓ Branch 1 taken 444096 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 444096 times.
✗ Branch 6 not taken.
444096 tmpval1 += vec2.val(icoor, jdof) * fe.dPhi[ig](iComp, jdof);
646 }
647
1/2
✓ Branch 1 taken 148032 times.
✗ Branch 2 not taken.
148032 tmpval2 += tmpval1 * vec1.val(icoor, 0);
648 }
649
3/6
✓ Branch 2 taken 74016 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 74016 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 74016 times.
✗ Branch 9 not taken.
74016 vec(idof) += tmpval2 * 0.5 * coef * fe.phi[ig](idof) * fe.weightMeas(ig);
650 }
651 }
652 8224 }
653 4112 break;
654 }
655 4112 }
656
657 /***********************************************************************************/
658 /***********************************************************************************/
659
660 void ElementVector::grad_phi_i_dot_vec1_dot_vec2(const double coef, const ElementField& vec1, const ElementField& vec2, const CurrentFiniteElement& fe, const int iblock, const int numComp)
661 {
662 // Not implemented for other type yet
663 FEL_ASSERT(vec1.type() == CONSTANT_FIELD);
664
665 double vecval;
666
667 switch(vec2.type()) {
668 case CONSTANT_FIELD:
669 for(felInt iComp=0; iComp<numComp; ++iComp) {
670 UBlasVectorRange vec = vecBlock(iblock + iComp);
671 for(felInt idof=0; idof<fe.numDof(); ++idof) {
672 for(felInt ig=0; ig<fe.numQuadraturePoint(); ++ig) {
673 for(felInt icoor=0; icoor<fe.numRefCoor(); ++icoor) {
674 vec(idof) += coef * fe.weightMeas(ig) * vec2.val(iComp, 0) * fe.dPhi[ig](icoor, idof) * vec1.val(icoor, 0);
675 }
676 }
677 }
678 }
679 break;
680
681 case QUAD_POINT_FIELD:
682 for(felInt iComp=0; iComp<numComp; ++iComp) {
683 UBlasVectorRange vec = vecBlock(iblock + iComp);
684 for(felInt idof=0; idof<fe.numDof(); ++idof) {
685 for(felInt ig=0; ig<fe.numQuadraturePoint(); ++ig) {
686 for(felInt icoor=0; icoor<fe.numRefCoor(); ++icoor) {
687 vec(idof) += coef * fe.weightMeas(ig) * vec2.val(iComp, ig) * fe.dPhi[ig](icoor, idof) * vec1.val(icoor, 0);
688 }
689 }
690 }
691 }
692 break;
693
694 case DOF_FIELD:
695 for(felInt iComp=0; iComp<numComp; ++iComp) {
696 UBlasVectorRange vec = vecBlock(iblock + iComp);
697 for(felInt idof=0; idof<fe.numDof(); ++idof) {
698 for(felInt ig=0; ig<fe.numQuadraturePoint(); ++ig) {
699 vecval = 0.0;
700 for(felInt kdof=0; kdof<fe.numDof(); ++kdof)
701 vecval += vec2.val(iComp, kdof) * fe.phi[ig](kdof);
702
703 for(felInt icoor=0; icoor<fe.numRefCoor(); ++icoor) {
704 vec(idof) += coef * fe.weightMeas(ig) * vecval * fe.dPhi[ig](icoor, idof) * vec1.val(icoor, 0);
705 }
706 }
707 }
708 }
709
710 break;
711 }
712 }
713
714 /***********************************************************************************/
715 /***********************************************************************************/
716
717 4112 void ElementVector::eps_phi_i_dot_vec1_dot_vec2(const double coef, const ElementField& vec1, const ElementField& vec2, const CurrentFiniteElement& fe, const int iblock, const int numComp)
718 {
719 // not implemented for other type yet
720
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4112 times.
4112 FEL_ASSERT(vec1.type() == CONSTANT_FIELD);
721
722 double vecvalComp, vecvalCoor;
723
724
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 4112 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
4112 switch(vec2.type()) {
725 case CONSTANT_FIELD:
726 for(felInt iComp=0; iComp<numComp; ++iComp) {
727 UBlasVectorRange vec = vecBlock(iblock + iComp);
728 for(felInt idof=0; idof<fe.numDof(); ++idof) {
729 for(felInt ig=0; ig<fe.numQuadraturePoint(); ++ig) {
730 for(felInt icoor=0; icoor<fe.numRefCoor(); ++icoor) {
731 vec(idof) += 0.5 * coef * fe.weightMeas(ig) * vec2.val(iComp, 0) * fe.dPhi[ig](icoor, idof) * vec1.val(icoor, 0);
732 vec(idof) += 0.5 * coef * fe.weightMeas(ig) * vec1.val(iComp, 0) * fe.dPhi[ig](icoor, idof) * vec2.val(icoor, 0);
733 }
734 }
735 }
736 }
737 break;
738
739 4112 case QUAD_POINT_FIELD:
740
2/2
✓ Branch 0 taken 8224 times.
✓ Branch 1 taken 4112 times.
12336 for(felInt iComp=0; iComp<numComp; ++iComp) {
741
1/2
✓ Branch 1 taken 8224 times.
✗ Branch 2 not taken.
8224 UBlasVectorRange vec = vecBlock(iblock + iComp);
742
2/2
✓ Branch 1 taken 24672 times.
✓ Branch 2 taken 8224 times.
32896 for(felInt idof=0; idof<fe.numDof(); ++idof) {
743
2/2
✓ Branch 1 taken 74016 times.
✓ Branch 2 taken 24672 times.
98688 for(felInt ig=0; ig<fe.numQuadraturePoint(); ++ig) {
744
2/2
✓ Branch 1 taken 148032 times.
✓ Branch 2 taken 74016 times.
222048 for(felInt icoor=0; icoor<fe.numRefCoor(); ++icoor) {
745
5/10
✓ Branch 1 taken 148032 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 148032 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 148032 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 148032 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 148032 times.
✗ Branch 15 not taken.
148032 vec(idof) += 0.5 * coef * fe.weightMeas(ig) * vec2.val(iComp, ig) * fe.dPhi[ig](icoor, idof) * vec1.val(icoor, 0);
746
5/10
✓ Branch 1 taken 148032 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 148032 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 148032 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 148032 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 148032 times.
✗ Branch 15 not taken.
148032 vec(idof) += 0.5 * coef * fe.weightMeas(ig) * vec1.val(iComp, 0) * fe.dPhi[ig](icoor, idof) * vec2.val(icoor, ig);
747 }
748 }
749 }
750 8224 }
751 4112 break;
752
753 case DOF_FIELD:
754 for(felInt iComp=0; iComp<numComp; ++iComp) {
755 UBlasVectorRange vec = vecBlock(iblock + iComp);
756 for(felInt idof=0; idof<fe.numDof(); ++idof) {
757 for(felInt ig=0; ig<fe.numQuadraturePoint(); ++ig) {
758 vecvalComp = 0.0;
759 for(felInt kdof=0; kdof<fe.numDof(); ++kdof)
760 vecvalComp += vec2.val(iComp, kdof) * fe.phi[ig](kdof);
761
762 for(felInt icoor=0; icoor<fe.numRefCoor(); ++icoor) {
763 vecvalCoor = 0.0;
764 for(felInt kdof=0; kdof<fe.numDof(); ++kdof)
765 vecvalCoor += vec2.val(icoor, kdof) * fe.phi[ig](kdof);
766
767 vec(idof) += 0.5 * coef * fe.weightMeas(ig) * vecvalComp * fe.dPhi[ig](icoor, idof) * vec1.val(icoor, 0);
768 vec(idof) += 0.5 * coef * fe.weightMeas(ig) * vec1.val(iComp, 0) * fe.dPhi[ig](icoor, idof) * vecvalCoor;
769 }
770 }
771 }
772 }
773
774 break;
775 }
776 4112 }
777
778 /***********************************************************************************/
779 /***********************************************************************************/
780
781 void ElementVector::eps_vec2_vec1_dot_eps_phi_i_vec1(const double coef, const ElementField& vec1, const ElementField& vec2, const CurrentFiniteElement& fe, const int iblock, const int numComp)
782 {
783 // not implemented for other type yet
784 FEL_ASSERT(vec1.type() == CONSTANT_FIELD);
785
786 double tmpval1, tmpval2;
787
788 switch(vec2.type()) {
789 case CONSTANT_FIELD:
790 // nothing to do
791 break;
792
793 case QUAD_POINT_FIELD:
794 // cannot compute the derivative of vec2 at integration points
795 FEL_ERROR("eps_vec2_dot_vec1_dot_phi_i does not work with vec2 defined at integration points");
796 break;
797
798 case DOF_FIELD:
799 for(felInt iComp=0; iComp<numComp; ++iComp) {
800 UBlasVectorRange vec = vecBlock(iblock + iComp);
801 for(felInt idof=0; idof<fe.numDof(); ++idof) {
802 for(felInt ig=0; ig<fe.numQuadraturePoint(); ++ig) {
803 tmpval2 = 0.0;
804 for(felInt icoor=0; icoor<fe.numRefCoor(); ++icoor) {
805 tmpval1 = 0.0;
806 for(felInt jdof=0; jdof<fe.numDof(); ++jdof) {
807 tmpval1 += vec2.val(iComp, jdof) * fe.dPhi[ig](icoor, jdof);
808 tmpval1 += vec2.val(icoor, jdof) * fe.dPhi[ig](iComp, jdof);
809 }
810 tmpval2 += tmpval1 * vec1.val(icoor, 0);
811 }
812
813 for(felInt icoor=0; icoor<fe.numRefCoor(); ++icoor) {
814 vec(idof) += 0.25 * coef * fe.weightMeas(ig) * tmpval2 * fe.dPhi[ig](icoor, idof) * vec1.val(icoor, 0);
815 vec(idof) += 0.25 * coef * fe.weightMeas(ig) * vec1.val(iComp, 0) * fe.dPhi[ig](icoor, idof) * tmpval2;
816 }
817 }
818 }
819 }
820 break;
821 }
822 }
823
824 /***********************************************************************************/
825 /***********************************************************************************/
826
827 void ElementVector::grad_vec2_vec1_dot_grad_phi_i_vec1(const double coef, const ElementField& vec1, const ElementField& vec2, const CurrentFiniteElement& fe, const int iblock, const int numComp)
828 {
829 // not implemented for other type yet
830 FEL_ASSERT(vec1.type() == CONSTANT_FIELD);
831
832 double tmpval1, tmpval2;
833
834 switch(vec2.type()) {
835 case CONSTANT_FIELD:
836 // nothing to do
837 break;
838
839 case QUAD_POINT_FIELD:
840 // cannot compute the derivative of vec2 at integration points
841 FEL_ERROR("grad_vec2_dot_vec1_dot_phi_i does not work with vec2 defined at integration points");
842 break;
843
844 case DOF_FIELD:
845 for(felInt iComp=0; iComp<numComp; ++iComp) {
846 UBlasVectorRange vec = vecBlock(iblock + iComp);
847 for(felInt idof=0; idof<fe.numDof(); ++idof) {
848 for(felInt ig=0; ig<fe.numQuadraturePoint(); ++ig) {
849 tmpval2 = 0.0;
850 for(felInt icoor=0; icoor<fe.numRefCoor(); ++icoor) {
851 tmpval1 = 0.0;
852 for(felInt jdof=0; jdof<fe.numDof(); ++jdof) {
853 tmpval1 += vec2.val(iComp, jdof) * fe.dPhi[ig](icoor, jdof);
854 }
855 tmpval2 += tmpval1 * vec1.val(icoor, 0);
856 }
857
858 for(felInt icoor=0; icoor<fe.numRefCoor(); ++icoor) {
859 vec(idof) += coef * fe.weightMeas(ig) * tmpval2 * fe.dPhi[ig](icoor, idof) * vec1.val(icoor, 0);
860 }
861 }
862 }
863 }
864 break;
865 }
866 }
867
868 /***********************************************************************************/
869 /***********************************************************************************/
870
871 void ElementVector::grad_phi_i_dot_n_f(const double coef,const CurrentFiniteElementWithBd& fewbd,
872 const ElementField& elfield,
873 const int iblockBd, const int numblockBd,
874 const int iblock, const int numComp)
875 {
876 FEL_ASSERT(iblockBd>=0 && iblockBd<fewbd.numBdEle() && (numblockBd-iblockBd) <= fewbd.numBdEle() );
877 FEL_ASSERT(static_cast<int>(m_tmpVecDof.size()) == fewbd.numDof() );
878
879 double tmp;
880 switch(elfield.type()) {
881 case CONSTANT_FIELD:
882 for(int icomp=0; icomp<numComp; icomp++) {
883 UBlasVectorRange vec = vecBlock(iblock+icomp);
884 for (int ibd=iblockBd; ibd<iblockBd+numblockBd; ibd++) {
885 FEL_ASSERT( fewbd.bdEle(ibd).hasNormal() && fewbd.hasFirstDeriv() );
886 for(int ilocg=0; ilocg<fewbd.numQuadPointBdEle(ibd); ilocg++) {
887 int ig = ilocg+fewbd.indexQuadPoint(ibd+1);
888 // face ibd starts at ibd+1 (0 for internal quad points)
889 //! Vector = [n \cdot \grad \phi]:
890 m_tmpVecDof = prod(trans(fewbd.bdEle(ibd).normal[ilocg]), fewbd.dPhi[ig]);
891 tmp = coef * elfield.val(icomp,0) * fewbd.bdEle(ibd).weightMeas(ilocg);
892 for(int idof=0; idof<fewbd.numDof(); idof++) {
893 // dphi_1/dn(idof) * f:
894 vec(idof) += tmp * m_tmpVecDof(idof);
895 }
896 }
897 }
898 }
899 break;
900 case QUAD_POINT_FIELD:
901 FEL_ASSERT( elfield.val.size2() == (std::size_t) fewbd.numQuadraturePointInternAndBd() ); //build the elfield from currentFEwBd
902 for(int icomp=0; icomp<numComp; icomp++) {
903 UBlasVectorRange vec = vecBlock(iblock+icomp);
904 for (int ibd=iblockBd; ibd<iblockBd+numblockBd; ibd++) {
905 FEL_ASSERT( fewbd.bdEle(ibd).hasNormal() && fewbd.hasFirstDeriv() );
906 for(int ilocg=0; ilocg<fewbd.numQuadPointBdEle(ibd); ilocg++) {
907 int ig = ilocg+fewbd.indexQuadPoint(ibd+1);
908 // face ibd starts at ibd+1 (0 for internal quad points)
909 //! Vector = [n \cdot \grad \phi]:
910 m_tmpVecDof = prod(trans(fewbd.bdEle(ibd).normal[ilocg]), fewbd.dPhi[ig]);
911 tmp = coef * elfield.val(icomp,ig) * fewbd.bdEle(ibd).weightMeas(ilocg);
912 for(int idof=0; idof<fewbd.numDof(); idof++) {
913 // dphi_1/dn(idof) * f:
914 vec(idof) += tmp * m_tmpVecDof(idof);
915 }
916 }
917 }
918 }
919 break;
920 case DOF_FIELD:
921 for(int icomp=0; icomp<numComp; icomp++) {
922 UBlasVectorRange vec = vecBlock(iblock+icomp);
923 for (int ibd=iblockBd; ibd<iblockBd+numblockBd; ibd++) {
924 FEL_ASSERT( fewbd.bdEle(ibd).hasNormal() && fewbd.hasFirstDeriv() );
925 for(int ilocg=0; ilocg<fewbd.numQuadPointBdEle(ibd); ilocg++) {
926 int ig = ilocg+fewbd.indexQuadPoint(ibd+1);
927 // face ibd starts at ibd+1 (0 for internal quad points)
928 //! Vector = [n \cdot \grad \phi]:
929 m_tmpVecDof = prod(trans(fewbd.bdEle(ibd).normal[ilocg]), fewbd.dPhi[ig]);
930
931 tmp = 0.0;
932 for(int idof=0; idof<fewbd.numDof(); idof++) {
933 tmp += fewbd.phi[ig](idof) * elfield.val(icomp,idof) * fewbd.bdEle(ibd).weightMeas(ilocg);
934 }
935 for(int idof=0; idof<fewbd.numDof(); idof++) {
936 // dphi_1/dn(idof) * f:
937 vec(idof) += coef * tmp * m_tmpVecDof(idof);
938 }
939 }
940 }
941 }
942 break;
943 // Default case should appear with a warning at compile time instead of an error in runtime
944 // (that's truly the point of using enums as switch cases)
945 // default:
946 // FEL_ERROR("Operator 'grad_phi_i_dot_n_f' not yet implemented with this type of element fields");
947 }
948 }
949
950 /***********************************************************************************/
951 /***********************************************************************************/
952
953 void ElementVector::grad_f_dot_n_phi_i(const double coef,const CurrentFiniteElementWithBd& fewbd,
954 const ElementField& elfield,
955 const int iblockBd, const int numblockBd,
956 const int iblock, const int numComp)
957 {
958 FEL_ASSERT(iblockBd>=0 && iblockBd<fewbd.numBdEle() && (numblockBd-iblockBd) <= fewbd.numBdEle() );
959 FEL_ASSERT( static_cast<int>(m_tmpVecDof.size()) == fewbd.numDof() );
960
961 double tmp;
962 switch(elfield.type()) {
963 case CONSTANT_FIELD:
964 // add nothing: grad cst = 0
965 break;
966 case QUAD_POINT_FIELD:
967 FEL_ERROR("Operator 'grad_f_dot_n_phi_i' is not well defined for quad_point_field: how to compute grad f ??");
968 break;
969 case DOF_FIELD:
970 for(int icomp=0; icomp<numComp; icomp++) {
971 UBlasVectorRange vec = vecBlock(iblock+icomp);
972 for (int ibd=iblockBd; ibd<iblockBd+numblockBd; ibd++) {
973 FEL_ASSERT( fewbd.bdEle(ibd).hasNormal() && fewbd.hasFirstDeriv() );
974 for(int ilocg=0; ilocg<fewbd.numQuadPointBdEle(ibd); ilocg++) {
975 int ig = ilocg+fewbd.indexQuadPoint(ibd+1);
976 // face ibd starts at ibd+1 (0 for internal quad points)
977 //! Vector = [n \cdot \grad \phi]:
978 m_tmpVecDof = prod(trans(fewbd.bdEle(ibd).normal[ilocg]), fewbd.dPhi[ig]);
979 tmp = 0.0;
980 for(int jdof=0; jdof<fewbd.numDof(); jdof++) {
981 //! tmp = [n \cdot \grad f] = \sum f_jdof (grad phi_jdof \cdot n)
982 tmp += m_tmpVecDof(jdof) * elfield.val(icomp,jdof);
983 }
984 tmp *= coef * fewbd.bdEle(ibd).weightMeas(ilocg);
985 for(int idof=0; idof<fewbd.bdEle(ibd).numDof(); idof++) {
986 //! df/dn *phi(idof):
987 vec(idof) += tmp * fewbd.bdEle(ibd).phi[ilocg](idof);
988 }
989 }
990 }
991 }
992 break;
993 // Default case should appear with a warning at compile time instead of an error in runtime
994 // (that's truly the point of using enums as switch cases)
995 // default:
996 // FEL_ERROR("Operator 'grad_f_dot_n_phi_i' not yet implemented with this type of element fields");
997 }
998 }
999
1000 /***********************************************************************************/
1001 /***********************************************************************************/
1002
1003 //----------------------------------------------------------------------
1004 // Operators \f$ \int_{\Sigma} (\grad f^T \dot n) \phi_i \f$,// shoudl be teseted !!!! saverio 8/10/2012
1005 //! where $\Sigma$ is a boundary element. (For Nitsche's treatment...)
1006 void ElementVector::grad_f_Transp_dot_n_phi_i(const double coef,const CurrentFiniteElementWithBd& fewbd,
1007 const ElementField& elfield,
1008 const int iblockBd, const int numblockBd,
1009 const int iblock, const int numComp)
1010 {
1011 FEL_ASSERT(iblockBd>=0 && iblockBd<fewbd.numBdEle() && (numblockBd-iblockBd) <= fewbd.numBdEle() );
1012 FEL_ASSERT( static_cast<int>(m_tmpVecDof.size()) == fewbd.numDof() );
1013 FEL_ASSERT( (int)m_tmpVecComp.size() == fewbd.numCoor());
1014 double tmp;
1015 switch(elfield.type()) {
1016 case CONSTANT_FIELD:
1017 // add nothing: grad cst = 0
1018 break;
1019 case QUAD_POINT_FIELD:
1020 FEL_ERROR("Operator 'grad_f_Transp_dot_n_phi_i' is not well defined for quad_point_field: how to compute grad f ??");
1021 break;
1022 case DOF_FIELD:
1023 for(int icomp=0; icomp<numComp; icomp++) {
1024 UBlasVectorRange vec = vecBlock(iblock+icomp);
1025 for (int ibd=iblockBd; ibd<iblockBd+numblockBd; ibd++) {
1026 FEL_ASSERT( fewbd.bdEle(ibd).hasNormal() && fewbd.hasFirstDeriv() );
1027 for(int ilocg=0; ilocg<fewbd.numQuadPointBdEle(ibd); ilocg++) {
1028 int ig = ilocg+fewbd.indexQuadPoint(ibd+1);
1029 // face ibd starts at ibd+1 (0 for internal quad points)
1030 //! Matrix = grad \phi cdot f
1031 m_tmpMatDof = prod(fewbd.dPhi[ig],trans(elfield.val));
1032 m_tmpVecComp = prod(m_tmpMatDof, fewbd.bdEle(ibd).normal[ilocg]);
1033 tmp = 0.0;
1034 //! tmp = [n \cdot \grad f] = \sum f_jdof (grad phi_jdof \cdot n)
1035 tmp = m_tmpVecComp(icomp);
1036 tmp *= coef * fewbd.bdEle(ibd).weightMeas(ilocg);
1037 for(int idof=0; idof<fewbd.bdEle(ibd).numDof(); idof++) {
1038 //! df/dn *phi(idof):
1039 vec(idof) += tmp * fewbd.bdEle(ibd).phi[ilocg](idof);
1040 }
1041 }
1042 }
1043 }
1044 break;
1045 // Default case should appear with a warning at compile time instead of an error in runtime
1046 // (that's truly the point of using enums as switch cases)
1047 // default:
1048 // FEL_ERROR("Operator 'grad_f_Transp_dot_n_phi_i' not yet implemented with this type of element fields");
1049 }
1050 }
1051
1052 /***********************************************************************************/
1053 /***********************************************************************************/
1054
1055 void ElementVector::f_dot_n_f_phi_i(const double coef,const CurvilinearFiniteElement& fe,
1056 const ElementField& elfield1,const ElementField& elfield2,
1057 const int iblock, const int numComp)
1058 {
1059 FEL_ASSERT(elfield1.type() != elfield2.type());
1060 double tmp1, tmp2, f_dot_n;
1061 switch(elfield1.type()) {
1062 case CONSTANT_FIELD:
1063 for(int icomp=0; icomp<numComp; icomp++) {
1064 UBlasVectorRange vec = vecBlock( iblock+icomp );
1065 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
1066 f_dot_n = 0.0;
1067 for(int icoor=0; icoor<fe.numCoor(); icoor++) {
1068 f_dot_n += elfield1.val(icoor,0)*fe.normal[ig](icoor);
1069 }
1070 tmp2 = elfield2.val(icomp,0) * fe.weightMeas(ig);
1071 for(int idof=0; idof<fe.numDof(); idof++) {
1072 vec(idof) += coef * f_dot_n * tmp2 * fe.phi[ig](idof);
1073 }
1074 }
1075 }
1076 break;
1077 case QUAD_POINT_FIELD:
1078 for(int icomp=0; icomp<numComp; icomp++) {
1079 UBlasVectorRange vec = vecBlock(iblock+icomp);
1080 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
1081 f_dot_n = 0.0;
1082 for(int icoor=0; icoor<fe.numCoor(); icoor++) {
1083 f_dot_n += elfield1.val(icoor,ig)*fe.normal[ig](icoor);
1084 }
1085 tmp2 = elfield2.val(icomp,ig) * fe.weightMeas(ig);
1086 for(int idof=0; idof<fe.numDof(); idof++) {
1087 vec(idof) += coef * f_dot_n * tmp2 * fe.phi[ig](idof);
1088 }
1089 }
1090 }
1091 break;
1092 case DOF_FIELD:
1093 for(int icomp=0; icomp<numComp; icomp++) {
1094 UBlasVectorRange vec = vecBlock(iblock+icomp);
1095 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
1096 tmp2 = 0.0;
1097 f_dot_n = 0.0;
1098 for(int icoor=0; icoor<fe.numCoor(); icoor++) {
1099 tmp1= 0.0;
1100 for(int jdof=0; jdof<fe.numDof(); jdof++) {
1101 tmp1 += fe.phi[ig](jdof) * elfield1.val(icoor,jdof);
1102 }
1103 //! sum f_icoor * n_icoor
1104 f_dot_n += tmp1 * fe.normal[ig](icoor);
1105 }
1106 for(int jdof=0; jdof<fe.numDof(); jdof++) {
1107 tmp2 += fe.phi[ig](jdof) * elfield2.val(icomp,jdof);
1108 }
1109 for(int idof=0; idof<fe.numDof(); idof++) {
1110 vec(idof) += coef * f_dot_n * tmp2 * fe.phi[ig](idof) * fe.weightMeas(ig);
1111 }
1112 }
1113 }
1114 break;
1115 // Default case should appear with a warning at compile time instead of an error in runtime
1116 // (that's truly the point of using enums as switch cases)
1117 // default:
1118 //FEL_ERROR("Operator 'f_dot_n_f_phi_i' not yet implemented with this type of element fields");
1119 }
1120 }
1121
1122 /***********************************************************************************/
1123 /***********************************************************************************/
1124
1125 2541420 void ElementVector::grad_f_phi_i(const double coef, const CurrentFiniteElement& fe1,const CurrentFiniteElement& fe2,const ElementField& elfield2,const int iblock)
1126 {
1127
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2541420 times.
2541420 FEL_CHECK(fe1.numQuadraturePoint() == fe2.numQuadraturePoint(),
1128 "ElementVector::grad_f_phi_i: The quadrature rules must be the same for the two elements");
1129 double tmp;
1130
1/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2541420 times.
✗ Branch 4 not taken.
2541420 switch(elfield2.type()) {
1131 case CONSTANT_FIELD:
1132 // add nothing: grad cst = 0
1133 break;
1134 case QUAD_POINT_FIELD:
1135 FEL_ERROR("ElementVector::grad_f_phi_i: Operator 'grad_f_phi_i' is not defined for quad_point_field: how to compute grad f ??");
1136 break;
1137 2541420 case DOF_FIELD:
1138
2/2
✓ Branch 1 taken 7624260 times.
✓ Branch 2 taken 2541420 times.
10165680 for (int icomp=0; icomp<fe1.numCoor(); icomp++) {
1139
1/2
✓ Branch 1 taken 7624260 times.
✗ Branch 2 not taken.
7624260 UBlasVectorRange vec = vecBlock(iblock+icomp);
1140
2/2
✓ Branch 1 taken 30497040 times.
✓ Branch 2 taken 7624260 times.
38121300 for(int ig=0; ig<fe1.numQuadraturePoint(); ig++) {
1141 30497040 tmp = 0.0;
1142
2/2
✓ Branch 1 taken 121988160 times.
✓ Branch 2 taken 30497040 times.
152485200 for (int jdof=0; jdof<fe2.numDof(); jdof++) {
1143
2/4
✓ Branch 2 taken 121988160 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 121988160 times.
✗ Branch 6 not taken.
121988160 tmp += fe2.dPhi[ig](icomp,jdof)*elfield2.val(0,jdof);
1144 }
1145
1/2
✓ Branch 1 taken 30497040 times.
✗ Branch 2 not taken.
30497040 tmp *= coef * fe1.weightMeas(ig);
1146
2/2
✓ Branch 1 taken 121988160 times.
✓ Branch 2 taken 30497040 times.
152485200 for(int idof=0; idof<fe1.numDof(); idof++) {
1147
2/4
✓ Branch 2 taken 121988160 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 121988160 times.
✗ Branch 6 not taken.
121988160 vec(idof) += tmp * fe1.phi[ig](idof);
1148 }
1149 }
1150 7624260 }
1151 2541420 break;
1152 }
1153 2541420 }
1154
1155 /***********************************************************************************/
1156 /***********************************************************************************/
1157
1158 void ElementVector::curl_f_phi_i(const double coef, const CurrentFiniteElement& fe1,const CurrentFiniteElement& fe2,const ElementField& elfield2,const int iblock)
1159 {
1160 FEL_CHECK(fe1.numQuadraturePoint() == fe2.numQuadraturePoint(), "ElementVector::curl_f_phi_i: The quadrature rules must be the same for the two elements");
1161 FEL_CHECK(fe1.numCoor() == 3, "ElementVector::curl_f_phi_i: curl not yet implemented in 2D");
1162 double tmp0,tmp1,tmp2;
1163 switch(elfield2.type()) {
1164 case CONSTANT_FIELD:
1165 // add nothing: curl cst = 0
1166 break;
1167 case QUAD_POINT_FIELD:
1168 FEL_ERROR("ElementVector::curl_f_phi_i: Operator 'curl_f_phi_i' is not defined for quad_point_field: how to compute curl f ??");
1169 break;
1170 case DOF_FIELD:
1171 UBlasVectorRange vec0 = vecBlock(iblock+0);
1172 UBlasVectorRange vec1 = vecBlock(iblock+1);
1173 UBlasVectorRange vec2 = vecBlock(iblock+2);
1174 for(int ig=0; ig<fe1.numQuadraturePoint(); ig++) {
1175 tmp0 = 0.0;
1176 tmp1 = 0.0;
1177 tmp2 = 0.0;
1178 for (int jdof=0; jdof<fe2.numDof(); jdof++) {
1179 tmp0 += fe2.dPhi[ig](1,jdof)*elfield2.val(2,jdof) - fe2.dPhi[ig](2,jdof)*elfield2.val(1,jdof);
1180 tmp1 += fe2.dPhi[ig](2,jdof)*elfield2.val(0,jdof) - fe2.dPhi[ig](0,jdof)*elfield2.val(2,jdof);
1181 tmp2 += fe2.dPhi[ig](0,jdof)*elfield2.val(1,jdof) - fe2.dPhi[ig](1,jdof)*elfield2.val(0,jdof);
1182 }
1183 tmp0 *= coef * fe1.weightMeas(ig);
1184 tmp1 *= coef * fe1.weightMeas(ig);
1185 tmp2 *= coef * fe1.weightMeas(ig);
1186 for(int idof=0; idof<fe1.numDof(); idof++) {
1187 vec0(idof) += tmp0 * fe1.phi[ig](idof);
1188 vec1(idof) += tmp1 * fe1.phi[ig](idof);
1189 vec2(idof) += tmp2 * fe1.phi[ig](idof);
1190 }
1191 }
1192 break;
1193 }
1194 }
1195
1196 /***********************************************************************************/
1197 /***********************************************************************************/
1198
1199 void ElementVector::WGX_dot_phi_i( const CurrentFiniteElement& feWGX, const CurrentFiniteElement& feWSS, const ElementField& WSSField, const int iblock)
1200 {
1201 double tmp0,tmp1,tmp2;
1202 switch(WSSField.type()) {
1203 case CONSTANT_FIELD:
1204 // add nothing: curl cst = 0
1205 break;
1206 case QUAD_POINT_FIELD:
1207 FEL_ERROR("ElementVector : not defined for quad_point_field");
1208 break;
1209 case DOF_FIELD:
1210 UBlasVectorRange vec0 = vecBlock(iblock+0);
1211 UBlasVectorRange vec1 = vecBlock(iblock+1);
1212 UBlasVectorRange vec2 = vecBlock(iblock+2);
1213 for(int ig=0; ig<feWGX.numQuadraturePoint(); ig++) {
1214
1215 tmp0 = 0.0;
1216 tmp1 = 0.0;
1217 tmp2 = 0.0;
1218
1219 for (int jdof=0; jdof<feWSS.numDof(); jdof++) {
1220 //std::cout<<"test WGX "<<WSSField.val(0,jdof)<<" "<<WSSField.val(1,jdof)<<" "<<WSSField.val(2,jdof)<<"\r";
1221 tmp0 += feWSS.dPhi[ig](0,jdof)*WSSField.val(0,jdof)* feWGX.weightMeas(ig);
1222 tmp1 += feWSS.dPhi[ig](1,jdof)*WSSField.val(0,jdof)* feWGX.weightMeas(ig);
1223 tmp2 += feWSS.dPhi[ig](2,jdof)*WSSField.val(0,jdof)* feWGX.weightMeas(ig);
1224 }
1225
1226 for(int idof=0; idof<feWGX.numDof(); idof++) {
1227 vec0(idof) += tmp0 * feWGX.phi[ig](idof);
1228 vec1(idof) += tmp1 * feWGX.phi[ig](idof);
1229 vec2(idof) += tmp2 * feWGX.phi[ig](idof);
1230
1231 }
1232 }
1233 break;
1234 }
1235 }
1236
1237 /***********************************************************************************/
1238 /***********************************************************************************/
1239
1240 void ElementVector::WGY_dot_phi_i( const CurrentFiniteElement& feWGY, const CurrentFiniteElement& feWSS, const ElementField& WSSField, const int iblock)
1241 {
1242 double tmp0,tmp1,tmp2;
1243 switch(WSSField.type()) {
1244 case CONSTANT_FIELD:
1245 // add nothing: curl cst = 0
1246 break;
1247 case QUAD_POINT_FIELD:
1248 FEL_ERROR("ElementVector : not defined for quad_point_field");
1249 break;
1250 case DOF_FIELD:
1251 UBlasVectorRange vec0 = vecBlock(iblock+0);
1252 UBlasVectorRange vec1 = vecBlock(iblock+1);
1253 UBlasVectorRange vec2 = vecBlock(iblock+2);
1254 for(int ig=0; ig<feWGY.numQuadraturePoint(); ig++) {
1255
1256 tmp0 = 0.0;
1257 tmp1 = 0.0;
1258 tmp2 = 0.0;
1259
1260 for (int jdof=0; jdof<feWSS.numDof(); jdof++) {
1261 //std::cout<<"test WGY "<<normalField.val(0,jdof)<<" "<<normalField.val(1,jdof)<<" "<<normalField.val(2,jdof)<<" "<<feWGY.weightMeas(ig)<<" "<<elfield_StressY.val(0,jdof)<<"\r";
1262 tmp0 += feWSS.dPhi[ig](0,jdof)*WSSField.val(1,jdof)*feWGY.weightMeas(ig);
1263 tmp1 += feWSS.dPhi[ig](1,jdof)*WSSField.val(1,jdof)*feWGY.weightMeas(ig);
1264 tmp2 += feWSS.dPhi[ig](2,jdof)*WSSField.val(1,jdof)*feWGY.weightMeas(ig);
1265
1266 }
1267
1268 for(int idof=0; idof<feWGY.numDof(); idof++) {
1269 vec0(idof) += tmp0 * feWGY.phi[ig](idof);
1270 vec1(idof) += tmp1 * feWGY.phi[ig](idof);
1271 vec2(idof) += tmp2 * feWGY.phi[ig](idof);
1272
1273 }
1274 }
1275 break;
1276 }
1277 }
1278
1279 /***********************************************************************************/
1280 /***********************************************************************************/
1281
1282 void ElementVector::WGZ_dot_phi_i( const CurrentFiniteElement& feWGZ, const CurrentFiniteElement& feWSS, const ElementField& WSSField, const int iblock)
1283 {
1284 double tmp0,tmp1,tmp2;
1285 switch(WSSField.type()) {
1286 case CONSTANT_FIELD:
1287 // add nothing: curl cst = 0
1288 break;
1289 case QUAD_POINT_FIELD:
1290 FEL_ERROR("ElementVector : not defined for quad_point_field");
1291 break;
1292 case DOF_FIELD:
1293 UBlasVectorRange vec0 = vecBlock(iblock+0);
1294 UBlasVectorRange vec1 = vecBlock(iblock+1);
1295 UBlasVectorRange vec2 = vecBlock(iblock+2);
1296 for(int ig=0; ig<feWGZ.numQuadraturePoint(); ig++) {
1297
1298 tmp0 = 0.0;
1299 tmp1 = 0.0;
1300 tmp2 = 0.0;
1301
1302 for (int jdof=0; jdof<feWSS.numDof(); jdof++) {
1303 //std::cout<<"test WGZ "<<normalField.val(0,jdof)<<" "<<normalField.val(1,jdof)<<" "<<normalField.val(2,jdof)<<" "<<feWGZ.weightMeas(ig)<<" "<<elfield_StressZ.val(0,jdof)<<"\r";
1304 tmp0 += feWSS.dPhi[ig](0,jdof)*WSSField.val(2,jdof)*feWGZ.weightMeas(ig);
1305 tmp1 += feWSS.dPhi[ig](1,jdof)*WSSField.val(2,jdof)*feWGZ.weightMeas(ig);
1306 tmp2 += feWSS.dPhi[ig](2,jdof)*WSSField.val(2,jdof)*feWGZ.weightMeas(ig);
1307 }
1308
1309 for(int idof=0; idof<feWGZ.numDof(); idof++) {
1310 vec0(idof) += tmp0 * feWGZ.phi[ig](idof);
1311 vec1(idof) += tmp1 * feWGZ.phi[ig](idof);
1312 vec2(idof) += tmp2 * feWGZ.phi[ig](idof);
1313 }
1314 }
1315 break;
1316 }
1317 }
1318
1319 /***********************************************************************************/
1320 /***********************************************************************************/
1321
1322 void ElementVector::stressX_dot_phi_i(const double viscosity, const CurrentFiniteElement& fePres,const CurrentFiniteElement& feStress,const CurrentFiniteElement& feVel,const ElementField& elfield_pressure,const ElementField& elfield_velocity,const int iblock)
1323 {
1324 FEL_CHECK(feStress.numQuadraturePoint() == feVel.numQuadraturePoint(), "ElementVector::stressX_dot_phi_i: The quadrature rules must be the same for all the elements");
1325 FEL_CHECK(feStress.numCoor() == 3, "ElementVector::stressX_dot_phi_i: not yet implemented in 2D");
1326 double tmp0,tmp1,tmp2;
1327 switch(elfield_velocity.type()) {
1328 case CONSTANT_FIELD:
1329 // add nothing: curl cst = 0
1330 break;
1331 case QUAD_POINT_FIELD:
1332 FEL_ERROR("ElementVector::curl_f_phi_i: Operator 'stressX_dot_phi_i' is not defined for quad_point_field");
1333 break;
1334 case DOF_FIELD:
1335 UBlasVectorRange vec0 = vecBlock(iblock+0);
1336 UBlasVectorRange vec1 = vecBlock(iblock+1);
1337 UBlasVectorRange vec2 = vecBlock(iblock+2);
1338 for(int ig=0; ig<feStress.numQuadraturePoint(); ig++) {
1339 tmp0 = 0.0;
1340 tmp1 = 0.0;
1341 tmp2 = 0.0;
1342 for (int jdof=0; jdof<feVel.numDof(); jdof++) {
1343 tmp0 += -elfield_pressure.val(0,jdof) * fePres.phi[ig](jdof) + 2*viscosity*feVel.dPhi[ig](0,jdof)*elfield_velocity.val(0,jdof);
1344 tmp1 += feVel.dPhi[ig](1,jdof)*elfield_velocity.val(0,jdof) + feVel.dPhi[ig](0,jdof)*elfield_velocity.val(1,jdof);
1345 tmp2 += feVel.dPhi[ig](2,jdof)*elfield_velocity.val(0,jdof) + feVel.dPhi[ig](0,jdof)*elfield_velocity.val(2,jdof);
1346 }
1347 tmp0 *= feStress.weightMeas(ig);
1348 tmp1 *= viscosity * feStress.weightMeas(ig);
1349 tmp2 *= viscosity * feStress.weightMeas(ig);
1350 for(int idof=0; idof<feStress.numDof(); idof++) {
1351 vec0(idof) += tmp0 * feStress.phi[ig](idof);
1352 vec1(idof) += tmp1 * feStress.phi[ig](idof);
1353 vec2(idof) += tmp2 * feStress.phi[ig](idof);
1354 }
1355 }
1356 break;
1357 }
1358 }
1359
1360 /***********************************************************************************/
1361 /***********************************************************************************/
1362
1363 void ElementVector::stressY_dot_phi_i(const double viscosity, const CurrentFiniteElement& fePres, const CurrentFiniteElement& feStress,const CurrentFiniteElement& feVel,const ElementField& elfield_pressure,const ElementField& elfield_velocity,const int iblock)
1364 {
1365 FEL_CHECK(feStress.numQuadraturePoint() == feVel.numQuadraturePoint() && fePres.numQuadraturePoint() == feVel.numQuadraturePoint(), "ElementVector::stressY_dot_phi_i: The quadrature rules must be the same for all the elements");
1366 FEL_CHECK(feStress.numCoor() == 3, "ElementVector::stressY_dot_phi_i: not yet implemented in 2D");
1367 double tmp0,tmp1,tmp2;
1368 switch(elfield_velocity.type()) {
1369 case CONSTANT_FIELD:
1370 // add nothing: curl cst = 0
1371 break;
1372 case QUAD_POINT_FIELD:
1373 FEL_ERROR("ElementVector::stressY_dot_phi_i: Operator 'stressY_dot_phi_i' is not defined for quad_point_field: how to compute curl f ??");
1374 break;
1375 case DOF_FIELD:
1376 UBlasVectorRange vec0 = vecBlock(iblock+0);
1377 UBlasVectorRange vec1 = vecBlock(iblock+1);
1378 UBlasVectorRange vec2 = vecBlock(iblock+2);
1379 for(int ig=0; ig<feStress.numQuadraturePoint(); ig++) {
1380 tmp0 = 0.0;
1381 tmp1 = 0.0;
1382 tmp2 = 0.0;
1383 for (int jdof=0; jdof<feVel.numDof(); jdof++) {
1384 tmp0 += feVel.dPhi[ig](1,jdof)*elfield_velocity.val(0,jdof) + feVel.dPhi[ig](0,jdof)*elfield_velocity.val(1,jdof);
1385 tmp1 += -elfield_pressure.val(0,jdof) * fePres.phi[ig](jdof) + 2 * viscosity * feVel.dPhi[ig](1,jdof)*elfield_velocity.val(1,jdof);
1386 tmp2 += feVel.dPhi[ig](2,jdof)*elfield_velocity.val(1,jdof) + feVel.dPhi[ig](1,jdof)*elfield_velocity.val(2,jdof);
1387 }
1388 tmp0 *= viscosity * feStress.weightMeas(ig);
1389 tmp1 *= feStress.weightMeas(ig);
1390 tmp2 *= viscosity * feStress.weightMeas(ig);
1391 for(int idof=0; idof<feStress.numDof(); idof++) {
1392 vec0(idof) += tmp0 * feStress.phi[ig](idof);
1393 vec1(idof) += tmp1 * feStress.phi[ig](idof);
1394 vec2(idof) += tmp2 * feStress.phi[ig](idof);
1395 }
1396 }
1397 break;
1398 }
1399 }
1400
1401 /***********************************************************************************/
1402 /***********************************************************************************/
1403
1404 void ElementVector::stressZ_dot_phi_i(const double viscosity, const CurrentFiniteElement& fePres, const CurrentFiniteElement& feStress,const CurrentFiniteElement& feVel,const ElementField& elfield_pressure,const ElementField& elfield_velocity,const int iblock)
1405 {
1406 FEL_CHECK(feStress.numQuadraturePoint() == feVel.numQuadraturePoint(), "ElementVector::stressZ_dot_phi_i: The quadrature rules must be the same for all the elements");
1407 FEL_CHECK(feStress.numCoor() == 3, "ElementVector::stressZ_dot_phi_i: not yet implemented in 2D");
1408 double tmp0,tmp1,tmp2;
1409 switch(elfield_velocity.type()) {
1410 case CONSTANT_FIELD:
1411 // add nothing: curl cst = 0
1412 break;
1413 case QUAD_POINT_FIELD:
1414 FEL_ERROR("ElementVector::stressZ_dot_phi_i: Operator 'stressZ_dot_phi_i' is not defined for quad_point_field: how to compute curl f ??");
1415 break;
1416 case DOF_FIELD:
1417 UBlasVectorRange vec0 = vecBlock(iblock+0);
1418 UBlasVectorRange vec1 = vecBlock(iblock+1);
1419 UBlasVectorRange vec2 = vecBlock(iblock+2);
1420 for(int ig=0; ig<feStress.numQuadraturePoint(); ig++) {
1421 tmp0 = 0.0;
1422 tmp1 = 0.0;
1423 tmp2 = 0.0;
1424 for (int jdof=0; jdof<feVel.numDof(); jdof++) {
1425 tmp0 += feVel.dPhi[ig](2,jdof)*elfield_velocity.val(0,jdof) + feVel.dPhi[ig](0,jdof)*elfield_velocity.val(2,jdof);
1426 tmp1 += feVel.dPhi[ig](2,jdof)*elfield_velocity.val(1,jdof) + feVel.dPhi[ig](1,jdof)*elfield_velocity.val(2,jdof);
1427 tmp2 += -elfield_pressure.val(0,jdof) * fePres.phi[ig](jdof)+ 2 * viscosity * feVel.dPhi[ig](2,jdof)*elfield_velocity.val(2,jdof);
1428 }
1429 tmp0 *= viscosity * feStress.weightMeas(ig);
1430 tmp1 *= viscosity * feStress.weightMeas(ig);
1431 tmp2 *= feStress.weightMeas(ig);
1432 for(int idof=0; idof<feStress.numDof(); idof++) {
1433 vec0(idof) += tmp0 * feStress.phi[ig](idof);
1434 vec1(idof) += tmp1 * feStress.phi[ig](idof);
1435 vec2(idof) += tmp2 * feStress.phi[ig](idof);
1436 }
1437 }
1438 break;
1439 }
1440 }
1441
1442 /***********************************************************************************/
1443 /***********************************************************************************/
1444
1445 void ElementVector::grad_f_grad_phi_i(const double coef, const CurrentFiniteElement& fe,const ElementField& elfield,const int iblock)
1446 {
1447 double tmp;
1448 UBlasVectorRange vec = vecBlock(iblock);
1449 switch(elfield.type()) {
1450 case CONSTANT_FIELD:
1451 // add nothing: grad cst = 0
1452 break;
1453 case QUAD_POINT_FIELD:
1454 FEL_ERROR("ElementVector::grad_f_grad_phi_i: Operator 'grad_f_grad_phi_i' is not defined for quad_point_field: how to compute grad f ??");
1455 break;
1456 case DOF_FIELD:
1457 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
1458 for (int icomp=0; icomp<fe.numCoor(); icomp++) {
1459 tmp = 0.0;
1460 for (int jdof=0; jdof<fe.numDof(); jdof++)
1461 tmp += fe.dPhi[ig](icomp,jdof)*elfield.val(0,jdof);
1462 tmp *= coef * fe.weightMeas(ig);
1463 for(int idof=0; idof<fe.numDof(); idof++)
1464 vec(idof) += tmp * fe.dPhi[ig](icomp,idof);
1465 }
1466 }
1467 break;
1468 }
1469 }
1470
1471 /***********************************************************************************/
1472 /***********************************************************************************/
1473
1474 void ElementVector::grad_f_grad_phi_i(const double coef,const CurvilinearFiniteElement& fe, const ElementField& elfield, const std::size_t iblock,const std::size_t num)
1475 {
1476 FEL_ASSERT(elfield.type() == DOF_FIELD);
1477
1478 UBlasMatrix tmpBlock(fe.numDof(),fe.numDof(),0);
1479 UBlasMatrix tmpAdPhi(fe.contravariantMetric[0].size1(), fe.dPhiRef(0).size2());
1480 for(int ig=0, numQuadPoint = fe.numQuadraturePoint(); ig < numQuadPoint; ig++) {
1481 tmpAdPhi = prod(fe.contravariantMetric[ig],fe.dPhiRef(ig));
1482 tmpBlock += coef*fe.weightMeas(ig)*prod(trans(fe.dPhiRef(ig)),tmpAdPhi);
1483 }
1484
1485 UBlasVector ff = elfield.valAsVec();
1486
1487 for(std::size_t icoor=0; icoor < num; icoor++) {
1488 UBlasVectorRange vec = vecBlock(iblock+icoor);
1489 UBlasVectorRange ficoor = UBlasVectorRange(ff,UBlasRange( m_firstRow[icoor], m_firstRow[icoor]+m_numRow[icoor]));
1490 vec += prod(tmpBlock,ficoor);
1491 }
1492 }
1493
1494 /***********************************************************************************/
1495 /***********************************************************************************/
1496
1497 void ElementVector::f_grad_phi_i(const double coef, const CurrentFiniteElement& fe,const ElementField& elfield,const int iblock)
1498 {
1499 double tmp;
1500 UBlasVectorRange vec = vecBlock(iblock);
1501 switch(elfield.type()) {
1502 case CONSTANT_FIELD:
1503 // add nothing: grad cst = 0
1504 break;
1505 case QUAD_POINT_FIELD:
1506 FEL_ERROR("ElementVector::grad_f_grad_phi_i: Operator 'grad_f_grad_phi_i' is not defined for quad_point_field: how to compute grad f ??");
1507 break;
1508 case DOF_FIELD:
1509 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
1510 for (int icomp=0; icomp<fe.numCoor(); icomp++) {
1511 tmp = 0.0;
1512 for (int jdof=0; jdof<fe.numDof(); jdof++)
1513 tmp += fe.phi[ig](jdof)*elfield.val(icomp,jdof);
1514 tmp *= coef * fe.weightMeas(ig);
1515 for(int idof=0; idof<fe.numDof(); idof++)
1516 vec(idof) += tmp * fe.dPhi[ig](icomp,idof);
1517 }
1518 }
1519 break;
1520 }
1521 }
1522
1523 /***********************************************************************************/
1524 /***********************************************************************************/
1525
1526 1315282 void ElementVector::div_f_phi_i(const double coef, const CurrentFiniteElement& fe1,const CurrentFiniteElement& fe2,const ElementField& elfield1,const int iblock)
1527 {
1528
1/6
✗ Branch 2 not taken.
✓ Branch 3 taken 1315282 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1315282 FEL_CHECK(fe1.numQuadraturePoint() == fe2.numQuadraturePoint(),"ElementVector::div_f_phi_i: The quadrature rules must be the same for the two elements");
1529 double tmp;
1530
1/2
✓ Branch 1 taken 1315282 times.
✗ Branch 2 not taken.
1315282 UBlasVectorRange vec = vecBlock(iblock);
1531
1/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1315282 times.
✗ Branch 4 not taken.
1315282 switch(elfield1.type()) {
1532 case CONSTANT_FIELD:
1533 // add nothing: div cst = 0
1534 break;
1535 case QUAD_POINT_FIELD:
1536 FEL_ERROR("ElementVector::div_f_phi_i: Operator 'div_f_phi_i' is not defined for quad_point_field: how to compute div f ??");
1537 break;
1538 1315282 case DOF_FIELD:
1539
2/2
✓ Branch 1 taken 5266452 times.
✓ Branch 2 taken 1315282 times.
6581734 for(int ig=0; ig<fe2.numQuadraturePoint(); ig++) {
1540 5266452 tmp = 0.0;
1541
2/2
✓ Branch 1 taken 15783384 times.
✓ Branch 2 taken 5266452 times.
21049836 for (int icomp=0; icomp<fe1.numCoor(); icomp++) {
1542
2/2
✓ Branch 1 taken 63101592 times.
✓ Branch 2 taken 15783384 times.
78884976 for (int jdof=0; jdof<fe1.numDof(); jdof++) {
1543
2/4
✓ Branch 2 taken 63101592 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 63101592 times.
✗ Branch 6 not taken.
63101592 tmp += fe1.dPhi[ig](icomp,jdof) * elfield1.val(icomp,jdof);
1544 }
1545 }
1546
1/2
✓ Branch 1 taken 5266452 times.
✗ Branch 2 not taken.
5266452 tmp *= coef * fe2.weightMeas(ig);
1547
2/2
✓ Branch 1 taken 21049836 times.
✓ Branch 2 taken 5266452 times.
26316288 for(int idof=0; idof<fe2.numDof(); idof++) {
1548
2/4
✓ Branch 2 taken 21049836 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 21049836 times.
✗ Branch 6 not taken.
21049836 vec(idof) += tmp * fe2.phi[ig](idof);
1549 }
1550 }
1551 1315282 break;
1552 }
1553 1315282 }
1554
1555 /***********************************************************************************/
1556 /***********************************************************************************/
1557
1558 void ElementVector::f_div_phi_i(const double coef, const CurrentFiniteElement& fe1,const CurrentFiniteElement& fe2,const ElementField& elfield2,const int iblock)
1559 {
1560 FEL_CHECK(fe1.numQuadraturePoint() == fe2.numQuadraturePoint(),
1561 "ElementVector::f_div_phi_i: The quadrature rules must be the same for the two elements");
1562 double tmp;
1563 switch(elfield2.type()) {
1564 case CONSTANT_FIELD:
1565 FEL_ERROR("ElementVector::f_div_phi_i: Operator 'f_div_phi_i' is not defined yet for constant_field");
1566 break;
1567 case QUAD_POINT_FIELD:
1568 FEL_ERROR("ElementVector::f_div_phi_i: Operator 'f_div_phi_i' is not defined yet for quad_point_field");
1569 break;
1570 case DOF_FIELD:
1571 for (int icomp=0; icomp<fe1.numCoor(); icomp++) {
1572 UBlasVectorRange vec = vecBlock(iblock+icomp);
1573 for(int ig=0; ig<fe2.numQuadraturePoint(); ig++) {
1574 tmp = 0.0;
1575 for (int jdof=0; jdof<fe1.numDof(); jdof++) {
1576 tmp += fe2.phi[ig](jdof)*elfield2.val(0,jdof);
1577 }
1578 tmp *= coef * fe1.weightMeas(ig);
1579 for(int idof=0; idof<fe1.numDof(); idof++) {
1580 vec(idof) += tmp * fe1.dPhi[ig](icomp,idof);
1581 }
1582 }
1583 }
1584 break;
1585 }
1586 }
1587
1588 /***********************************************************************************/
1589 /***********************************************************************************/
1590
1591 void ElementVector::grad_u_dot_grad_LSu_v(const double coef,const ElementField& u,const ElementField& LSu,const std::vector<double>& data,double avHeavU0,double avHeavMinusU0,double insidePar,double outsidePar,const CurvilinearFiniteElement& fe,std::size_t iblock)
1592 {
1593 UBlasVectorRange vec = vecBlock(iblock);
1594 // grad_level_set
1595 UBlasVector vec_grad_phi(2);
1596 //norm of grad_level_set
1597 // double norm_grad_phi = 0.0;
1598 // grad_transmembrane_pot
1599 UBlasVector vec_grad_u(2);
1600 double grad_u_dot_grad_phi = 0.0;
1601 double dirac = 0.0;
1602 const double epsilon = 1.0e-5;
1603
1604 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
1605 vec_grad_phi(0) = 0.0;
1606 vec_grad_phi(1) = 0.0;
1607 vec_grad_u(0) = 0.0;
1608 vec_grad_u(1) = 0.0;
1609 grad_u_dot_grad_phi = 0.0;
1610 for( felInt icoor = 0; icoor<fe.numRefCoor(); icoor++) {
1611 for (int idof=0; idof<fe.numDof(); idof++) {
1612 vec_grad_phi(icoor) += LSu.val(0, idof) * fe.dPhiRef(ig)(icoor, idof);
1613 vec_grad_u(icoor) += u.val(0, idof) * fe.dPhiRef(ig)(icoor, idof);
1614 }
1615 }
1616
1617 grad_u_dot_grad_phi = std::sqrt(vec_grad_phi(0)*vec_grad_phi(0)+vec_grad_phi(1)*vec_grad_phi(1));
1618
1619 for (int idof=0; idof<fe.numDof(); idof++) {
1620 dirac = ( 1./ std::sqrt(3.14151) )* ( epsilon / ( epsilon*epsilon + LSu.val(0, idof)*LSu.val(0, idof) ) );
1621 vec(idof) += coef * fe.weightMeas(ig) * grad_u_dot_grad_phi * dirac *(insidePar*(data[idof]-avHeavU0)*(data[idof]-avHeavU0) + outsidePar*(data[idof]-avHeavMinusU0)*(data[idof]-avHeavMinusU0))* fe.phi[ig](idof);
1622 }
1623 }
1624 }
1625
1626 /***********************************************************************************/
1627 /***********************************************************************************/
1628
1629 void ElementVector::sourceHyp1DCont(std::vector<double>& coef,const CurrentFiniteElement& fe1,const CurrentFiniteElement& fe2,const ElementField& elfield1,const ElementField& elfield2,const int iblock,int iterm)
1630 {
1631 FEL_CHECK(elfield2.type()==DOF_FIELD,"Operator Continuity for 1D Fsi not yet implemented with this type of element fields");
1632 FEL_CHECK(elfield1.type()==DOF_FIELD,"Operator Continuity for 1D Fsi not yet implemented with this type of element fields");
1633 FEL_CHECK(fe1.numQuadraturePoint() == fe2.numQuadraturePoint(),"The quadrature rules must be the same for the two elements");
1634
1635 FEL_ASSERT(coef.size()==4);
1636 const double dt = coef[0];
1637 const double k = coef[1];
1638 const double betaDivrho = coef[2];
1639 //const double sectionAtRest = coef[3];
1640
1641 double tmpA,tmpU,tmpDxA,tmpDxU,tmpDxF1,tmpDxF2;
1642
1643 UBlasVectorRange vec = vecBlock(iblock);
1644
1645 switch (iterm) {
1646
1647 case 0:
1648
1649 break;
1650 case 1: {
1651 for(int ig=0; ig<fe1.numQuadraturePoint(); ig++) {
1652 tmpU=0.0;
1653 tmpA=0.0;
1654 for(int i=0; i<fe1.numDof(); i++) {
1655 tmpA+= elfield1.val(0,i)*fe1.phi[ig](i);
1656 }
1657 for(int j=0; j<fe2.numDof(); j++) {
1658 tmpU+= elfield2.val(0,j)*fe2.phi[ig](j);
1659 }
1660 double Au = tmpA*tmpU;
1661 double tmp = tmpU*0.5*k*dt;
1662
1663 for(int idof=0; idof<fe1.numDof(); idof++) {
1664 vec(idof)+= dt*(Au-tmp)*fe1.dPhi[ig](0,idof)*fe1.weightMeas(ig);
1665 }
1666 }
1667 }
1668 break;
1669
1670 case 2:
1671
1672 break;
1673
1674 case 3: {
1675 for(int ig=0; ig<fe1.numQuadraturePoint(); ig++) {
1676 tmpA=0.0;
1677 tmpU=0.0;
1678 tmpDxA=0.0;
1679 tmpDxU=0.0;
1680 for(int i=0; i<fe1.numDof(); i++) {
1681 tmpA+= elfield1.val(0,i)*fe1.phi[ig](i);
1682 tmpDxA+= elfield1.val(0,i)*fe1.dPhi[ig](0,i);
1683 }
1684
1685 for(int j=0; j<fe2.numDof(); j++) {
1686 tmpU+= elfield2.val(0,j)*fe2.phi[ig](j);
1687 tmpDxU+= elfield2.val(0,j)*fe2.dPhi[ig](0,j);
1688 }
1689
1690 tmpDxF1 = tmpA*tmpDxU + tmpU*tmpDxA;
1691 tmpDxF2 = tmpU*tmpDxU + (0.5*betaDivrho/(std::sqrt(tmpA)))*tmpDxA;
1692
1693 for(int idof=0; idof<fe1.numDof(); idof++) {
1694 vec(idof)+= -0.5*dt*dt*(tmpU*tmpDxF1+tmpA*tmpDxF2)*fe1.dPhi[ig](0,idof)*fe1.weightMeas(ig);
1695 }
1696 }
1697 }
1698 break;
1699 }
1700 }
1701
1702 /***********************************************************************************/
1703 /***********************************************************************************/
1704
1705 void ElementVector::sourceHyp1DMom(std::vector<double>& coef,const CurrentFiniteElement& fe1,const CurrentFiniteElement& fe2,const ElementField& elfield1,const ElementField& elfield2,const int iblock,int iterm)
1706 {
1707 FEL_CHECK(elfield2.type()==DOF_FIELD,"Operator Momentum for 1D Fsi not yet implemented with this type of element fields");
1708 FEL_CHECK(elfield1.type()==DOF_FIELD,"Operator Momentum for 1D Fsi not yet implemented with this type of element fields");
1709 FEL_CHECK(fe1.numQuadraturePoint() == fe2.numQuadraturePoint(),"The quadrature rules must be the same for the two elements");
1710
1711 FEL_ASSERT(coef.size()==4);
1712 const double dt = coef[0];
1713 const double k = coef[1];
1714 const double betaDivrho = coef[2];
1715 const double r_0 = std::sqrt(coef[3]);
1716
1717 double tmpA,tmpU,tmpDxA,tmpDxU,tmpDxF1,tmpDxF2;
1718
1719 UBlasVectorRange vec = vecBlock(iblock);
1720
1721 switch (iterm) {
1722 case 0: {
1723 for(int ig=0; ig<fe1.numQuadraturePoint(); ig++) {
1724 tmpU=0.0;
1725 tmpA=0.0;
1726 for(int i=0; i<fe1.numDof(); i++) {
1727 tmpA+= elfield1.val(0,i)*fe1.phi[ig](i);
1728 }
1729 for(int j=0; j<fe2.numDof(); j++) {
1730 tmpU+= elfield2.val(0,j)*fe2.phi[ig](j);
1731 }
1732 const double UdivA = tmpU/tmpA;
1733 const double UdivA2 = tmpU/(tmpA*tmpA);
1734
1735 for(int idof=0; idof<fe1.numDof(); idof++) {
1736 vec(idof)+= dt*(-k*UdivA+0.5*dt*k*k*UdivA2)*fe2.phi[ig](idof)*fe2.weightMeas(ig);
1737 }
1738 }
1739 }
1740 break;
1741 case 1: {
1742 for(int ig=0; ig<fe1.numQuadraturePoint(); ig++) {
1743 tmpU=0.0;
1744 tmpA=0.0;
1745 for(int i=0; i<fe1.numDof(); i++) {
1746 tmpA+= elfield1.val(0,i)*fe1.phi[ig](i);
1747 }
1748 for(int j=0; j<fe2.numDof(); j++) {
1749 tmpU+= elfield2.val(0,j)*fe2.phi[ig](j);
1750 }
1751 const double tmpP = betaDivrho*(std::sqrt(tmpA)-r_0);
1752 const double U2DivA = (tmpU*tmpU)/tmpA;
1753
1754 for(int idof=0; idof<fe1.numDof(); idof++) {
1755 vec(idof)+= dt*(0.5*tmpU*tmpU+tmpP-0.5*dt*k*U2DivA)*fe2.dPhi[ig](0,idof)*fe2.weightMeas(ig);
1756 }
1757 }
1758 }
1759 break;
1760 case 2: {
1761 for(int ig=0; ig<fe1.numQuadraturePoint(); ig++) {
1762 tmpU=0.0;
1763 tmpA=0.0;
1764 tmpDxA=0.0;
1765 tmpDxU=0.0;
1766 for(int i=0; i<fe1.numDof(); i++) {
1767 tmpA+= elfield1.val(0,i)*fe1.phi[ig](i);
1768 tmpDxA+= elfield1.val(0,i)*fe1.dPhi[ig](0,i);
1769 }
1770
1771 for(int j=0; j<fe2.numDof(); j++) {
1772 tmpU+= elfield2.val(0,j)*fe2.phi[ig](j);
1773 tmpDxU+= elfield2.val(0,j)*fe2.dPhi[ig](0,j);
1774 }
1775
1776 tmpDxF1 = tmpA*tmpDxU + tmpU*tmpDxA;
1777 tmpDxF2 = tmpU*tmpDxU + (0.5*betaDivrho*1.0/(std::sqrt(tmpA)))*tmpDxA;
1778
1779 const double UdivA2 = tmpU/(tmpA*tmpA);
1780
1781
1782 for(int idof=0; idof<fe1.numDof(); idof++) {
1783 vec(idof)+= -0.5*dt*dt*(k*UdivA2*tmpDxF1-(k/tmpA)*tmpDxF2)*fe2.phi[ig](idof)*fe2.weightMeas(ig);
1784 }
1785 }
1786 }
1787 break;
1788 case 3: {
1789 for(int ig=0; ig<fe1.numQuadraturePoint(); ig++) {
1790 tmpU=0.0;
1791 tmpA=0.0;
1792 tmpDxA=0.0;
1793 tmpDxU=0.0;
1794 for(int i=0; i<fe1.numDof(); i++) {
1795 tmpA+= elfield1.val(0,i)*fe1.phi[ig](i);
1796 tmpDxA+= elfield1.val(0,i)*fe1.dPhi[ig](0,i);
1797 }
1798
1799 for(int j=0; j<fe2.numDof(); j++) {
1800 tmpU+= elfield2.val(0,j)*fe2.phi[ig](j);
1801 tmpDxU+= elfield2.val(0,j)*fe2.dPhi[ig](0,j);
1802 }
1803
1804 tmpDxF1 = tmpA*tmpDxU + tmpU*tmpDxA;
1805 tmpDxF2 = tmpU*tmpDxU + (0.5*betaDivrho/(std::sqrt(tmpA)))*tmpDxA;
1806
1807 const double tmpR = std::sqrt(tmpA);
1808
1809 for(int idof=0; idof<fe1.numDof(); idof++) {
1810 vec(idof)+= -0.5*dt*dt*(0.5*(betaDivrho/tmpR)*tmpDxF1 + tmpU*tmpDxF2)*fe2.dPhi[ig](0,idof)*fe2.weightMeas(ig);
1811 }
1812 }
1813 }
1814 break;
1815 }
1816 }
1817
1818 /***********************************************************************************/
1819 /***********************************************************************************/
1820
1821 void ElementVector::abs_u_dot_n_u_dot_phi_i(const double coef,
1822 const ElementField& elfield,
1823 const CurvilinearFiniteElement& febd,
1824 const int iblock, const int numComp) {
1825 double u_n,u_bd;
1826 switch(elfield.type()) {
1827 case DOF_FIELD: // P1
1828 for(int icomp=0; icomp<numComp; icomp++) {
1829 UBlasVectorRange vec = vecBlock(iblock+icomp);
1830 for(int ig=0; ig<febd.numQuadraturePoint(); ig++) {
1831
1832 // compute 1/2[ ||u.n|| - u.n ](ig)
1833 u_n = 0.0;
1834 for(int jdof=0; jdof<febd.numDof(); jdof++) {
1835 for (int jcomp=0; jcomp<numComp; jcomp++) {
1836 u_n += febd.phi[ig](jdof) * elfield.val(jcomp,jdof)
1837 * febd.normal[ig](jcomp);
1838 }
1839 }
1840 // compute u_icomp (ig)
1841 u_bd = 0.0;
1842 for(int jdof=0; jdof<febd.numDof(); jdof++) {
1843 u_bd += febd.phi[ig](jdof) * elfield.val(icomp,jdof);
1844 }
1845
1846
1847 // compute local contribution for component icomp
1848 for(int idof=0; idof<febd.numDof(); idof++) {
1849 vec(idof) += coef * 0.5 * (std::abs(u_n) - u_n) * u_bd *
1850 febd.phi[ig](idof) * febd.weightMeas(ig);
1851 }
1852 }
1853 } // for i comp
1854 break;
1855 case CONSTANT_FIELD:
1856 case QUAD_POINT_FIELD:
1857 FEL_ERROR("Operator 'abs_u_dot_n_u_dot_phi_i' not yet implemented with this type of element fields");
1858 }
1859 }
1860
1861 /***********************************************************************************/
1862 /***********************************************************************************/
1863
1864 void ElementVector::u_grad_u_phi_i(const double coef, const CurrentFiniteElement& fe,const ElementField& elfield,const int iblock,const int numComp)
1865 {
1866 double tmp,u_i2,di2_u_icomp;
1867 switch(elfield.type()) {
1868 case DOF_FIELD:
1869 // loop over components [b]: sum_a u_a d_a u_b phi
1870 for(int icomp=0; icomp<numComp; icomp++) {
1871 UBlasVectorRange vec = vecBlock(iblock+icomp);
1872
1873 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
1874 tmp = 0.0;
1875 for(int i2comp=0; i2comp<numComp; i2comp++) {
1876 di2_u_icomp = 0.0;
1877 u_i2 = 0.0;
1878 // compute d_a u_b
1879 for (int jdof=0; jdof<fe.numDof(); jdof++) {
1880 di2_u_icomp += fe.dPhi[ig](i2comp,jdof)*elfield.val(icomp,jdof);
1881 }
1882 // compute u_a
1883 for(int idof=0; idof<fe.numDof(); idof++) {
1884 u_i2 += fe.phi[ig](idof) * elfield.val(i2comp,idof);
1885 }
1886 // u_a d_a(u_b)
1887 tmp += u_i2*di2_u_icomp;
1888 }
1889 // add to std::vector
1890 for(int idof=0; idof<fe.numDof(); idof++) {
1891 vec(idof) += coef * tmp * fe.phi[ig](idof) * fe.weightMeas(ig);
1892 }
1893
1894 } // ig
1895 } // icomp
1896 break;
1897 case CONSTANT_FIELD:
1898 case QUAD_POINT_FIELD:
1899
1900 FEL_ERROR("Operator 'source' not yet implemented with this type of element fields");
1901 }
1902 }
1903
1904 /***********************************************************************************/
1905 /***********************************************************************************/
1906
1907 void ElementVector::u_grad_u_grad_phi_i(const double coef, const CurrentFiniteElement& fe,const ElementField& elfield,const int iblock,const int numComp)
1908 {
1909 double tmp,u_i2,di2_u_icomp;
1910 UBlasVectorRange vec = vecBlock(iblock);
1911 switch(elfield.type()) {
1912 case DOF_FIELD:
1913 // loop over components [b]: sum_a u_a d_a u_b phi
1914 for(int icomp=0; icomp<numComp; icomp++) {
1915
1916 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
1917 tmp = 0.0;
1918 for(int i2comp=0; i2comp<numComp; i2comp++) {
1919 di2_u_icomp = 0.0;
1920 u_i2 = 0.0;
1921 // compute d_a u_b
1922 for (int jdof=0; jdof<fe.numDof(); jdof++) {
1923 di2_u_icomp += fe.dPhi[ig](i2comp,jdof)*elfield.val(icomp,jdof);
1924 }
1925 // compute u_a
1926 for(int idof=0; idof<fe.numDof(); idof++) {
1927 u_i2 += fe.phi[ig](idof) * elfield.val(i2comp,idof);
1928 }
1929 // u_a d_a(u_b)
1930 tmp += u_i2*di2_u_icomp;
1931 }
1932 // add to std::vector
1933 for(int idof=0; idof<fe.numDof(); idof++) {
1934 vec(idof) += coef * tmp * fe.dPhi[ig](icomp,idof) * fe.weightMeas(ig);
1935 }
1936
1937 } // ig
1938 } // icomp
1939 break;
1940 case CONSTANT_FIELD:
1941 case QUAD_POINT_FIELD:
1942
1943 FEL_ERROR("Operator 'source' not yet implemented with this type of element fields");
1944 }
1945 }
1946
1947 /***********************************************************************************/
1948 /***********************************************************************************/
1949
1950 void ElementVector::f_dot_n_phi_i_dot_n(const double coef,const CurvilinearFiniteElement& fe,const ElementField& elfield,const int iblock)
1951 {
1952 double tmp,f_dot_n;
1953 switch(elfield.type()) {
1954 case DOF_FIELD: {
1955 for(int icomp=0; icomp<fe.numCoor(); icomp++) {
1956 UBlasVectorRange vec = vecBlock(iblock+icomp);
1957 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
1958 f_dot_n = 0.0;
1959 // compute f \cdot n
1960 for(int icoor=0; icoor<fe.numCoor(); icoor++) {
1961 tmp = 0.0;
1962 for(int jdof=0; jdof<fe.numDof(); jdof++) {
1963 tmp += fe.phi[ig](jdof) * elfield.val(icoor,jdof);
1964 }
1965 // sum f_icoor * n_icoor
1966 f_dot_n += tmp * fe.normal[ig](icoor);
1967 }
1968
1969 for( std::size_t idof=0 ; idof < (std::size_t) fe.numDof() ; idof++ ) {
1970 // coef * f_dot_n * ( phi_i \cdot \n )
1971 vec(idof) += coef * f_dot_n * fe.weightMeas(ig) * fe.normal[ig](icomp) * fe.phi[ig](idof);
1972 }
1973 }
1974 }
1975 }
1976 break;
1977 case CONSTANT_FIELD:
1978 case QUAD_POINT_FIELD:
1979 FEL_ERROR("Operator 'f_dot_n_phi_i_dot_n' not yet implemented with this type of element fields");
1980 }
1981 }
1982
1983 /***********************************************************************************/
1984 /***********************************************************************************/
1985
1986 void ElementVector::f_times_n_phi_i_times_n(const double coef,const CurvilinearFiniteElement& fe,const ElementField& elfield,const int iblock)
1987 {
1988 double tmp,aux,inDiagonal;
1989 switch(elfield.type()) {
1990 case DOF_FIELD: {
1991 for(int icomp=0; icomp<fe.numCoor(); icomp++) {
1992 UBlasVectorRange vec = vecBlock(iblock+icomp);
1993 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
1994 aux = 0.0;
1995 for(int icoor=0; icoor<fe.numCoor(); icoor++) {
1996 tmp = 0.0;
1997 inDiagonal = 0.0;
1998 if (icoor==icomp) {
1999 inDiagonal = 1.;
2000 }
2001 for(int jdof=0; jdof<fe.numDof(); jdof++) {
2002 tmp += fe.phi[ig](jdof) * elfield.val(icoor,jdof);
2003 }
2004 aux += tmp * (inDiagonal - fe.normal[ig](icoor) * fe.normal[ig](icomp));
2005 }
2006 for( std::size_t idof=0 ; idof < (std::size_t) fe.numDof() ; idof++ ) {
2007
2008 vec(idof) += coef * aux * fe.weightMeas(ig) * fe.phi[ig](idof);
2009 }
2010 }
2011 }
2012 }
2013 break;
2014 case CONSTANT_FIELD:
2015 case QUAD_POINT_FIELD:
2016 FEL_ERROR("Operator 'f_times_n_phi_i_times_n' not yet implemented with this type of element fields");
2017 }
2018 }
2019
2020 /***********************************************************************************/
2021 /***********************************************************************************/
2022
2023 void ElementVector::grad_f_dot_n_times_n_phi_i_times_n(const double coef,const CurrentFiniteElementWithBd& fewbd,
2024 const ElementField& elfield,
2025 const int iblockBd, const int numblockBd,
2026 const int iblock, const int numComp)
2027 {
2028 FEL_ASSERT(iblockBd>=0 && iblockBd<fewbd.numBdEle() && (numblockBd-iblockBd) <= fewbd.numBdEle() );
2029 FEL_ASSERT( static_cast<int>(m_tmpVecDof.size()) == fewbd.numDof() );
2030
2031 double tmp,aux,inDiagonal;
2032 switch(elfield.type()) {
2033 case CONSTANT_FIELD:
2034 // add nothing: grad cst = 0
2035 break;
2036 case QUAD_POINT_FIELD:
2037 FEL_ERROR("Operator 'grad_f_dot_n_times_n_phi_i_times_n' is not well defined for quad_point_field: how to compute grad f ??");
2038 break;
2039 case DOF_FIELD:
2040 for(int icomp=0; icomp<numComp; icomp++) {
2041 UBlasVectorRange vec = vecBlock(iblock+icomp);
2042 for (int ibd=iblockBd; ibd<iblockBd+numblockBd; ibd++) {
2043 FEL_ASSERT( fewbd.bdEle(ibd).hasNormal() && fewbd.hasFirstDeriv() );
2044 for(int ilocg=0; ilocg<fewbd.numQuadPointBdEle(ibd); ilocg++) {
2045 int ig = ilocg+fewbd.indexQuadPoint(ibd+1);
2046 // face ibd starts at ibd+1 (0 for internal quad points)
2047 //! Vector = [n \cdot \grad \phi]:
2048 m_tmpVecDof = prod(trans(fewbd.bdEle(ibd).normal[ilocg]), fewbd.dPhi[ig]);
2049 tmp = 0.0;
2050 for(int icoor=0; icoor<fewbd.numCoor(); icoor++) {
2051 aux = 0.0;
2052 inDiagonal = 0.0;
2053 if (icoor==icomp) {
2054 inDiagonal = 1.;
2055 }
2056 for(int jdof=0; jdof<fewbd.numDof(); jdof++) {
2057 //! tmp = [n \cdot \grad f] = \sum f_jdof (grad phi_jdof \cdot n)
2058 aux += m_tmpVecDof(jdof) * elfield.val(icoor,jdof);
2059 }
2060 tmp += aux * (inDiagonal - fewbd.bdEle(ibd).normal[ilocg](icoor) * fewbd.bdEle(ibd).normal[ilocg](icomp));
2061 }
2062 tmp *= coef * fewbd.bdEle(ibd).weightMeas(ilocg);
2063 for(int idof=0; idof<fewbd.numDof(); idof++) {
2064 vec(idof) += tmp * fewbd.bdEle(ibd).phi[ilocg](idof);
2065 }
2066 }
2067 }
2068 }
2069 break;
2070 // Default case should appear with a warning at compile time instead of an error in runtime
2071 // (that's truly the point of using enums as switch cases)
2072 // default:
2073 // FEL_ERROR("Operator 'grad_f_dot_n_phi_i' not yet implemented with this type of element fields");
2074 }
2075 }
2076
2077 /***********************************************************************************/
2078 /***********************************************************************************/
2079
2080 void ElementVector::print(int verbose,std::ostream& c)
2081 {
2082 if(verbose) {
2083 for (std::size_t i=0; i<numBlockRow(); i++) {
2084 c << "Block (" << i << "), ";
2085 c << vecBlock( i ) << std::endl;
2086 }
2087 }
2088 }
2089
2090 /***********************************************************************************/
2091 /***********************************************************************************/
2092
2093 1578000 void ElementVector::GradientBasedHyperElasticityVector_grad_phi_i(const double coef,
2094 const CurrentFiniteElement& finite_element,
2095 int quadraturePointIndex,
2096 UBlasVector& rhsPart,
2097 std::size_t iblock)
2098 {
2099 1578000 const std::size_t nC = finite_element.numRefCoor();
2100
1/2
✓ Branch 1 taken 1578000 times.
✗ Branch 2 not taken.
1578000 const double modified_m_weightmeas = finite_element.weightMeas(quadraturePointIndex) * coef;
2101
2102
2/4
✓ Branch 2 taken 1578000 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1578000 times.
✗ Branch 6 not taken.
1578000 const UBlasMatrix trans_dPhi = trans(finite_element.dPhi[quadraturePointIndex]);
2103
2104
2/2
✓ Branch 0 taken 3156000 times.
✓ Branch 1 taken 1578000 times.
4734000 for (std::size_t icoor = 0u; icoor < nC; ++icoor) {
2105
1/2
✓ Branch 1 taken 3156000 times.
✗ Branch 2 not taken.
3156000 UBlasVectorRange vec = vecBlock(iblock + icoor);
2106
2/4
✓ Branch 1 taken 3156000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3156000 times.
✗ Branch 5 not taken.
3156000 UBlasVectorRange Block(rhsPart, UBlasRange(icoor * nC, icoor * nC + nC));
2107
2108
3/6
✓ Branch 1 taken 3156000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3156000 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3156000 times.
✗ Branch 8 not taken.
3156000 vec += modified_m_weightmeas * prod(trans_dPhi, Block);
2109 3156000 }
2110 1578000 }
2111
2112 /***********************************************************************************/
2113 /***********************************************************************************/
2114
2115 1351020 void ElementVector::stab_supgAdvDiffCT(const double dt, const double stab1, const double density, const double visc, const CurrentFiniteElement& feVel, const CurrentFiniteElement& fePres,
2116 const ElementField& vel, const ElementField& pres, const ElementField& rhs)
2117 {
2118
1/6
✗ Branch 2 not taken.
✓ Branch 3 taken 1351020 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1351020 FEL_CHECK(feVel.numQuadraturePoint() == fePres.numQuadraturePoint(),"ElementVector::stab_supgAdvDiffCT: The quadrature rules must be the same for the two elements");
2119
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1351020 times.
1351020 FEL_ASSERT(vel.type() == DOF_FIELD);
2120
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1351020 times.
1351020 FEL_ASSERT(pres.type() == DOF_FIELD);
2121
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1351020 times.
1351020 FEL_ASSERT(rhs.type() == DOF_FIELD);
2122
2123 // Resize if required
2124
4/6
✓ Branch 1 taken 1351020 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1351020 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 244 times.
✓ Branch 7 taken 1350776 times.
1351020 if (m_tmpVec2Coor.size() != m_tmpVecCoor.size())
2125
2/4
✓ Branch 1 taken 244 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 244 times.
✗ Branch 5 not taken.
244 m_tmpVec2Coor.resize(m_tmpVecCoor.size());
2126
2127 double weightJ, norm_u, aux, tau;
2128
1/2
✓ Branch 1 taken 1351020 times.
✗ Branch 2 not taken.
1351020 const double h_elem = feVel.diameter();
2129
1/2
✓ Branch 2 taken 1351020 times.
✗ Branch 3 not taken.
1351020 UBlasVector tmpVecCoor3(feVel.numCoor());
2130
2131
2/2
✓ Branch 1 taken 5404080 times.
✓ Branch 2 taken 1351020 times.
6755100 for(int ig=0; ig<feVel.numQuadraturePoint(); ig++) {
2132
1/2
✓ Branch 1 taken 5404080 times.
✗ Branch 2 not taken.
5404080 weightJ = feVel.weightMeas(ig);
2133
2134 // u at the integration point ig
2135
2/4
✓ Branch 2 taken 5404080 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5404080 times.
✗ Branch 6 not taken.
5404080 m_tmpVecCoor = prod(vel.val, feVel.phi[ig]); // vel
2136
2137 // grad p at the integration point ig
2138
2/2
✓ Branch 1 taken 16212240 times.
✓ Branch 2 taken 5404080 times.
21616320 for(int icomp=0; icomp<feVel.numCoor(); icomp++) { // grad pres
2139
1/2
✓ Branch 1 taken 16212240 times.
✗ Branch 2 not taken.
16212240 m_tmpVec2Coor(icomp) = 0.0;
2140
2/2
✓ Branch 1 taken 64848960 times.
✓ Branch 2 taken 16212240 times.
81061200 for(int idof=0; idof<fePres.numDof(); idof++)
2141
3/6
✓ Branch 2 taken 64848960 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 64848960 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 64848960 times.
✗ Branch 9 not taken.
64848960 m_tmpVec2Coor(icomp) += fePres.dPhi[ig](icomp, idof)*pres.val(0, idof);
2142 }
2143
2144 // rhs at the integration point ig
2145
2/4
✓ Branch 2 taken 5404080 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5404080 times.
✗ Branch 6 not taken.
5404080 tmpVecCoor3 = prod(rhs.val,feVel.phi[ig]); // rhs
2146
2147
1/2
✓ Branch 1 taken 5404080 times.
✗ Branch 2 not taken.
5404080 norm_u = norm_1(m_tmpVecCoor);
2148 5404080 tau = 10.*stab1 / std::sqrt( (4./(dt*dt)) +
2149 5404080 (4.*norm_u*norm_u)/(h_elem*h_elem) +
2150 5404080 (16.*visc*visc)/(density*density*h_elem*h_elem*h_elem*h_elem)
2151 ) / density;
2152
2153 //
2154
2/2
✓ Branch 1 taken 16212240 times.
✓ Branch 2 taken 5404080 times.
21616320 for(int icomp=0; icomp< feVel.numCoor(); icomp++) {
2155
1/2
✓ Branch 1 taken 16212240 times.
✗ Branch 2 not taken.
16212240 UBlasVectorRange vec = vecBlock(icomp);
2156
2157
2/2
✓ Branch 1 taken 64848960 times.
✓ Branch 2 taken 16212240 times.
81061200 for(int idof=0; idof<feVel.numDof(); idof++) {
2158 64848960 aux = 0;
2159
2/2
✓ Branch 1 taken 194546880 times.
✓ Branch 2 taken 64848960 times.
259395840 for(int jcomp=0; jcomp< feVel.numCoor(); jcomp++)
2160
2/4
✓ Branch 1 taken 194546880 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 194546880 times.
✗ Branch 6 not taken.
194546880 aux+=m_tmpVecCoor(jcomp)*feVel.dPhi[ig](jcomp,idof);
2161
2/4
✓ Branch 1 taken 64848960 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 64848960 times.
✗ Branch 5 not taken.
64848960 vec(idof) -= m_tmpVec2Coor(icomp)*aux*tau*weightJ; // - grad p . vel . grad v
2162
2/4
✓ Branch 1 taken 64848960 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 64848960 times.
✗ Branch 5 not taken.
64848960 vec(idof) += tmpVecCoor3(icomp)*aux*tau*weightJ; // rhs . vel . grad v
2163 }//idof
2164 16212240 }//icomp
2165
2166 }//ig
2167
2168 1351020 }
2169
2170 /***********************************************************************************/
2171 /***********************************************************************************/
2172
2173 1312620 void ElementVector::stab_supgProjCT(const double dt,const double stab1,const double density, const double visc, const CurrentFiniteElement& fe,
2174 const ElementField& beta, const ElementField& vel, const ElementField& pres,
2175 const ElementField& rhs)
2176 {
2177
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1312620 times.
1312620 FEL_ASSERT(vel.type() == DOF_FIELD);
2178
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1312620 times.
1312620 FEL_ASSERT(pres.type() == DOF_FIELD);
2179
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1312620 times.
1312620 FEL_ASSERT(rhs.type() == DOF_FIELD);
2180
2181 // Resize if required
2182
4/6
✓ Branch 1 taken 1312620 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1312620 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 240 times.
✓ Branch 7 taken 1312380 times.
1312620 if (m_tmpVec2Coor.size() != m_tmpVecCoor.size())
2183
2/4
✓ Branch 1 taken 240 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 240 times.
✗ Branch 5 not taken.
240 m_tmpVec2Coor.resize(m_tmpVecCoor.size());
2184
2185 double norm_u, di2_u_icomp, tau;
2186
1/2
✓ Branch 1 taken 1312620 times.
✗ Branch 2 not taken.
1312620 const double h_elem = fe.diameter();
2187
2188
1/2
✓ Branch 2 taken 1312620 times.
✗ Branch 3 not taken.
1312620 UBlasVector tmpVecCoor3(fe.numCoor());
2189
1/2
✓ Branch 2 taken 1312620 times.
✗ Branch 3 not taken.
1312620 UBlasVector tmpVecCoor4(fe.numCoor());
2190
2191
1/2
✓ Branch 1 taken 1312620 times.
✗ Branch 2 not taken.
1312620 UBlasVectorRange vec = vecBlock(0);
2192
2/2
✓ Branch 1 taken 5250480 times.
✓ Branch 2 taken 1312620 times.
6563100 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
2193
2194 // u at the ig
2195
2/4
✓ Branch 2 taken 5250480 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5250480 times.
✗ Branch 6 not taken.
5250480 m_tmpVecCoor = prod(beta.val, fe.phi[ig]); // beta
2196
2197 // grad p at the integration point ig
2198
2/2
✓ Branch 1 taken 15751440 times.
✓ Branch 2 taken 5250480 times.
21001920 for(int icomp=0; icomp<fe.numCoor(); icomp++) { // grad pres
2199
1/2
✓ Branch 1 taken 15751440 times.
✗ Branch 2 not taken.
15751440 m_tmpVec2Coor(icomp) = 0.0;
2200
2/2
✓ Branch 1 taken 63005760 times.
✓ Branch 2 taken 15751440 times.
78757200 for(int idof=0; idof<fe.numDof(); idof++)
2201
3/6
✓ Branch 2 taken 63005760 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 63005760 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 63005760 times.
✗ Branch 9 not taken.
63005760 m_tmpVec2Coor(icomp) += fe.dPhi[ig](icomp, idof)*pres.val(0, idof);
2202 }
2203
2204 // rhs at the integration point ig
2205
2/4
✓ Branch 2 taken 5250480 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5250480 times.
✗ Branch 6 not taken.
5250480 tmpVecCoor3 = prod(rhs.val,fe.phi[ig]); // rhs
2206
2207
2/2
✓ Branch 1 taken 15751440 times.
✓ Branch 2 taken 5250480 times.
21001920 for(int icomp=0; icomp<fe.numCoor(); icomp++) {
2208
1/2
✓ Branch 1 taken 15751440 times.
✗ Branch 2 not taken.
15751440 tmpVecCoor4(icomp) = 0.0;
2209
2/2
✓ Branch 1 taken 47254320 times.
✓ Branch 2 taken 15751440 times.
63005760 for(int i2comp=0; i2comp<fe.numCoor(); i2comp++) {
2210 47254320 di2_u_icomp = 0.0;
2211 // compute d_a u_b
2212
2/2
✓ Branch 1 taken 189017280 times.
✓ Branch 2 taken 47254320 times.
236271600 for (int jdof=0; jdof<fe.numDof(); jdof++)
2213
2/4
✓ Branch 2 taken 189017280 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 189017280 times.
✗ Branch 6 not taken.
189017280 di2_u_icomp += fe.dPhi[ig](i2comp,jdof)*vel.val(icomp,jdof);
2214
2215 // u_a d_a(u_b)
2216
2/4
✓ Branch 1 taken 47254320 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 47254320 times.
✗ Branch 5 not taken.
47254320 tmpVecCoor4(icomp) += m_tmpVecCoor(i2comp)*di2_u_icomp;
2217 }
2218 }
2219
2220 // stabilization parameter
2221
1/2
✓ Branch 1 taken 5250480 times.
✗ Branch 2 not taken.
5250480 norm_u = norm_1(m_tmpVecCoor);
2222 5250480 tau = 10.*stab1 / std::sqrt( (4./(dt*dt)) +
2223 5250480 (4.*norm_u*norm_u)/(h_elem*h_elem) +
2224 5250480 (16.*visc*visc)/(density*density*h_elem*h_elem*h_elem*h_elem)
2225 ) / density;
2226
2227
2228
2/2
✓ Branch 1 taken 21001920 times.
✓ Branch 2 taken 5250480 times.
26252400 for(int idof=0; idof<fe.numDof(); idof++)
2229
2/2
✓ Branch 1 taken 63005760 times.
✓ Branch 2 taken 21001920 times.
84007680 for(int icomp=0; icomp<fe.numCoor(); icomp++) {
2230 // - u . grad v
2231
4/8
✓ Branch 1 taken 63005760 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 63005760 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 63005760 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 63005760 times.
✗ Branch 12 not taken.
63005760 vec(idof) -= tau * fe.weightMeas(ig) * tmpVecCoor4(icomp) * fe.dPhi[ig](icomp,idof);
2232 // + f . grad q
2233
4/8
✓ Branch 1 taken 63005760 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 63005760 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 63005760 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 63005760 times.
✗ Branch 12 not taken.
63005760 vec(idof) += tau * fe.weightMeas(ig) * tmpVecCoor3(icomp) * fe.dPhi[ig](icomp,idof);
2234 // - grad p .grad q
2235
4/8
✓ Branch 1 taken 63005760 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 63005760 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 63005760 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 63005760 times.
✗ Branch 12 not taken.
63005760 vec(idof) -= tau * fe.weightMeas(ig) * m_tmpVec2Coor(icomp)* fe.dPhi[ig](icomp,idof);
2236 }
2237
2238 }//ig
2239
2240 1312620 }
2241
2242 /***********************************************************************************/
2243 /***********************************************************************************/
2244
2245 void ElementVector::stab_supgRhsFS(const double dt, const double stabSUPG, const double density, const double viscosity,
2246 const double c0, const double c1, const double c2,
2247 const CurrentFiniteElement& feVel, const CurrentFiniteElement& fePre,
2248 const ElementField& vel, const ElementField& pres, const ElementField& velRHS)
2249 {
2250 // \int_K [stabSUPG * tau * c0 * (vel . \grad) v] . [ c1 velRHS + c2 \grad pres]
2251
2252 FEL_ASSERT(vel.type() == DOF_FIELD);
2253 FEL_ASSERT(pres.type() == DOF_FIELD);
2254 FEL_ASSERT(velRHS.type() == DOF_FIELD);
2255
2256 // Resize if required
2257 if (m_tmpVec2Coor.size() != m_tmpVecCoor.size())
2258 m_tmpVec2Coor.resize(m_tmpVecCoor.size());
2259
2260 double weightJ, norm_u, aux;
2261 const double h_elem = feVel.diameter();
2262 double tau;
2263 UBlasVector tmpVecCoor3(feVel.numCoor());
2264
2265 for(int ig=0; ig<feVel.numQuadraturePoint(); ig++) {
2266 weightJ = feVel.weightMeas(ig);
2267
2268 // Computation of u and grad p in the element in the integration point ig
2269 // vel
2270 m_tmpVecCoor = prod(vel.val, feVel.phi[ig]);
2271
2272 // RHS vel
2273 m_tmpVec2Coor = prod(velRHS.val, feVel.phi[ig]);
2274
2275 // grad pres
2276 for(int icomp=0; icomp<feVel.numCoor(); icomp++) {
2277 tmpVecCoor3(icomp) = 0.0;
2278 for(int idof=0; idof<fePre.numDof(); idof++)
2279 tmpVecCoor3(icomp) += fePre.dPhi[ig](icomp, idof) * pres.val(0, idof);
2280 }
2281
2282 norm_u = norm_1(m_tmpVecCoor);
2283
2284 tau = stabSUPG / std::sqrt( (4./(dt*dt)) +
2285 (4.*norm_u*norm_u)/(h_elem*h_elem) +
2286 (16*viscosity*viscosity)/(density*density*h_elem*h_elem*h_elem*h_elem));
2287
2288 for(int icomp=0; icomp<feVel.numCoor(); icomp++) {
2289 UBlasVectorRange vec = vecBlock(icomp);
2290
2291 for(int idof=0; idof<feVel.numDof(); idof++) {
2292 aux = 0;
2293 for(int jcomp=0; jcomp<feVel.numCoor(); jcomp++) {
2294 aux += m_tmpVecCoor(jcomp) * feVel.dPhi[ig](jcomp, idof);
2295 }
2296 aux *= c0 * tau * weightJ; // tau * C_0 (U . \grad) . v_i
2297
2298 vec(idof) += c1 * aux * m_tmpVec2Coor(icomp);
2299 vec(idof) += c2 * aux * tmpVecCoor3(icomp);
2300 }
2301 }
2302 }
2303 }
2304
2305 /***********************************************************************************/
2306 /***********************************************************************************/
2307
2308 void ElementVector::quadratic(const double coef, const CurrentFiniteElement& fe,const ElementField& elfield, const int iblock,const int numComp)
2309 {
2310 if(numComp>1) {
2311 FEL_ERROR("Not defined for vector fields!")
2312 }
2313
2314 double tmp;
2315 switch(elfield.type()) {
2316 case CONSTANT_FIELD:
2317
2318 break;
2319 case QUAD_POINT_FIELD:
2320
2321 break;
2322
2323 case DOF_FIELD:
2324
2325 for(int icomp=0; icomp<numComp; icomp++) {
2326 UBlasVectorRange vec = vecBlock(iblock+icomp);
2327 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
2328 tmp = 0.0;
2329 for(int idof=0; idof<fe.numDof(); idof++) {
2330
2331 for(int jdof=0; jdof<fe.numDof(); jdof++) {
2332 for(int hdof=0; hdof<fe.numDof(); hdof++) {
2333 tmp += fe.phi[ig](jdof) * elfield.val(icomp,jdof) *fe.phi[ig](hdof) * elfield.val(icomp,hdof);
2334 }
2335 }
2336 vec(idof) += coef * tmp * fe.phi[ig](idof) * fe.weightMeas(ig);
2337 }
2338 }
2339
2340 }
2341 break;
2342 }
2343 }
2344
2345 /***********************************************************************************/
2346 /***********************************************************************************/
2347
2348 void ElementVector::sGrad_phi_i_tensor_sGrad_f(const double coef, const ElementField& f, const ElementField& normalField, const CurvilinearFiniteElement& fe, UBlasMatrix tensor)
2349 {
2350 UBlasVector sGradF(2);
2351 sGradF=Curvatures::elemFieldGradient(f);
2352
2353 // if tensor is the invers of the first fundamental form you get the laplacian operator on the surface
2354 UBlasVector KsGradF(2);
2355 KsGradF(0)=0.0;
2356 KsGradF(1)=0.0;
2357 KsGradF = prod(tensor, sGradF );
2358
2359 for ( int iLocDof(0); iLocDof < fe.numDof(); iLocDof++) {
2360 UBlasVector sGradPhi_i(2);
2361 sGradPhi_i=Curvatures::testFuncGradient(iLocDof);
2362
2363 double val = coef * inner_prod(KsGradF, sGradPhi_i) * fe.measure();
2364 for ( int iCoor(0); iCoor < fe.numCoor(); iCoor++) {
2365 double value = val*normalField.val(iCoor,iLocDof); // here we multiply the result by the normal std::vector in order to use the result in the NSSimplifiedFSI model
2366 UBlasVectorRange rhs = vecBlock(iCoor);
2367 rhs(iLocDof) += value;
2368 }
2369 }
2370 }
2371
2372 /***********************************************************************************/
2373 /***********************************************************************************/
2374
2375 931737 void ElementVector::sGrad_phi_i_tensor_sGrad_f(const double coef, const ElementField& elemCoef, const ElementField& f, const ElementField& normalField, const CurvilinearFiniteElement& fe, UBlasMatrix tensor)
2376 {
2377
1/2
✓ Branch 1 taken 931737 times.
✗ Branch 2 not taken.
931737 UBlasVector tmpVecQuadPoint;
2378
1/3
✓ Branch 1 taken 931737 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
931737 switch(elemCoef.type()) {
2379 931737 case DOF_FIELD:
2380
1/2
✓ Branch 2 taken 931737 times.
✗ Branch 3 not taken.
931737 tmpVecQuadPoint.resize(fe.numQuadraturePoint());
2381
2/2
✓ Branch 1 taken 5590422 times.
✓ Branch 2 taken 931737 times.
6522159 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
2382
3/6
✓ Branch 2 taken 5590422 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 5590422 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 5590422 times.
✗ Branch 9 not taken.
5590422 tmpVecQuadPoint(ig) = prod(elemCoef.val,fe.phi[ig])(0);
2383 }
2384 931737 break;
2385
2386 case CONSTANT_FIELD:
2387 case QUAD_POINT_FIELD:
2388 FEL_ERROR("this case has not been implemented");
2389 break;
2390 }
2391
2392
1/2
✓ Branch 1 taken 931737 times.
✗ Branch 2 not taken.
1863474 UBlasVector sGradF(2);
2393
2/4
✓ Branch 1 taken 931737 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 931737 times.
✗ Branch 5 not taken.
931737 sGradF=Curvatures::elemFieldGradient(f);
2394
2395 // if tensor is the invers of the first fundamental form you get the laplacian operator on the surface
2396
1/2
✓ Branch 1 taken 931737 times.
✗ Branch 2 not taken.
1863474 UBlasVector KsGradF(2);
2397
1/2
✓ Branch 1 taken 931737 times.
✗ Branch 2 not taken.
931737 KsGradF(0)=0.0;
2398
1/2
✓ Branch 1 taken 931737 times.
✗ Branch 2 not taken.
931737 KsGradF(1)=0.0;
2399
2/4
✓ Branch 1 taken 931737 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 931737 times.
✗ Branch 5 not taken.
931737 KsGradF = prod(tensor, sGradF );
2400
2401
2/2
✓ Branch 1 taken 2795211 times.
✓ Branch 2 taken 931737 times.
3726948 for ( int iLocDof(0); iLocDof < fe.numDof(); iLocDof++) {
2402
1/2
✓ Branch 1 taken 2795211 times.
✗ Branch 2 not taken.
2795211 UBlasVector sGradPhi_i(2);
2403
2/4
✓ Branch 1 taken 2795211 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2795211 times.
✗ Branch 5 not taken.
2795211 sGradPhi_i=Curvatures::testFuncGradient(iLocDof);
2404
2405 2795211 double val(0.0);
2406
2/2
✓ Branch 1 taken 16771266 times.
✓ Branch 2 taken 2795211 times.
19566477 for(int ig=0; ig<fe.numQuadraturePoint(); ig++)
2407
3/6
✓ Branch 1 taken 16771266 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16771266 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16771266 times.
✗ Branch 8 not taken.
16771266 val += coef * tmpVecQuadPoint(ig) * inner_prod(KsGradF, sGradPhi_i) * fe.weightMeas(ig); //TODO only P1! we should integrate, but gradient is constant over the element
2408
2/2
✓ Branch 1 taken 8385633 times.
✓ Branch 2 taken 2795211 times.
11180844 for ( int iCoor(0); iCoor < fe.numCoor(); iCoor++) {
2409
1/2
✓ Branch 1 taken 8385633 times.
✗ Branch 2 not taken.
8385633 double value = val*normalField.val(iCoor,iLocDof); // here we multiply the result by the normal std::vector in order to use the result in the NSSimplifiedFSI model
2410
1/2
✓ Branch 1 taken 8385633 times.
✗ Branch 2 not taken.
8385633 UBlasVectorRange rhs = vecBlock(iCoor);
2411
1/2
✓ Branch 1 taken 8385633 times.
✗ Branch 2 not taken.
8385633 rhs(iLocDof) += value;
2412 8385633 }
2413 2795211 }
2414 931737 }
2415
2416 /***********************************************************************************/
2417 /***********************************************************************************/
2418
2419 1 void ElementVector::operator+=(const ElementVector& vec)
2420 {
2421 1 m_vec += vec.vec();
2422 1 }
2423
2424 /***********************************************************************************/
2425 /***********************************************************************************/
2426
2427 1 void ElementVector::operator-=(const ElementVector& vec)
2428 {
2429 1 m_vec -= vec.vec();
2430 1 }
2431
2432 /***********************************************************************************/
2433 /***********************************************************************************/
2434
2435 1 void ElementVector::operator*=(const double factor)
2436 {
2437 1 m_vec *= factor;
2438 1 }
2439
2440 /***********************************************************************************/
2441 /***********************************************************************************/
2442
2443 3717260 void ElementVector::stab_supg(const double dt, const double stab1, const double density, const double visc,
2444 const CurrentFiniteElement& fe,const ElementField& vel,const ElementField& rhs,
2445 double& Re_elem,double& tau, const int type)
2446 {
2447 /*
2448 Typical value for stab1 = 0.1
2449 This stabilization does not include the 1/dt term (not strongly consistant with the time discrete scheme, may
2450 be viewed as a space-time, P0 in time)
2451 If type = 1: stabilization parameter depends on dt (Tezduyar)
2452 If type = 2: stabilization parameter independent of dt (Franca-Frey CMAME 1992)
2453 */
2454
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3717260 times.
3717260 FEL_ASSERT(vel.type() == DOF_FIELD);
2455
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3717260 times.
3717260 FEL_ASSERT(rhs.type() == DOF_FIELD);
2456
2457 // Resize if required
2458
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 3717260 times.
3717260 if (m_tmpVec2Coor.size() != m_tmpVecCoor.size())
2459 m_tmpVec2Coor.resize(m_tmpVecCoor.size());
2460
2461 double weightJ,norm_u,s,adveps;
2462 3717260 const double h_elem = fe.diameter();
2463 int i0,i0_pres;
2464
2/2
✓ Branch 1 taken 14953300 times.
✓ Branch 2 taken 3717260 times.
18670560 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
2465 14953300 weightJ = fe.weightMeas(ig);
2466 // Computation of u and f in the element in the integration point ig
2467
1/2
✓ Branch 3 taken 14953300 times.
✗ Branch 4 not taken.
14953300 m_tmpVecCoor = prod(vel.val,fe.phi[ig]); // vel
2468 14953300 norm_u = norm_1(m_tmpVecCoor);
2469
1/2
✓ Branch 3 taken 14953300 times.
✗ Branch 4 not taken.
14953300 m_tmpVec2Coor = prod(rhs.val,fe.phi[ig]); // rhs
2470 14953300 Re_elem = density*stab1*norm_u*h_elem/(4*visc);
2471
2/2
✓ Branch 0 taken 14717926 times.
✓ Branch 1 taken 235374 times.
14953300 if(Re_elem<1.0) {
2472 14717926 tau = stab1*density*h_elem*h_elem/(8*visc);
2473 } else {
2474 235374 tau = h_elem/(2.*norm_u);
2475 }
2476
2/2
✓ Branch 0 taken 4201300 times.
✓ Branch 1 taken 10752000 times.
14953300 if(type==1) {
2477 4201300 tau = 10.*stab1 / std::sqrt( (4./(dt*dt)) +
2478 4201300 (4.*norm_u*norm_u)/(h_elem*h_elem) +
2479 4201300 (16.*visc*visc)/(density*density*h_elem*h_elem*h_elem*h_elem)
2480 4201300 ) / density;
2481 // coef 10 is to have a typical value of 0.1 as for type 2
2482 }
2483
1/2
✓ Branch 0 taken 10752000 times.
✗ Branch 1 not taken.
10752000 else if (type==2) {
2484 // FreeFem
2485 10752000 tau = stab1*h_elem*h_elem/visc;
2486 }
2487 else if (type==3) {
2488 tau = 10.*stab1 / std::sqrt( (16.*visc*visc)/(h_elem*h_elem*h_elem*h_elem) );
2489 }
2490
2491 14953300 int ncoor = fe.numCoor();
2492 14953300 i0_pres = m_firstRow[ncoor];
2493
2/2
✓ Branch 1 taken 59344420 times.
✓ Branch 2 taken 14953300 times.
74297720 for(int idof=0; idof<fe.numDof(); idof++) {
2494 59344420 adveps=0.0;
2495
2/2
✓ Branch 0 taken 176498920 times.
✓ Branch 1 taken 59344420 times.
235843340 for(int kcoor=0; kcoor<ncoor; kcoor++) {
2496 176498920 adveps += m_tmpVecCoor[kcoor]* fe.dPhi[ig](kcoor,idof);
2497 }
2498 59344420 adveps *= density*tau*weightJ;// rho (u.\gradv_i)
2499 59344420 s=0.0;
2500
2/2
✓ Branch 0 taken 176498920 times.
✓ Branch 1 taken 59344420 times.
235843340 for(int icoor=0; icoor<ncoor; icoor++) {
2501 176498920 i0 = m_firstRow[icoor];
2502 176498920 m_vec(i0+idof) += m_tmpVec2Coor[icoor]*adveps;
2503 176498920 s += fe.dPhi[ig](icoor,idof)*m_tmpVec2Coor(icoor); // same fe for velocity and pressure
2504 }
2505 59344420 m_vec(i0_pres+idof) -= tau*s*weightJ;
2506
2507 }// idof
2508 }// ig
2509 3717260 }
2510
2511 /***********************************************************************************/
2512 /***********************************************************************************/
2513
2514 void ElementVector::f_scalar_phi_i(const double coef,const CurrentFiniteElement& fe, const ElementField& elfield,const int iblock)
2515 {
2516 double tmp;
2517 for(int icomp=0; icomp<fe.numCoor(); icomp++) {
2518 UBlasVectorRange vec = vecBlock(iblock+icomp);
2519 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
2520 tmp = coef*fe.weightMeas(ig);
2521 for(int idof=0; idof<fe.numDof(); idof++) {
2522 vec(idof) += tmp * elfield.val(icomp,idof);
2523 }
2524 }
2525 }
2526 }
2527
2528 /***********************************************************************************/
2529 /***********************************************************************************/
2530
2531 void ElementVector::div_u_div_phi_i(const double coef,const CurrentFiniteElement& fe, const ElementField& elfield, const int iblock)
2532 {
2533 //rem : elfield is a dof field
2534 for(int kcomp=0; kcomp<fe.numCoor(); kcomp++){
2535 UBlasVectorRange vec = vecBlock(iblock+kcomp);
2536 for(int idof=0; idof<fe.numDof(); idof++) {
2537 double tmpi,tmpj;
2538 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
2539 tmpi = 0.0;
2540 tmpj = 0.0;
2541 for(int jdof=0; jdof<fe.numDof(); jdof++){
2542 for (int jcomp=0; jcomp<fe.numCoor(); jcomp++) {
2543 tmpi += fe.dPhi[ig](kcomp,idof);
2544 tmpj += fe.dPhi[ig](jcomp,jdof)*elfield.val(jcomp,jdof);
2545 }
2546 }
2547 vec(idof) += coef*tmpi*tmpj*fe.weightMeas(ig);
2548 }
2549 }
2550 }
2551 }
2552
2553 /***********************************************************************************/
2554 /***********************************************************************************/
2555
2556 193437 void ElementVector::transpirationSurfStabRHS( const double coef, const ElementField& elemCoef, const ElementField& normalField, const ElementField& force, const CurvilinearFiniteElement& fe, UBlasMatrix tensor)
2557 {
2558 // Tensor is supposed to be the inverse matric tensor
2559 // TODO compute directly it from fe!
2560
1/2
✓ Branch 2 taken 193437 times.
✗ Branch 3 not taken.
193437 UBlasVector tmpVecQuadPoint( fe.numQuadraturePoint() );
2561
1/3
✓ Branch 1 taken 193437 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
193437 switch(elemCoef.type()) {
2562 193437 case DOF_FIELD:
2563
2/2
✓ Branch 1 taken 1160622 times.
✓ Branch 2 taken 193437 times.
1354059 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
2564
2/4
✓ Branch 2 taken 1160622 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1160622 times.
✗ Branch 6 not taken.
1160622 m_tmpVecCoor = prod(elemCoef.val,fe.phi[ig]);
2565
2/4
✓ Branch 1 taken 1160622 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1160622 times.
✗ Branch 5 not taken.
1160622 tmpVecQuadPoint(ig) = m_tmpVecCoor(0)*coef;
2566 }
2567 193437 break;
2568 case CONSTANT_FIELD:
2569 case QUAD_POINT_FIELD:
2570 FEL_ERROR("this case has not been implemented");
2571 break;
2572 }
2573 // Only P1
2574 193437 double coeffQuad = 0.0;
2575
2/2
✓ Branch 1 taken 1160622 times.
✓ Branch 2 taken 193437 times.
1354059 for(int ig=0; ig<fe.numQuadraturePoint(); ig++) {
2576
3/6
✓ Branch 1 taken 1160622 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1160622 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1160622 times.
✗ Branch 8 not taken.
1160622 coeffQuad += tmpVecQuadPoint(ig) * fe.weightMeas(ig) * fe.diameter() ;
2577 }
2578
2579
2/2
✓ Branch 1 taken 580311 times.
✓ Branch 2 taken 193437 times.
773748 for (int forceLocDof = 0; forceLocDof < fe.numDof(); forceLocDof++) {
2580
2/2
✓ Branch 1 taken 1740933 times.
✓ Branch 2 taken 580311 times.
2321244 for (int testLocDof = 0; testLocDof < fe.numDof(); testLocDof++) {
2581
2582 // computation of (\nabla_c\phi_test)^T A^-1 \nabla_c\phi_sol
2583
1/2
✓ Branch 1 taken 1740933 times.
✗ Branch 2 not taken.
1740933 UBlasVector gradForce(2);
2584
1/2
✓ Branch 1 taken 1740933 times.
✗ Branch 2 not taken.
1740933 UBlasVector gradTest(2);
2585
1/2
✓ Branch 1 taken 1740933 times.
✗ Branch 2 not taken.
1740933 UBlasVector KgradForce(2);
2586
1/2
✓ Branch 1 taken 1740933 times.
✗ Branch 2 not taken.
1740933 KgradForce(0)=0.0;
2587
1/2
✓ Branch 1 taken 1740933 times.
✗ Branch 2 not taken.
1740933 KgradForce(1)=0.0;
2588
2/4
✓ Branch 1 taken 1740933 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1740933 times.
✗ Branch 5 not taken.
1740933 gradForce = Curvatures::testFuncGradient(forceLocDof);
2589
2/4
✓ Branch 1 taken 1740933 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1740933 times.
✗ Branch 5 not taken.
1740933 gradTest = Curvatures::testFuncGradient(testLocDof);
2590
2/4
✓ Branch 1 taken 1740933 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1740933 times.
✗ Branch 5 not taken.
1740933 KgradForce = prod(tensor, gradForce );
2591
2592
1/2
✓ Branch 1 taken 1740933 times.
✗ Branch 2 not taken.
1740933 const double lap = inner_prod(KgradForce, gradTest);
2593
2594
2/2
✓ Branch 1 taken 5222799 times.
✓ Branch 2 taken 1740933 times.
6963732 for ( int forceCoor(0); forceCoor < fe.numCoor(); forceCoor++) {
2595
2/2
✓ Branch 1 taken 15668397 times.
✓ Branch 2 taken 5222799 times.
20891196 for ( int testCoor(0); testCoor < fe.numCoor(); testCoor++) {
2596 15668397 double projCoef = 0;
2597
2/2
✓ Branch 1 taken 47005191 times.
✓ Branch 2 taken 15668397 times.
62673588 for ( int ausCoor(0); ausCoor < fe.numCoor(); ++ausCoor ) {
2598 47005191 double deltaTest(0), deltaSol(0);
2599
2/2
✓ Branch 0 taken 15668397 times.
✓ Branch 1 taken 31336794 times.
47005191 if ( forceCoor - ausCoor == 0 )
2600 15668397 deltaSol = 1;
2601
2/2
✓ Branch 0 taken 15668397 times.
✓ Branch 1 taken 31336794 times.
47005191 if ( testCoor - ausCoor == 0 )
2602 15668397 deltaTest = 1;
2603 // Setting normnorm
2604
2/4
✓ Branch 1 taken 47005191 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 47005191 times.
✗ Branch 5 not taken.
47005191 const double normnormSol = normalField.val( forceCoor, forceLocDof)*normalField.val(ausCoor, forceLocDof);
2605
2/4
✓ Branch 1 taken 47005191 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 47005191 times.
✗ Branch 5 not taken.
47005191 const double normnormTest = normalField.val(testCoor,testLocDof)*normalField.val(ausCoor,testLocDof);
2606 47005191 projCoef += ( deltaSol - normnormSol ) * ( deltaTest - normnormTest );
2607 }
2608
2609
1/2
✓ Branch 1 taken 15668397 times.
✗ Branch 2 not taken.
15668397 const double value = projCoef * lap * coeffQuad * force.val(forceCoor,forceLocDof);
2610
2611
1/2
✓ Branch 1 taken 15668397 times.
✗ Branch 2 not taken.
15668397 UBlasVectorRange vec = vecBlock(testCoor);
2612
1/2
✓ Branch 1 taken 15668397 times.
✗ Branch 2 not taken.
15668397 vec(testLocDof) += value;
2613 15668397 }
2614 }
2615 1740933 }
2616 }
2617 193437 }
2618
2619 /***********************************************************************************/
2620 /***********************************************************************************/
2621
2622 void ElementVector::velocityConstraint(const double coef, const ElementField& disp, const CurvilinearFiniteElement& fe, const int iblock)
2623 {
2624 FEL_CHECK(fe.hasMeas() ,"ElementVector::velocityConstraint: requires covariant basis");
2625 FEL_CHECK(disp.type() == DOF_FIELD,"ElementVector::velocityConstraint: wrong displacement field type");
2626
2627 const UBlasMatrix& d = disp.val;
2628
2629 UBlasMatrix cbasis(fe.numRefCoor(),fe.numCoor()); // covariant basis in current configuation
2630 UBlasVector n(fe.numCoor()); // normal std::vector, not unitary
2631 UBlasMatrix datq(fe.numCoor(),fe.numQuadraturePoint()); // displacement at quadrature poins
2632
2633 for (int ic=0; ic <fe.numCoor(); ++ic) {
2634 for(int iq=0; iq<fe.numQuadraturePoint(); ++iq) {
2635 datq(ic,iq) = 0.0;
2636 for(int idof=0; idof<fe.numDof(); ++idof) {
2637 datq(ic,iq) += fe.phi[iq](idof) * d(ic,idof);
2638 }
2639 }
2640 }
2641
2642 UBlasVectorRange vec = vecBlock(iblock);
2643
2644 // Loop on quadrature points
2645 for (int iq=0; iq < fe.numQuadraturePoint(); ++iq) {
2646
2647 // Covariant basis in current configuratgion
2648 for (int ir=0; ir < fe.numRefCoor(); ++ir) {
2649 for (int ic=0; ic <fe.numCoor(); ++ic) {
2650 cbasis(ir,ic) = fe.m_covBasis[iq](ir,ic);
2651 for(int idof=0; idof< fe.numDof(); idof++)
2652 cbasis(ir,ic) += d(ic,idof)*fe.dPhiRef(iq)(ir,idof);
2653 }
2654 }
2655
2656 switch ( fe.numRefCoor() ) { // Warning: must be as in CurvilinearFiniteElement::computeNormal()
2657 case 1:
2658 n(0) = cbasis(0,1);
2659 n(1) = - cbasis(0,0);
2660 break;
2661 case 2:
2662 n(0) = fe.m_sign * ( cbasis(0,1) * cbasis(1,2) - cbasis(0,2)*cbasis(1,1) );
2663 n(1) = fe.m_sign * ( cbasis(0,2) * cbasis(1,0) - cbasis(0,0)*cbasis(1,2) );
2664 n(2) = fe.m_sign * ( cbasis(0,0) * cbasis(1,1) - cbasis(0,1)*cbasis(1,0) );
2665 break;
2666 default:
2667 FEL_ERROR("ElementVector::velocityConstraint: numRefCoor must be 1 or 2");
2668 }
2669
2670 // Update residual in elementary std::vector
2671 for (int ic=0; ic < fe.numCoor(); ++ic)
2672 vec(0) += coef*datq(ic,iq)*n(ic)*fe.quadratureRule().weight(iq);
2673 }
2674
2675 }
2676
2677 /***********************************************************************************/
2678 /***********************************************************************************/
2679
2680 void ElementVector::followerPressure(const double coef, const ElementField& press, const ElementField& disp, const CurvilinearFiniteElement& fe)
2681 {
2682 FEL_CHECK(fe.hasMeas() ,"ElementVector::followerPressure: requires covariant basis");
2683 FEL_CHECK(disp.type() == DOF_FIELD,"ElementVector::followerPressure: wrong displacement field type");
2684 FEL_CHECK(press.numComp() == 1,"ElementVector::followerPressure: wrong pressure field");
2685
2686 const UBlasMatrix& d = disp.val;
2687
2688 UBlasMatrix cbasis(fe.numRefCoor(),fe.numCoor()); // covariant basis in current configuation
2689 UBlasVector n(fe.numCoor()); // normal std::vector, not unitary
2690 UBlasVector patq(fe.numQuadraturePoint()); // pressure at quadrature poins
2691
2692 // Evaluate pressure at quadrature points
2693 switch(press.type()) {
2694 case CONSTANT_FIELD:
2695 for(int iq=0; iq<fe.numQuadraturePoint(); ++iq)
2696 patq(iq) = press.val(0,0);
2697 break;
2698 case QUAD_POINT_FIELD:
2699 for(int iq=0; iq<fe.numQuadraturePoint(); ++iq)
2700 patq(iq) = press.val(0,iq);
2701 break;
2702 case DOF_FIELD:
2703 for(int iq=0; iq<fe.numQuadraturePoint(); ++iq) {
2704 patq(iq) = 0.0;
2705 for(int idof=0; idof<fe.numDof(); ++idof)
2706 patq(iq) += fe.phi[iq](idof) * press.val(0,idof);
2707 }
2708 break;
2709 default:
2710 FEL_ERROR("this pressure element field type has not been implemented");
2711 }
2712
2713 // Loop on quadrature points
2714 for (int iq=0; iq < fe.numQuadraturePoint(); ++iq) {
2715
2716 // covariant basis in current configuratgion
2717 for (int ir=0; ir < fe.numRefCoor(); ++ir) {
2718 for (int ic=0; ic <fe.numCoor(); ++ic) {
2719 cbasis(ir,ic) = fe.m_covBasis[iq](ir,ic);
2720 for(int idof=0; idof< fe.numDof(); idof++)
2721 cbasis(ir,ic) += d(ic,idof)*fe.dPhiRef(iq)(ir,idof);
2722 }
2723 }
2724
2725 switch ( fe.numRefCoor() ) { // Warning: must be as in CurvilinearFiniteElement::computeNormal()
2726 case 1:
2727 n(0) = cbasis(0,1);
2728 n(1) = - cbasis(0,0);
2729 break;
2730 case 2:
2731 n(0) = fe.m_sign * ( cbasis(0,1) * cbasis(1,2) - cbasis(0,2)*cbasis(1,1) );
2732 n(1) = fe.m_sign * ( cbasis(0,2) * cbasis(1,0) - cbasis(0,0)*cbasis(1,2) );
2733 n(2) = fe.m_sign * ( cbasis(0,0) * cbasis(1,1) - cbasis(0,1)*cbasis(1,0) );
2734 break;
2735 default:
2736 FEL_ERROR("ElementVector::followerPressure: numRefCoor must be 1 or 2");
2737 }
2738
2739 // Update residual in elementary std::vector
2740 for (int ic=0; ic < fe.numCoor(); ++ic) {
2741 UBlasVectorRange vec = vecBlock(ic);
2742 for(int idof=0; idof< fe.numDof(); idof++)
2743 vec(idof) += coef*patq(iq)*n(ic)*fe.phi[iq](idof)*fe.quadratureRule().weight(iq);
2744 }
2745 }
2746 }
2747
2748 }
2749