GCC Code Coverage Report


Directory: ./
File: Solver/linearProblemFSINitscheXFEMSolid.hxx
Date: 2024-04-14 07:32:34
Exec Total Coverage
Lines: 301 453 66.4%
Branches: 235 538 43.7%

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: B. Fabreges
13 //
14
15 // System includes
16
17 // External includes
18
19 // Project includes
20 #include "FiniteElement/elementVector.hpp"
21 #include "FiniteElement/elementMatrix.hpp"
22
23 namespace felisce
24 {
25 /*!
26 \brief Matrix and rhs for the elastic string solver.
27 */
28 template<class SolidPrb>
29 2 LinearProblemFSINitscheXFEMSolid<SolidPrb>::LinearProblemFSINitscheXFEMSolid():
30
2/4
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
2 SolidPrb()
31 {
32 2 m_isSeqLastTimeSolAllocated = false;
33 2 m_isSeqLastTimeVelSolAllocated = false;
34 2 m_isSeqStabExplicitFluidExtrapolAllocated = false;
35 2 m_isSeqRNStrucExtrapolAllocated = false;
36
37 2 m_elemFieldTimeSchemeType = NULL;
38 2 m_timeSchemeType = 0;
39
40 2 m_leftSide = 0;
41 2 m_rightSide = 0;
42
43 2 m_assemblingOfSolidProblemTerms = true;
44
45 2 m_useCurrentFluidSolution = false;
46
47
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 m_seqLastTimeSol = PetscVector::null();
48
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 m_seqLastTimeVelSol = PetscVector::null();
49
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 m_seqRNStrucExtrapol = PetscVector::null();
50
51
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 m_seqVecL2Norm = PetscVector::null();
52
53 2 m_isStrucOperatorExplicitlyComputed = false;
54 2 }
55
56 template<class SolidPrb>
57 4 LinearProblemFSINitscheXFEMSolid<SolidPrb>::~LinearProblemFSINitscheXFEMSolid()
58 {
59 4 if(m_isSeqLastTimeSolAllocated)
60 4 m_seqLastTimeSol.destroy();
61
62
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
4 if(m_isSeqLastTimeVelSolAllocated)
63 m_seqLastTimeVelSol.destroy();
64
65
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 if(m_isSeqStabExplicitFluidExtrapolAllocated)
66
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
8 for(std::size_t i=0; i<m_seqStabExplicitFluidExtrapol.size(); ++i)
67 4 m_seqStabExplicitFluidExtrapol[i].destroy();
68
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
4 if(m_isSeqRNStrucExtrapolAllocated)
70 m_seqRNStrucExtrapol.destroy();
71
72
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
4 if(m_seqVecL2Norm.isNotNull())
73 m_seqVecL2Norm.destroy();
74
75
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
12 for(std::size_t iPt=0; iPt < m_subItfPts.size(); ++iPt) {
76
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 delete m_subItfPts[iPt];
77 }
78 }
79
80 template<class SolidPrb>
81 2 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::initialize(std::vector<GeometricMeshRegion::Pointer>& mesh, FelisceTransient::Pointer fstransient, MPI_Comm& comm, bool doUseSNES)
82 {
83 // call the initialize function of the solid problem
84
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 SolidPrb::initialize(mesh, fstransient, comm, doUseSNES);
85
86 // add the fluid variable to the list of physical variables
87 // unknowns are already define in the solid problem
88
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 this->m_listVariable.addVariable(velocity, 2);
89
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 this->m_listVariable.addVariable(pressure, 1);
90 2 this->m_listVariable.print(this->verbosity());
91
92 // send the unknown to the fluid problem (should be already initialize) to add them as variable there
93 2 m_pLinFluid->addSolidVariable();
94
95 // get the id of the displacement variable
96 2 m_iDisplacement = this->m_listVariable.getVariableIdList(displacement);
97
98 // get the number of component of the displacement
99 2 m_numSolidComponent = this->m_listVariable[m_iDisplacement].numComponent();
100
101 // get the time scheme type from the data file
102 2 m_elemFieldTimeSchemeType = FelisceParam::instance().elementFieldDynamicValue("TimeSchemeType");
103
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if(m_elemFieldTimeSchemeType != NULL)
104 2 m_timeSchemeType = (felInt) m_elemFieldTimeSchemeType->constant(Comp1);
105
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (m_timeSchemeType == 2) {
107 // Robin-Neumann scheme
108 // extrapolation order
109 m_betaRN.resize(2);
110 if (FelisceParam::instance().fsiRNscheme == 0){
111 m_betaRN[0] = 0.;
112 m_betaRN[1] = 0.;
113 } else if (FelisceParam::instance().fsiRNscheme == 1){
114 m_betaRN[0] = 1.;
115 m_betaRN[1] = 0.;
116 } else if (FelisceParam::instance().fsiRNscheme == 2){
117 m_betaRN[0] = 2.;
118 m_betaRN[1] = -1.;
119 }
120 }
121
122 // sub element
123 2 m_numVerPerSolidElt = SolidPrb::mesh()->domainDim() + 1;
124
125 // create the std::vector of points for the solid elements
126 2 m_subItfPts.resize(m_numVerPerSolidElt);
127
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
6 for(std::size_t iver=0; iver < m_subItfPts.size(); ++iver) {
128 8 m_subItfPts[iver] = new Point();
129 }
130
131 // compute solid coefficient
132 2 m_massVel = FelisceParam::instance().densitySolid * FelisceParam::instance().thickness / this->m_fstransient->timeStep;
133 2 }
134
135 template<class SolidPrb>
136 80 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::initPerElementTypeBD(GeometricMeshRegion::ElementType eltType, FlagMatrixRHS flagMatrixRHS)
137 {
138 // call the function of the solid problem
139 80 SolidPrb::initPerElementTypeBD(eltType, flagMatrixRHS);
140
141 // m_dispLastSol contains some old displacement
142 80 m_dispLastSol.initialize(DOF_FIELD, *(this->m_feDisp), m_numSolidComponent);
143
144 // source term coming from the coupling with the fluid and Nitsche-XFEM terms
145 80 m_elemNitscheXFEMSolidRHS.initialize(QUAD_POINT_FIELD, *(this->m_feDisp), m_numSolidComponent);
146
147 // allocate elementField for the fluid
148 80 m_fluidDofSol.resize(2);
149 80 m_fluidDofSol[0].initialize(DOF_FIELD, *m_feFluid, m_feFluid->numCoor());
150 80 m_fluidDofSol[1].initialize(DOF_FIELD, *m_fePres, 1);
151
152 // integration points
153 80 m_intPoints.clear();
154 80 m_intPoints.resize(this->m_feDisp->numQuadraturePoint());
155 80 }
156
157 template<class SolidPrb>
158 720 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::computeElementArrayBD(const std::vector<Point*>& elemPoint, const std::vector<felInt>& elemIdPoint, felInt& iel, FlagMatrixRHS flagMatrixRHS)
159 {
160 // Assembling of the solid problem terms
161
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 360 times.
720 if(m_assemblingOfSolidProblemTerms) {
162
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 360 times.
360 if(!this->m_feDisp->hasOriginalQuadPoint())
163 this->m_feDisp->updateBasisAndNormalContra(0, elemPoint);
164
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360 times.
360 if(m_isStrucOperatorExplicitlyComputed) {
166 // update finite element
167 this->m_feDisp->updateMeasNormalContra(0, elemPoint);
168
169 // MATRIX //
170 // time scheme
171 this->m_elementMatBD[0]->phi_i_phi_j(m_massVel, *(this->m_feDisp), 0, 0, m_numSolidComponent);
172
173 // RHS //
174 // time scheme
175 m_dispLastSol.setValue(m_seqRNStrucExtrapol, *(this->m_feDisp), iel, m_iDisplacement, this->m_ao, this->dof());
176 this->m_elementVectorBD[0]->source(m_massVel, *(this->m_feDisp), m_dispLastSol, 0, m_numSolidComponent);
177
178 } else {
179 360 SolidPrb::computeElementArrayBD(elemPoint, elemIdPoint, iel, flagMatrixRHS);
180 }
181 } else {
182 360 assembleNitscheXFEMTerms(elemPoint, elemIdPoint, iel, flagMatrixRHS);
183 }
184 720 }
185
186 template<class SolidPrb>
187 720 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::computeElementArrayBD(const std::vector<Point*>& elemPoint, const std::vector<felInt>& elemIdPoint, const std::vector<Point*>& elemNormal, const std::vector< std::vector<Point*> >& elemTangent, felInt& iel, FlagMatrixRHS flagMatrixRHS)
188 {
189 // Assembling of the solid problem terms
190
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 360 times.
720 if(m_assemblingOfSolidProblemTerms) {
191
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 360 times.
360 if(!this->m_feDisp->hasOriginalQuadPoint())
192 this->m_feDisp->updateBasisAndNormalContra(0, elemPoint);
193
194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360 times.
360 if(m_isStrucOperatorExplicitlyComputed) {
195 // update finite element
196 this->m_feDisp->updateMeasNormalContra(0, elemPoint);
197
198 // MATRIX //
199 // time scheme
200 this->m_elementMatBD[0]->phi_i_phi_j(m_massVel, *(this->m_feDisp), 0, 0, m_numSolidComponent);
201
202 // RHS //
203 // time scheme
204 m_dispLastSol.setValue(m_seqRNStrucExtrapol, *(this->m_feDisp), iel, m_iDisplacement, this->m_ao, this->dof());
205 this->m_elementVectorBD[0]->source(m_massVel, *(this->m_feDisp), m_dispLastSol, 0, m_numSolidComponent);
206 } else {
207 360 SolidPrb::computeElementArrayBD(elemPoint, elemIdPoint, elemNormal, elemTangent, iel, flagMatrixRHS);
208 }
209 } else {
210 360 assembleNitscheXFEMTerms(elemPoint, elemIdPoint, iel, flagMatrixRHS);
211 }
212 720 }
213
214
215
216 template<class SolidPrb>
217 720 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::assembleNitscheXFEMTerms(const std::vector<Point*>& elemPoint, const std::vector<felInt>& elemIdPoint, felInt& iel, FlagMatrixRHS flagMatrixRHS)
218 {
219 (void) elemIdPoint;
220 (void) flagMatrixRHS;
221
222 // Assembling of the terms coming from the coupling with the fluid and the Nitsche-XFEM formulation
223 720 std::vector< std::vector<felInt> > vectorIdSupport;
224
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 720 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
720 if((m_timeSchemeType == 3) || (m_timeSchemeType == 2) || (m_timeSchemeType == 4) )
225
1/2
✓ Branch 2 taken 720 times.
✗ Branch 3 not taken.
720 vectorIdSupport.resize(m_seqStabExplicitFluidExtrapol.size());
226 else
227 vectorIdSupport.resize(1);
228
229 // loop over the sub structure to compute the integrals involving the fluid velocity and pressure
230
1/2
✓ Branch 1 taken 720 times.
✗ Branch 2 not taken.
720 felInt numSubElement = m_duplicateSupportElements->getNumSubItfEltPerItfElt(iel);
231
1/2
✓ Branch 0 taken 720 times.
✗ Branch 1 not taken.
720 if(numSubElement > 0) {
232 felInt subElemId;
233 felInt fluidElemId;
234
1/2
✓ Branch 2 taken 720 times.
✗ Branch 3 not taken.
720 std::vector<double> tmpPt(3);
235
1/2
✓ Branch 2 taken 720 times.
✗ Branch 3 not taken.
720 std::vector<double> itfNormal(3);
236
1/2
✓ Branch 2 taken 720 times.
✗ Branch 3 not taken.
720 std::vector<double> itfNormalInit(3);
237
238 // get the normal and the initial normal to this sub element
239 720 GeometricMeshRegion::ElementType eltTypeStruc = this->mesh()->bagElementTypeDomain()[0];
240
1/2
✓ Branch 4 taken 720 times.
✗ Branch 5 not taken.
720 this->mesh()->listElementNormal(eltTypeStruc, iel).getCoor(itfNormal);
241
1/2
✓ Branch 4 taken 720 times.
✗ Branch 5 not taken.
720 this->mesh()->listElementNormalInit(eltTypeStruc, iel).getCoor(itfNormalInit);
242
243
2/2
✓ Branch 2 taken 2056 times.
✓ Branch 3 taken 720 times.
2776 for(felInt iSubElt=0; iSubElt < numSubElement; ++iSubElt) {
244 // get the id of the sub element
245
1/2
✓ Branch 1 taken 2056 times.
✗ Branch 2 not taken.
2056 subElemId = m_duplicateSupportElements->getSubItfEltIdxItf(iel, iSubElt);
246
247 // fill the std::vector with the points of the sub-element
248
2/2
✓ Branch 0 taken 4112 times.
✓ Branch 1 taken 2056 times.
6168 for(std::size_t iPt=0; iPt < m_numVerPerSolidElt; ++iPt) {
249
1/2
✓ Branch 1 taken 4112 times.
✗ Branch 2 not taken.
4112 m_duplicateSupportElements->getSubItfEltVerCrd(subElemId, iPt, tmpPt);
250 4112 *m_subItfPts[iPt] = Point(tmpPt[0], tmpPt[1], tmpPt[2]);
251 }
252
253 // update measure
254
2/4
✓ Branch 1 taken 2056 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2056 times.
✗ Branch 5 not taken.
2056 this->m_feDisp->updateSubElementMeasNormal(0, elemPoint, m_subItfPts);
255
256
257 // get the coordinate of the fluid element
258
1/2
✓ Branch 1 taken 2056 times.
✗ Branch 2 not taken.
2056 fluidElemId = m_duplicateSupportElements->getMshEltIdxOfSubItfElt(subElemId);
259
260 2056 GeometricMeshRegion::ElementType eltType = m_pLinFluid->mesh()->bagElementTypeDomain()[0];
261 2056 int numPointsPerElt = GeometricMeshRegion::m_numPointsPerElt[eltType];
262
263
1/2
✓ Branch 2 taken 2056 times.
✗ Branch 3 not taken.
2056 std::vector<Point*> fluidElemPts(numPointsPerElt);
264
1/2
✓ Branch 2 taken 2056 times.
✗ Branch 3 not taken.
2056 std::vector<felInt> fluidElemPtsId(numPointsPerElt);
265
266
1/2
✓ Branch 3 taken 2056 times.
✗ Branch 4 not taken.
2056 m_pLinFluid->mesh()->getOneElement(eltType, fluidElemId, fluidElemPtsId, 0);
267
2/2
✓ Branch 0 taken 6168 times.
✓ Branch 1 taken 2056 times.
8224 for (int iPoint = 0; iPoint < numPointsPerElt; ++iPoint)
268 6168 fluidElemPts[iPoint] = &m_pLinFluid->mesh()->listPoints()[fluidElemPtsId[iPoint]];
269
270
271 // update the element for the fluid finite element
272
1/2
✓ Branch 1 taken 2056 times.
✗ Branch 2 not taken.
2056 m_feFluid->updateFirstDeriv(0, fluidElemPts);
273
274 // compute the integration point for this element
275
1/2
✓ Branch 1 taken 2056 times.
✗ Branch 2 not taken.
2056 computeIntegrationPoints(fluidElemPts);
276
277 // get all the support elements for the fluid
278
6/8
✓ Branch 1 taken 2056 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2056 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1028 times.
✓ Branch 6 taken 1028 times.
✓ Branch 7 taken 1028 times.
✓ Branch 8 taken 1028 times.
2056 if(FelisceParam::instance().useProjectionForNitscheXFEM || m_useCurrentFluidSolution)
279
2/2
✓ Branch 1 taken 1028 times.
✓ Branch 2 taken 1028 times.
2056 for(std::size_t i=0; i<vectorIdSupport.size(); ++i)
280
1/2
✓ Branch 3 taken 1028 times.
✗ Branch 4 not taken.
1028 m_pLinFluid->supportDofUnknown(0).getIdElementSupport(fluidElemId, vectorIdSupport[i]);
281 else
282
2/2
✓ Branch 1 taken 2056 times.
✓ Branch 2 taken 1028 times.
3084 for(std::size_t i=0; i<vectorIdSupport.size(); ++i)
283
1/2
✓ Branch 3 taken 2056 times.
✗ Branch 4 not taken.
2056 m_pLinFluid->supportDofUnknownOld(i,0).getIdElementSupport(fluidElemId, vectorIdSupport[i]);
284
285 // compute the elementary matrix and rhs
286
1/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2056 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2056 switch(m_timeSchemeType) {
287 case 0: {
288 // Robin-Neumann schemes (direct implementation) (0th, 1st and 2nd order extrapolated variants)
289 for(std::size_t iSup=m_leftSide; iSup<vectorIdSupport[0].size() - m_rightSide; ++iSup) {
290 // force of the fluid to the structure
291 updateFluidVel(vectorIdSupport[0][iSup], m_pLinFluid->sequentialSolution());
292
293 computeFluidNormalDerivativeJump(2.*iSup - 1., itfNormal, itfNormalInit);
294 this->m_elementVectorBD[0]->source(-1., *(this->m_feDisp), m_elemNitscheXFEMSolidRHS, 0, m_numSolidComponent);
295 }
296 break;
297 }
298
299 case 1: {
300 // Robin - Robin //
301 // Nitsche penalty term (derivative of the displacement)
302 // This integral is here because the penalty parameter depends of the fluid element
303 double penaltyTerm = FelisceParam::instance().viscosity*FelisceParam::instance().NitschePenaltyParam/m_feFluid->diameter();
304 double tau = this->m_fstransient->timeStep;
305 double coef = 2. - m_leftSide - m_rightSide;
306
307 this->m_elementMatBD[0]->phi_i_phi_j(coef*penaltyTerm/tau, *(this->m_feDisp), 0, 0, m_numSolidComponent);
308
309 m_dispLastSol.setValue(m_seqLastTimeSol, *(this->m_feDisp), iel, m_iDisplacement, this->m_ao, this->dof());
310 this->m_elementVectorBD[0]->source(coef*penaltyTerm/tau, *(this->m_feDisp), m_dispLastSol, 0, m_numSolidComponent);
311
312
313 for(std::size_t iSup=m_leftSide; iSup<vectorIdSupport[0].size() - m_rightSide; ++iSup) {
314 // get the velocity and pressure at the dof of the structure
315 // Nitsche penalty term
316 if(FelisceParam::instance().useProjectionForNitscheXFEM)
317 updateFluidVel(vectorIdSupport[0][iSup], m_pLinFluid->sequentialSolution());
318 else
319 updateFluidVel(vectorIdSupport[0][iSup], m_pLinFluid->sequentialSolutionOld(0));
320
321 computeFluidVelOnSubStructure(itfNormalInit);
322 this->m_elementVectorBD[0]->source(penaltyTerm, *(this->m_feDisp), m_elemNitscheXFEMSolidRHS, 0, m_numSolidComponent);
323
324 computeFluidNormalDerivativeJump(2.*iSup - 1., itfNormal, itfNormalInit);
325 this->m_elementVectorBD[0]->source(-1., *(this->m_feDisp), m_elemNitscheXFEMSolidRHS, 0, m_numSolidComponent);
326 }
327 break;
328 }
329
330 case 2: {
331 // Robin-Neumann schemes a la Stenberg (0th, 1st and 2nd order extrapolated variants)
332 double alpha = 0.5;
333 double RNParam = FelisceParam::instance().densitySolid * FelisceParam::instance().thickness / this->m_fstransient->timeStep;
334 double penaltyParam1 = (m_feFluid->diameter()) / (FelisceParam::instance().viscosity * FelisceParam::instance().NitschePenaltyParam + RNParam*m_feFluid->diameter());
335 double penaltyParam2 = (FelisceParam::instance().NitschePenaltyParam *FelisceParam::instance().viscosity ) / (FelisceParam::instance().viscosity *FelisceParam::instance().NitschePenaltyParam + RNParam*m_feFluid->diameter());
336
337 if (m_useCurrentFluidSolution) {
338 m_dispLastSol.setValue(m_seqRNStrucExtrapol, *(this->m_feDisp), iel, m_iDisplacement, this->m_ao, this->dof());
339 this->m_elementVectorBD[0]->source(-1.0 * penaltyParam2 * RNParam , *(this->m_feDisp), m_dispLastSol, 0, m_numSolidComponent);
340
341 // get the velocity and pressure at the dof of the structure
342 // Nitsche penalty term
343 for(std::size_t iSup=m_leftSide; iSup< vectorIdSupport[0].size() - m_rightSide; ++iSup) {
344 updateFluidVel(vectorIdSupport[0][iSup], m_pLinFluid->sequentialSolution());
345
346 computeFluidVelOnSubStructure(itfNormalInit);
347 this->m_elementVectorBD[0]->source(alpha * penaltyParam2 * RNParam, *(this->m_feDisp), m_elemNitscheXFEMSolidRHS, 0, m_numSolidComponent);
348
349 // force of the fluid to the structure
350 computeFluidNormalDerivativeJump(2.*iSup - 1., itfNormal, itfNormalInit);
351 this->m_elementVectorBD[0]->source(-1.0 * penaltyParam1 * RNParam , *(this->m_feDisp), m_elemNitscheXFEMSolidRHS, 0, m_numSolidComponent);
352 }
353 } else {
354 // get the velocity and pressure at the dof of the structure
355 // Nitsche penalty term
356 for(std::size_t i=0; i<m_seqStabExplicitFluidExtrapol.size(); ++i) {
357 for(std::size_t iSup=m_leftSide; iSup<vectorIdSupport[i].size() - m_rightSide; ++iSup) {
358 updateFluidVel(vectorIdSupport[i][iSup], m_seqStabExplicitFluidExtrapol[i], i);
359 computeFluidNormalDerivativeJump(2.*iSup - 1., itfNormal, itfNormalInit);
360 this->m_elementVectorBD[0]->source(-1.0 * penaltyParam2 * m_betaRN[i], *(this->m_feDisp), m_elemNitscheXFEMSolidRHS, 0, m_numSolidComponent);
361 }
362 }
363 }
364
365 break;
366 }
367
368 2056 case 3:{
369 // stabilized explicit //
370 // Nitsche penalty term (derivative of the displacement)
371 // This integral is here because the penalty parameter depends of the fluid element
372
3/6
✓ Branch 1 taken 2056 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2056 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2056 times.
✗ Branch 8 not taken.
2056 double penaltyTerm = FelisceParam::instance().viscosity*FelisceParam::instance().NitschePenaltyParam/m_feFluid->diameter();
373 2056 double tau = this->m_fstransient->timeStep;
374 2056 double coef = 2. - m_leftSide - m_rightSide;
375
376 // Add the penalty terms in the solid if we are using the classic Nitsche's formulation
377
2/4
✓ Branch 1 taken 2056 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2056 times.
✗ Branch 4 not taken.
2056 if(!FelisceParam::instance().usePenaltyFreeNitscheMethod) {
378 // displacement part
379
1/2
✓ Branch 3 taken 2056 times.
✗ Branch 4 not taken.
2056 this->m_elementMatBD[0]->phi_i_phi_j(coef*penaltyTerm/tau, *(this->m_feDisp), 0, 0, m_numSolidComponent); // gamma/(h tau) \int d . w
380
1/2
✓ Branch 2 taken 2056 times.
✗ Branch 3 not taken.
2056 m_dispLastSol.setValue(m_seqLastTimeSol, *(this->m_feDisp), iel, m_iDisplacement, this->m_ao, this->dof());
381
1/2
✓ Branch 3 taken 2056 times.
✗ Branch 4 not taken.
2056 this->m_elementVectorBD[0]->source(coef*penaltyTerm/tau, *(this->m_feDisp), m_dispLastSol, 0, m_numSolidComponent); // gamma/(h tau) \int dold . w
382
383 // get the velocity and pressure at the dof of the structure
384 // Fluid Nitsche penalty term
385
2/2
✓ Branch 1 taken 3084 times.
✓ Branch 2 taken 2056 times.
5140 for(std::size_t i=0; i<m_seqStabExplicitFluidExtrapol.size(); ++i) {
386
2/2
✓ Branch 2 taken 6106 times.
✓ Branch 3 taken 3084 times.
9190 for(std::size_t iSup=m_leftSide; iSup<vectorIdSupport[i].size() - m_rightSide; ++iSup) {
387
1/2
✓ Branch 4 taken 6106 times.
✗ Branch 5 not taken.
6106 updateFluidVel(vectorIdSupport[i][iSup], m_seqStabExplicitFluidExtrapol[i], i);
388
1/2
✓ Branch 1 taken 6106 times.
✗ Branch 2 not taken.
6106 computeFluidVelOnSubStructure(itfNormalInit);
389
1/2
✓ Branch 3 taken 6106 times.
✗ Branch 4 not taken.
6106 this->m_elementVectorBD[0]->source(penaltyTerm, *(this->m_feDisp), m_elemNitscheXFEMSolidRHS, 0, m_numSolidComponent); // gamma/(h ) \int uf^{n-1} . w
390 }
391 }
392 }
393
394 // Nitsche consistency term
395
2/2
✓ Branch 2 taken 4090 times.
✓ Branch 3 taken 2056 times.
6146 for(std::size_t iSup=m_leftSide; iSup<vectorIdSupport[0].size() - m_rightSide; ++iSup) {
396
6/8
✓ Branch 1 taken 4090 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4090 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2056 times.
✓ Branch 6 taken 2034 times.
✓ Branch 7 taken 2056 times.
✓ Branch 8 taken 2034 times.
4090 if(FelisceParam::instance().useProjectionForNitscheXFEM || m_useCurrentFluidSolution)
397
1/2
✓ Branch 4 taken 2056 times.
✗ Branch 5 not taken.
2056 updateFluidVel(vectorIdSupport[0][iSup], m_pLinFluid->sequentialSolution());
398 else
399
1/2
✓ Branch 4 taken 2034 times.
✗ Branch 5 not taken.
2034 updateFluidVel(vectorIdSupport[0][iSup], m_pLinFluid->sequentialSolutionOld(0));
400
401
1/2
✓ Branch 1 taken 4090 times.
✗ Branch 2 not taken.
4090 computeFluidNormalDerivativeJump(2.*iSup - 1., itfNormal, itfNormalInit);
402
1/2
✓ Branch 3 taken 4090 times.
✗ Branch 4 not taken.
4090 this->m_elementVectorBD[0]->source(-1., *(this->m_feDisp), m_elemNitscheXFEMSolidRHS, 0, m_numSolidComponent); // -int sigma(u^{n-1},p^{n-1})n . w
403 }
404 2056 break;
405 }
406
407
408 case 4:{
409 // Robin-Neumann semi-implict (0th, 1st and 2nd order extrapolated variants) //
410 // Nitsche penalty term (derivative of the displacement)
411 // This integral is here because the penalty parameter depends of the fluid element
412 double penaltyTerm = FelisceParam::instance().viscosity*FelisceParam::instance().NitschePenaltyParam/m_feFluid->diameter();
413 double coef = 2. - m_leftSide - m_rightSide;
414
415 if(!m_isStrucOperatorExplicitlyComputed) {
416 m_dispLastSol.setValue(this->sequentialSolution(), *(this->m_feDisp), iel, m_iDisplacement, this->m_ao, this->dof());
417 this->m_elementVectorBD[0]->source(-coef*penaltyTerm, *(this->m_feDisp), m_dispLastSol, 0, m_numSolidComponent);
418 } else {
419 // matrix part
420 this->m_elementMatBD[0]->phi_i_phi_j(coef * penaltyTerm, *(this->m_feDisp), 0, 0, m_numSolidComponent);
421
422 // All the extrapolation parts are added in the rhs later in the model.
423 // There are indeed store in a std::vector during the real solid step and reused here later.
424 }
425
426 // get the velocity and pressure at the dof of the structure
427 // Nitsche penalty term
428 for(std::size_t i=0; i<m_seqStabExplicitFluidExtrapol.size(); ++i) {
429 for(std::size_t iSup=m_leftSide; iSup<vectorIdSupport[i].size() - m_rightSide; ++iSup) {
430 updateFluidVel(vectorIdSupport[i][iSup], m_seqStabExplicitFluidExtrapol[i], i);
431 computeFluidVelOnSubStructure(itfNormalInit);
432 this->m_elementVectorBD[0]->source(penaltyTerm, *(this->m_feDisp), m_elemNitscheXFEMSolidRHS, 0, m_numSolidComponent);
433 }
434 }
435
436 // Nitsche consistency term
437 for(std::size_t iSup=m_leftSide; iSup<vectorIdSupport[0].size() - m_rightSide; ++iSup) {
438 if(FelisceParam::instance().useProjectionForNitscheXFEM || m_useCurrentFluidSolution)
439 updateFluidVel(vectorIdSupport[0][iSup], m_pLinFluid->sequentialSolution());
440 else
441 updateFluidVel(vectorIdSupport[0][iSup], m_pLinFluid->sequentialSolutionOld(0));
442
443 computeFluidNormalDerivativeJump(2.*iSup - 1., itfNormal, itfNormalInit);
444 this->m_elementVectorBD[0]->source(-1., *(this->m_feDisp), m_elemNitscheXFEMSolidRHS, 0, m_numSolidComponent);
445 }
446
447 break;
448 }
449
450 default:{
451 FEL_ERROR("Bad time splitting scheme");
452 break;
453 }
454 }
455 }
456 720 }
457 720 }
458
459 template<class SolidPrb>
460 2 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::setDuplicateSupportObject(DuplicateSupportDof* object)
461 {
462 2 m_duplicateSupportElements = object;
463 2 }
464
465 template<class SolidPrb>
466 2 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::setFluidLinPrb(LinearProblemFSINitscheXFEMFluid* pLinPrb)
467 {
468 2 m_pLinFluid = pLinPrb;
469 2 }
470
471 template<class SolidPrb>
472 2 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::setFluidFiniteElement(CurrentFiniteElement* velFE, CurrentFiniteElement* preFE)
473 {
474 2 m_feFluid = velFE;
475 2 m_fePres = preFE;
476 2 }
477
478
479 template<class SolidPrb>
480 80 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::isAssemblingOfSolidProblemTerms(bool isit)
481 {
482 80 m_assemblingOfSolidProblemTerms = isit;
483 80 }
484
485 template<class SolidPrb>
486 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::isStrucOperatorExplicitlyComputed(bool isit)
487 {
488 m_isStrucOperatorExplicitlyComputed = isit;
489 }
490
491 template<class SolidPrb>
492 40 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::setUserBoundaryCondition()
493 {
494
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 36 times.
40 if(this->m_fstransient->iteration == 1) {
495 // resize the arrays
496
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 m_applyDirichletBC.resize(this->m_listUnknown.size());
497
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 m_idDofBCVertices.resize(this->m_listUnknown.size());
498
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 m_valBC.resize(this->m_listUnknown.size());
499
500 // get the id of the boundary of the structure
501 // we identify the points that are in only one edge. There should only be "boundaries" elements.
502
1/2
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 std::vector<felInt> numEdgePerVertices(this->m_supportDofUnknown[0].numSupportDof(), 0);
503 4 felInt cntDof = 0;
504 4 felInt numComp = 0;
505 4 felInt idof = 0;
506
507
2/2
✓ Branch 3 taken 72 times.
✓ Branch 4 taken 4 times.
76 for(std::size_t ielSup=0; ielSup<this->m_supportDofUnknown[0].iEle().size()-1; ++ielSup) {
508
2/2
✓ Branch 2 taken 144 times.
✓ Branch 3 taken 72 times.
216 for(felInt idSup=0; idSup<this->m_supportDofUnknown[0].getNumSupportDof(ielSup); ++idSup) {
509 144 ++numEdgePerVertices[this->m_supportDofUnknown[0].iSupportDof()[this->m_supportDofUnknown[0].iEle()[ielSup] + idSup]];
510 }
511 }
512
513
2/2
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 4 times.
84 for(std::size_t ivert=0; ivert<numEdgePerVertices.size(); ++ivert) {
514
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 64 times.
80 if(numEdgePerVertices[ivert] == 1) {
515 // we got a point on the border of the structure
516 // add it only if it's not a front point (not attached, to change if one wants to modeled a rigid immersed wall)
517
3/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 8 times.
16 if(!m_duplicateSupportElements->checkFrontPoint(ivert)) {
518 8 cntDof = 0;
519
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 8 times.
20 for(std::size_t iUnknown=0; iUnknown<this->m_listUnknown.size(); ++iUnknown) {
520 12 numComp = this->m_listVariable[this->m_listUnknown.idVariable(iUnknown)].numComponent();
521
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 12 times.
28 for(felInt icoor=0; icoor<numComp; ++icoor) {
522 16 idof = cntDof + ivert * numComp + icoor;
523
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 AOApplicationToPetsc(this->ao(), 1, &idof);
524
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
16 m_idDofBCVertices[iUnknown].push_back(idof);
525 }
526
527 12 cntDof += this->supportDofUnknown(iUnknown).numSupportDof() * numComp;
528 }
529 }
530 }
531 }
532
533 // By default, apply an homogeneous Dirichlet BC to all unknown of the solid.
534
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 4 times.
10 for(std::size_t iUnknown=0; iUnknown<this->m_listUnknown.size(); ++iUnknown) {
535
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 m_applyDirichletBC[iUnknown] = true;
536
1/2
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 m_valBC[iUnknown].resize(m_idDofBCVertices[iUnknown].size(), 0.);
537 }
538 4 }
539
540
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 if(!m_idDofBCVertices.empty()) {
541 40 userSetDirichletBC();
542
543 40 bool isDirichletBC = false;
544
2/2
✓ Branch 1 taken 60 times.
✓ Branch 2 taken 40 times.
100 for(std::size_t iUnknown=0; iUnknown<this->m_listUnknown.size(); ++iUnknown) {
545
1/2
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
60 if(m_applyDirichletBC[iUnknown]) {
546 // Enforce the Dirichlet boundary conditions
547 60 this->matrix(0).zeroRows(m_idDofBCVertices[iUnknown].size(), m_idDofBCVertices[iUnknown].data(), 1.);
548
549 60 this->vector().setValues(m_idDofBCVertices[iUnknown].size(), m_idDofBCVertices[iUnknown].data(), m_valBC[iUnknown].data(), INSERT_VALUES);
550
551 60 isDirichletBC = true;
552 }
553 }
554
555
1/2
✓ Branch 0 taken 40 times.
✗ Branch 1 not taken.
40 if(isDirichletBC)
556 40 this->vector().assembly();
557 }
558 40 }
559
560
561 template<class SolidPrb>
562 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::userSetDirichletBC()
563 {
564 // nothing to do, to override in the user solid problem
565 }
566
567
568 template<class SolidPrb>
569 10196 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::updateFluidVel(felInt ielSupportDof, const PetscVector& fluidSol, felInt iold)
570 {
571 felInt idDof;
572
573
2/2
✓ Branch 2 taken 20392 times.
✓ Branch 3 taken 10196 times.
30588 for(std::size_t iUnknown=0; iUnknown<m_pLinFluid->listUnknown().size(); ++iUnknown) {
574 20392 felInt idVar = m_pLinFluid->listUnknown().idVariable(iUnknown);
575
576
6/8
✓ Branch 1 taken 20392 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 20392 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8224 times.
✓ Branch 6 taken 12168 times.
✓ Branch 7 taken 8224 times.
✓ Branch 8 taken 12168 times.
20392 if(FelisceParam::instance().useProjectionForNitscheXFEM || m_useCurrentFluidSolution) {
577 // get the value of the velocity and the pressure at the dofs
578
2/2
✓ Branch 2 taken 24672 times.
✓ Branch 3 taken 8224 times.
32896 for (felInt iSupport=0; iSupport < m_pLinFluid->supportDofUnknown(iUnknown).getNumSupportDof(ielSupportDof); iSupport++) {
579
2/2
✓ Branch 3 taken 37008 times.
✓ Branch 4 taken 24672 times.
61680 for(std::size_t iComp=0; iComp<m_pLinFluid->listVariable()[idVar].numComponent(); ++iComp) {
580 // local to global id of the dof
581
1/2
✓ Branch 2 taken 37008 times.
✗ Branch 3 not taken.
37008 m_pLinFluid->dof().loc2glob(ielSupportDof, iSupport, idVar, iComp, idDof);
582
583 // petsc ordering
584
1/2
✓ Branch 2 taken 37008 times.
✗ Branch 3 not taken.
37008 AOApplicationToPetsc(m_pLinFluid->ao(), 1, &idDof);
585
586 // get values
587
2/4
✓ Branch 2 taken 37008 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 37008 times.
✗ Branch 6 not taken.
37008 fluidSol.getValues( 1, &idDof, &m_fluidDofSol[iUnknown].val(iComp, iSupport));
588 }
589 }
590 } else {
591 // get the value of the velocity and the pressure at the dofs
592
2/2
✓ Branch 2 taken 36504 times.
✓ Branch 3 taken 12168 times.
48672 for (felInt iSupport=0; iSupport < m_pLinFluid->supportDofUnknownOld(iold, iUnknown).getNumSupportDof(ielSupportDof); iSupport++) {
593
2/2
✓ Branch 3 taken 54756 times.
✓ Branch 4 taken 36504 times.
91260 for(std::size_t iComp=0; iComp<m_pLinFluid->listVariable()[idVar].numComponent(); ++iComp) {
594 // local to global id of the dof
595
1/2
✓ Branch 2 taken 54756 times.
✗ Branch 3 not taken.
54756 m_pLinFluid->dofOld(iold).loc2glob(ielSupportDof, iSupport, idVar, iComp, idDof);
596
597 // petsc ordering
598
1/2
✓ Branch 2 taken 54756 times.
✗ Branch 3 not taken.
54756 AOApplicationToPetsc(m_pLinFluid->aoOld(iold), 1, &idDof);
599
600 // get values
601
2/4
✓ Branch 2 taken 54756 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 54756 times.
✗ Branch 6 not taken.
54756 fluidSol.getValues( 1, &idDof, &m_fluidDofSol[iUnknown].val(iComp, iSupport));
602 }
603 }
604 }
605 }
606 10196 }
607
608
609 template<class SolidPrb>
610 2056 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::computeIntegrationPoints(std::vector<Point*>& ptElem)
611 {
612 // compute the integration of the substructure in the reference element of the structure element.
613 2056 this->m_feDisp->update(0, m_subItfPts);
614 2056 this->m_feDisp->computeCurrentQuadraturePoint();
615
616 2056 TypeShape fluidCellShape = (TypeShape) m_feFluid->geoEle().shape().typeShape();
617
618 // mapping from the current fluid element to the fluid reference element
619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2056 times.
2056 if(fluidCellShape == Quadrilateral) {
620 for(int ig=0; ig<this->m_feDisp->numQuadraturePoint(); ++ig) {
621 for(int icomp=0; icomp<m_feFluid->numCoor(); ++icomp) {
622 m_intPoints[ig][icomp] = 2*(this->m_feDisp->currentQuadPoint[ig][icomp] - (*ptElem[0])[icomp])/((*ptElem[2])[icomp] - (*ptElem[0])[icomp]) - 1.;
623 }
624 }
625
1/2
✓ Branch 0 taken 2056 times.
✗ Branch 1 not taken.
2056 } else if(fluidCellShape == Triangle) {
626 2056 double det = (ptElem[2]->y() - ptElem[0]->y())*(ptElem[1]->x() - ptElem[0]->x())
627 2056 - (ptElem[2]->x() - ptElem[0]->x())*(ptElem[1]->y() - ptElem[0]->y());
628
629
2/2
✓ Branch 1 taken 4112 times.
✓ Branch 2 taken 2056 times.
6168 for(int ig=0; ig<this->m_feDisp->numQuadraturePoint(); ++ig) {
630 4112 m_intPoints[ig][0] = (ptElem[2]->y() - ptElem[0]->y())*(this->m_feDisp->currentQuadPoint[ig].x() - ptElem[0]->x())/det + (ptElem[0]->x() - ptElem[2]->x()) * (this->m_feDisp->currentQuadPoint[ig].y() - ptElem[0]->y())/det;
631
632 4112 m_intPoints[ig][1] = (ptElem[0]->y() - ptElem[1]->y())*(this->m_feDisp->currentQuadPoint[ig].x() - ptElem[0]->x())/det + (ptElem[1]->x() - ptElem[0]->x())*(this->m_feDisp->currentQuadPoint[ig].y() - ptElem[0]->y())/det;
633 }
634
635 // m_scalDer[0] = (ptElem[2]->y() - ptElem[1]->y())/det;
636 // m_scalDer[1] = (ptElem[1]->x() - ptElem[2]->x())/det;
637 } else {
638 FEL_ERROR("This shape type is not implemented yet");
639 }
640 2056 }
641
642 template<class SolidPrb>
643 6106 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::computeFluidVelOnSubStructure(const std::vector<double>& strucNormal)
644 {
645 // Compute the velocity at the integration points of the sub structure
646 // These points are computed in the function computeIntegrationPoints
647
2/2
✓ Branch 1 taken 3053 times.
✓ Branch 2 taken 3053 times.
6106 if(m_numSolidComponent < m_feFluid->numCoor()) {
648
2/2
✓ Branch 1 taken 3053 times.
✓ Branch 2 taken 3053 times.
6106 for(int icomp=0; icomp<this->m_feDisp->numRefCoor(); ++icomp) {
649
2/2
✓ Branch 1 taken 6106 times.
✓ Branch 2 taken 3053 times.
9159 for(int ig=0; ig<this->m_feDisp->numQuadraturePoint(); ++ig) {
650 6106 m_elemNitscheXFEMSolidRHS.val(icomp, ig) = 0;
651
2/2
✓ Branch 1 taken 18318 times.
✓ Branch 2 taken 6106 times.
24424 for(int idof=0; idof<m_feFluid->numDof(); ++idof) {
652
2/2
✓ Branch 1 taken 36636 times.
✓ Branch 2 taken 18318 times.
54954 for(int jcomp=0; jcomp<m_feFluid->numCoor(); ++jcomp) {
653 36636 m_elemNitscheXFEMSolidRHS.val(icomp, ig) += m_fluidDofSol[0].val(jcomp, idof) * m_feFluid->refEle().basisFunction().phi(idof, m_intPoints[ig]) * strucNormal[jcomp];
654 }
655 }
656 }
657 }
658 } else {
659
2/2
✓ Branch 0 taken 6106 times.
✓ Branch 1 taken 3053 times.
9159 for(int icomp=0; icomp<m_numSolidComponent; ++icomp) {
660
2/2
✓ Branch 1 taken 12212 times.
✓ Branch 2 taken 6106 times.
18318 for(int ig=0; ig<this->m_feDisp->numQuadraturePoint(); ++ig) {
661 12212 m_elemNitscheXFEMSolidRHS.val(icomp, ig) = 0;
662
2/2
✓ Branch 1 taken 36636 times.
✓ Branch 2 taken 12212 times.
48848 for(int idof=0; idof<m_feFluid->numDof(); ++idof) {
663 36636 m_elemNitscheXFEMSolidRHS.val(icomp, ig) += m_fluidDofSol[0].val(icomp, idof) * m_feFluid->refEle().basisFunction().phi(idof, m_intPoints[ig]);
664 }
665 }
666 }
667 }
668 6106 }
669
670 template<class SolidPrb>
671 4090 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::computeFluidNormalDerivativeJump(double sideCoeff, const std::vector<double>& strucNormal, const std::vector<double>& strucNormalInit)
672 {
673 // compute the tensor at integration points of the sub structure
674 // These points are computed in the function computeIntegrationPoints
675 4090 double tmpval1 = 0;
676 4090 double tmpval2 = 0;
677
678
2/2
✓ Branch 1 taken 2045 times.
✓ Branch 2 taken 2045 times.
4090 if(m_numSolidComponent < m_feFluid->numCoor()) {
679
2/2
✓ Branch 1 taken 2045 times.
✓ Branch 2 taken 2045 times.
4090 for(int icomp=0; icomp<this->m_feDisp->numRefCoor(); ++icomp) {
680
2/2
✓ Branch 1 taken 4090 times.
✓ Branch 2 taken 2045 times.
6135 for(int ig=0; ig<this->m_feDisp->numQuadraturePoint(); ++ig) {
681 4090 m_elemNitscheXFEMSolidRHS.val(icomp, ig) = 0;
682
683 // velocity
684
2/2
✓ Branch 1 taken 8180 times.
✓ Branch 2 taken 4090 times.
12270 for(int kcomp=0; kcomp<m_feFluid->numCoor(); ++kcomp) {
685 8180 tmpval1 = 0;
686
2/2
✓ Branch 1 taken 24540 times.
✓ Branch 2 taken 8180 times.
32720 for(int idof=0; idof<m_feFluid->numDof(); ++idof) {
687 24540 tmpval2 = 0;
688
2/2
✓ Branch 1 taken 49080 times.
✓ Branch 2 taken 24540 times.
73620 for(int jcomp=0; jcomp<m_feFluid->numCoor(); ++jcomp) {
689 49080 tmpval2 += m_fluidDofSol[0].val(jcomp, idof) * strucNormal[jcomp];
690 }
691 // tmpval1 += m_scalDer[kcomp] * m_feFluid->refEle().basisFunction().dPhi(idof, kcomp, m_intPoints[ig]) * tmpval2;
692 24540 tmpval1 += m_feFluid->dPhi[ig](kcomp, idof) * tmpval2;
693 }
694 8180 m_elemNitscheXFEMSolidRHS.val(icomp, ig) += FelisceParam::instance().viscosity * tmpval1 * sideCoeff * strucNormalInit[kcomp];
695 }
696
697 // pressure
698 4090 tmpval1 = 0.;
699
2/2
✓ Branch 1 taken 8180 times.
✓ Branch 2 taken 4090 times.
12270 for(int kcomp=0; kcomp<m_feFluid->numCoor(); ++kcomp)
700 8180 tmpval1 += strucNormal[kcomp] * strucNormalInit[kcomp];
701
702
2/2
✓ Branch 1 taken 12270 times.
✓ Branch 2 taken 4090 times.
16360 for(int idof=0; idof<m_feFluid->numDof(); ++idof) {
703 12270 m_elemNitscheXFEMSolidRHS.val(icomp, ig) -= sideCoeff * m_fluidDofSol[1].val(0, idof) * m_fePres->refEle().basisFunction().phi(idof, m_intPoints[ig]) * tmpval1;
704 }
705 }
706 }
707
708 // if we use the symmetric formulation for the stress
709
1/2
✓ Branch 1 taken 2045 times.
✗ Branch 2 not taken.
2045 if(FelisceParam::instance().useSymmetricStress) {
710
2/2
✓ Branch 1 taken 2045 times.
✓ Branch 2 taken 2045 times.
4090 for(int icomp=0; icomp<this->m_feDisp->numRefCoor(); ++icomp) {
711
2/2
✓ Branch 1 taken 4090 times.
✓ Branch 2 taken 2045 times.
6135 for(int ig=0; ig<this->m_feDisp->numQuadraturePoint(); ++ig) {
712
2/2
✓ Branch 1 taken 8180 times.
✓ Branch 2 taken 4090 times.
12270 for(int jcomp=0; jcomp<m_feFluid->numCoor(); ++jcomp) {
713 8180 tmpval1 = 0;
714
2/2
✓ Branch 1 taken 24540 times.
✓ Branch 2 taken 8180 times.
32720 for(int idof=0; idof<m_feFluid->numDof(); ++idof) {
715 24540 tmpval2 = 0;
716
2/2
✓ Branch 1 taken 49080 times.
✓ Branch 2 taken 24540 times.
73620 for(int kcomp=0; kcomp<m_feFluid->numCoor(); ++kcomp) {
717 49080 tmpval2 += m_fluidDofSol[0].val(kcomp, idof) * sideCoeff * strucNormal[kcomp];
718 }
719 // tmpval1 += m_scalDer[jcomp] * m_feFluid->refEle().basisFunction().dPhi(idof, jcomp, m_intPoints[ig]) * tmpval2;
720 24540 tmpval1 += m_feFluid->dPhi[ig](jcomp, idof) * tmpval2;
721 }
722 8180 m_elemNitscheXFEMSolidRHS.val(icomp, ig) += FelisceParam::instance().viscosity * tmpval1 * strucNormalInit[jcomp];
723 }
724 }
725 }
726 }
727 } else {
728
2/2
✓ Branch 0 taken 4090 times.
✓ Branch 1 taken 2045 times.
6135 for(int icomp=0; icomp<m_numSolidComponent; ++icomp) {
729
2/2
✓ Branch 1 taken 8180 times.
✓ Branch 2 taken 4090 times.
12270 for(int ig=0; ig<this->m_feDisp->numQuadraturePoint(); ++ig) {
730 8180 m_elemNitscheXFEMSolidRHS.val(icomp, ig) = 0;
731
732 // velocity
733
2/2
✓ Branch 1 taken 16360 times.
✓ Branch 2 taken 8180 times.
24540 for(int jcomp=0; jcomp<m_feFluid->numCoor(); ++jcomp) {
734 16360 tmpval1 = 0;
735
2/2
✓ Branch 1 taken 49080 times.
✓ Branch 2 taken 16360 times.
65440 for(int idof=0; idof<m_feFluid->numDof(); ++idof) {
736 49080 tmpval1 += m_fluidDofSol[0].val(icomp, idof) * m_feFluid->dPhi[ig](jcomp, idof);
737 }
738
739 16360 m_elemNitscheXFEMSolidRHS.val(icomp, ig) += FelisceParam::instance().viscosity * tmpval1 * sideCoeff * strucNormal[jcomp];
740 }
741
742 // pressure
743
2/2
✓ Branch 1 taken 24540 times.
✓ Branch 2 taken 8180 times.
32720 for(int idof=0; idof<m_feFluid->numDof(); ++idof) {
744 24540 m_elemNitscheXFEMSolidRHS.val(icomp, ig) -= sideCoeff * m_fluidDofSol[1].val(0, idof) * m_fePres->refEle().basisFunction().phi(idof, m_intPoints[ig]) * strucNormal[icomp];
745 }
746 }
747 }
748
749 // if we use the symmetric formulation for the stress
750
1/2
✓ Branch 1 taken 2045 times.
✗ Branch 2 not taken.
2045 if(FelisceParam::instance().useSymmetricStress) {
751
2/2
✓ Branch 0 taken 4090 times.
✓ Branch 1 taken 2045 times.
6135 for(int icomp=0; icomp<m_numSolidComponent; ++icomp) {
752
2/2
✓ Branch 1 taken 8180 times.
✓ Branch 2 taken 4090 times.
12270 for(int ig=0; ig<this->m_feDisp->numQuadraturePoint(); ++ig) {
753
2/2
✓ Branch 1 taken 24540 times.
✓ Branch 2 taken 8180 times.
32720 for(int idof=0; idof<m_feFluid->numDof(); ++idof) {
754 24540 tmpval1 = 0;
755
2/2
✓ Branch 1 taken 49080 times.
✓ Branch 2 taken 24540 times.
73620 for(int jcomp=0; jcomp<m_feFluid->numCoor(); ++jcomp) {
756 49080 tmpval1 += m_fluidDofSol[0].val(jcomp, idof) * strucNormal[jcomp];
757 }
758
759 24540 m_elemNitscheXFEMSolidRHS.val(icomp, ig) += FelisceParam::instance().viscosity * tmpval1 * sideCoeff * m_feFluid->dPhi[ig](icomp, idof);
760 }
761 }
762 }
763 }
764 }
765 4090 }
766
767 /*!
768 * Gather the last time step displacement into m_seqLastTimeSol.
769 * If m_seqLastTimeSol is null, it will be created and allocated during the gathering
770 * according to the parallel shape of parStrucLastSol
771 */
772 template<class SolidPrb>
773 20 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::gatherSeqLastTimeSol(PetscVector& parStrucLastSol)
774 {
775 20 this->gatherVector(parStrucLastSol, m_seqLastTimeSol);
776 20 m_isSeqLastTimeSolAllocated = true;
777 20 }
778
779 /*!
780 * Gather the last time step displacement-velocity into m_seqLastTimeVelSol.
781 * If m_seqLastTimeVelSol is null, it will be created and allocated during the gathering
782 * according to the parallel shape of parStrucLastVelSol
783 */
784 template<class SolidPrb>
785 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::gatherSeqLastTimeVelSol(PetscVector& parStrucLastVelSol)
786 {
787 this->gatherVector(parStrucLastVelSol, m_seqLastTimeVelSol);
788 m_isSeqLastTimeVelSolAllocated = true;
789 }
790
791 /*!
792 * Gather the extrapolation Robin-Neumann of the displacement into m_seqRNStrucExtrapol.
793 * If m_seqRNStrucExtrapol is null, it will be created and allocated during the gathering
794 * according to the parallel shape of parStrucExtrapol
795 */
796 template<class SolidPrb>
797 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::gatherRNStructExtrapol(PetscVector& parRNStrucExtrapol) {
798 this->gatherVector(parRNStrucExtrapol, m_seqRNStrucExtrapol);
799 m_isSeqRNStrucExtrapolAllocated = true;
800 }
801
802 /*!
803 * Gather the extrapolation of the fluid velocity for the stabilized explicit splitting scheme
804 * into m_seqStabExplicitFluidExtrapol.
805 * If m_seqStabExplicitFluidExtrapol is null, it will be created and allocated during the gathering
806 * according to the parallel shape of parFluidExtrapol
807 */
808 template<class SolidPrb>
809 38 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::gatherStabExplicitFluidExtrapol(std::vector<PetscVector>& parFluidExtrapol)
810 {
811
2/2
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 38 times.
114 for(std::size_t i=0; i<parFluidExtrapol.size(); ++i)
812 76 this->gatherVector(parFluidExtrapol[i], m_seqStabExplicitFluidExtrapol[i]);
813
814 38 m_isSeqStabExplicitFluidExtrapolAllocated = true;
815 38 }
816
817 template<class SolidPrb>
818 20 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::gatherStabExplicitFluidExtrapol(PetscVector& parFluidExtrapol)
819 {
820 20 this->gatherVector(parFluidExtrapol, m_seqStabExplicitFluidExtrapol[0]);
821 20 m_isSeqStabExplicitFluidExtrapolAllocated = true;
822 20 }
823
824 template<class SolidPrb>
825 20 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::setStabExplicitFluidExtrapol(PetscVector& seqFluidExtrapol)
826 {
827 20 m_seqStabExplicitFluidExtrapol[0].copyFrom(seqFluidExtrapol);
828 20 }
829
830 template<class SolidPrb>
831 42 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::initStabExplicitFluidExtrapol(felInt order)
832 {
833
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 15 times.
42 if(m_isSeqStabExplicitFluidExtrapolAllocated) {
834
2/2
✓ Branch 1 taken 47 times.
✓ Branch 2 taken 27 times.
74 for(std::size_t i=0; i<m_seqStabExplicitFluidExtrapol.size(); ++i)
835 47 m_seqStabExplicitFluidExtrapol[i].destroy();
836
837 27 m_isSeqStabExplicitFluidExtrapolAllocated = false;
838 }
839
840 42 m_seqStabExplicitFluidExtrapol.resize(order);
841
2/2
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 42 times.
106 for(std::size_t i=0; i<m_seqStabExplicitFluidExtrapol.size(); ++i)
842
1/2
✓ Branch 3 taken 64 times.
✗ Branch 4 not taken.
64 m_seqStabExplicitFluidExtrapol[i] = PetscVector::null();
843 42 }
844
845 template<class SolidPrb>
846 11 void LinearProblemFSINitscheXFEMSolid<SolidPrb>::deleteDynamicData()
847 {
848
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if(m_isSeqStabExplicitFluidExtrapolAllocated) {
849
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 11 times.
22 for(std::size_t i=0; i<m_seqStabExplicitFluidExtrapol.size(); ++i) {
850 11 m_seqStabExplicitFluidExtrapol[i].destroy();
851
1/2
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
11 m_seqStabExplicitFluidExtrapol[i] = PetscVector::null();
852 }
853 11 m_isSeqStabExplicitFluidExtrapolAllocated = false;
854 }
855 11 }
856
857 template<class SolidPrb>
858 double LinearProblemFSINitscheXFEMSolid<SolidPrb>::computeL2Norm(PetscVector& inputVec)
859 {
860 if(m_seqVecL2Norm.isNull())
861 m_seqVecL2Norm.duplicateFrom(this->sequentialSolution());
862
863 this->gatherVector(inputVec, m_seqVecL2Norm);
864
865 GeometricMeshRegion::ElementType eltType;
866 felInt numPointPerElt = 0;
867 felInt numEltPerLabel = 0;
868
869 std::vector<Point*> elemPoint;
870 std::vector<felInt> elemIdPoint;
871 std::vector <felInt> vectorIdSupport;
872
873 // use to identify global id of dof.
874 felInt idDof;
875 felInt cpt = 0;
876
877 // Id link element to its supportDof.
878 felInt ielSupportDof;
879
880 // return value
881 double l2Norm = 0.;
882 double tmpL2Norm = 0.;
883
884 // initialize id global of elements.
885 felInt numElement[GeometricMeshRegion::m_numTypesOfElement ];
886 for (int ityp=0; ityp<GeometricMeshRegion::m_numTypesOfElement; ityp++ ) {
887 eltType = (GeometricMeshRegion::ElementType)ityp;
888 numElement[eltType] = 0;
889 }
890
891 CurvilinearFiniteElement *fePtr;
892 std::vector<double> dofValue;
893 std::vector<felInt> idGlobalDof;
894
895 const std::vector<GeometricMeshRegion::ElementType>& bagElementTypeDomain = this->meshLocal()->bagElementTypeDomain();
896 for (std::size_t i = 0; i < bagElementTypeDomain.size(); ++i) {
897 eltType = bagElementTypeDomain[i];
898 numPointPerElt = GeometricMeshRegion::m_numPointsPerElt[eltType];
899 elemPoint.resize(numPointPerElt, 0);
900 elemIdPoint.resize(numPointPerElt, 0);
901
902 // define the curvilinear finite element
903 this->defineCurvilinearFiniteElement(eltType);
904 this->initElementArrayBD();
905 fePtr = this->m_listCurvilinearFiniteElement[m_iDisplacement];
906
907 dofValue.resize(fePtr->numDof()*m_numSolidComponent, 0.);
908 idGlobalDof.resize(fePtr->numDof()*m_numSolidComponent, 0);
909
910 for(auto itRef = this->meshLocal()->intRefToBegEndMaps[eltType].begin(); itRef != this->meshLocal()->intRefToBegEndMaps[eltType].end(); itRef++) {
911 numEltPerLabel = itRef->second.second;
912
913 for (felInt iel = 0; iel < numEltPerLabel; iel++) {
914 this->setElemPoint(eltType, numElement[eltType], elemPoint, elemIdPoint, vectorIdSupport);
915 fePtr->updateMeas(0, elemPoint);
916
917 // loop over all the support elements
918 for (std::size_t it = 0; it < vectorIdSupport.size(); it++) {
919 // get the id of the support
920 ielSupportDof = vectorIdSupport[it];
921
922 cpt = 0;
923 for(felInt iDof=0; iDof<fePtr->numDof(); iDof++) {
924 for(felInt iComp = 0; iComp<m_numSolidComponent; iComp++) {
925 this->dof().loc2glob(ielSupportDof, iDof, m_iDisplacement, iComp, idDof);
926 idGlobalDof[cpt] = idDof;
927 ++cpt;
928 }
929 }
930
931 // mapping to obtain new global numbering. (I/O array: idGlobalDof).
932 AOApplicationToPetsc(this->m_ao, fePtr->numDof()*m_numSolidComponent, idGlobalDof.data());
933
934 // gets values of associate dofs.
935 m_seqVecL2Norm.getValues(fePtr->numDof()*m_numSolidComponent, idGlobalDof.data(), dofValue.data());
936
937 for(felInt ig=0; ig<fePtr->numQuadraturePoint(); ++ig) {
938 double tmpval = 0.;
939 for(felInt iComp=0; iComp<m_numSolidComponent; ++iComp) {
940 double uicomp = 0.;
941 for(felInt idof = 0; idof<fePtr->numDof(); ++idof) {
942 uicomp += fePtr->phi[ig](idof) * dofValue[idof*m_numSolidComponent + iComp] ;
943 }
944 tmpval += uicomp * uicomp;
945 }
946 tmpL2Norm += tmpval * fePtr->weightMeas(ig);
947 }
948 }
949 numElement[eltType]++;
950 }
951 }
952 }
953
954 MPI_Allreduce(&tmpL2Norm, &l2Norm, 1, MPI_DOUBLE, MPI_SUM, MpiInfo::petscComm());
955 return l2Norm;
956 }
957 }
958