GCC Code Coverage Report


Directory: ./
File: Solver/linearProblemStokesContinuation.cpp
Date: 2024-04-14 07:32:34
Exec Total Coverage
Lines: 283 288 98.3%
Branches: 223 370 60.3%

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
13 //
14
15 // System includes
16 #include <stack>
17
18 // External includes
19
20 // Project includes
21 #include "Solver/linearProblemStokesContinuation.hpp"
22 #include "Core/felisceTransient.hpp"
23 #include "FiniteElement/elementVector.hpp"
24 #include "FiniteElement/elementMatrix.hpp"
25 #include "InputOutput/io.hpp"
26 #include "DegreeOfFreedom/boundaryCondition.hpp"
27
28 /*!
29 \file linearProblemStokesContinuation.cpp
30 \date 17/03/2022
31 \brief Continuation method for Stokes' equation
32 */
33
34 namespace felisce {
35 4 LinearProblemStokesContinuation::LinearProblemStokesContinuation():
36
5/10
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
4 LinearProblem("Poisson continuation equation")
37 {
38 4 }
39
40 20 void LinearProblemStokesContinuation::readData(IO& io,double iteration) {
41 // Read velocity variable from the .case file
42 20 std::vector<double> potData;
43
1/2
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
20 potData.resize(m_mesh[m_currentMesh]->numPoints()*3, 0.);
44
1/2
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
20 io.readVariable(0,iteration, potData.data(), potData.size());
45
46 20 std::vector<double> potDataVelocity;
47 20 int dim = this->dimension();
48
1/2
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
20 potDataVelocity.resize(m_mesh[m_currentMesh]->numPoints()*dim, 0.);
49
2/2
✓ Branch 3 taken 2840 times.
✓ Branch 4 taken 20 times.
2860 for (int i=0; i < m_mesh[m_currentMesh]->numPoints(); ++i) {
50
2/2
✓ Branch 0 taken 5680 times.
✓ Branch 1 taken 2840 times.
8520 for(int icomp=0; icomp<dim; icomp++) {
51 5680 potDataVelocity[dim*i+icomp]=potData[3*i+icomp];
52 }
53 }
54
55
1/2
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 m_potData.duplicateFrom(this->sequentialSolution());
56
57
1/2
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
20 std::vector<PetscInt> ao_potData( potDataVelocity.size());
58
2/2
✓ Branch 1 taken 5680 times.
✓ Branch 2 taken 20 times.
5700 for (size_t i=0; i < potDataVelocity.size(); ++i) {
59 5680 ao_potData[i]=i;
60 }
61
62
1/2
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
20 AOApplicationToPetsc(this->ao(),potDataVelocity.size(),ao_potData.data());
63
2/4
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
20 VecSetValues(m_potData.toPetsc(),potDataVelocity.size(),ao_potData.data(), potDataVelocity.data(), INSERT_VALUES);
64 20 }
65
66 4 void LinearProblemStokesContinuation::initialize(std::vector<GeometricMeshRegion::Pointer>& mesh, FelisceTransient::Pointer fstransient, MPI_Comm& comm, bool doUseSNES) {
67
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 LinearProblem::initialize(mesh,comm, doUseSNES);
68 4 this->m_fstransient = fstransient;
69 4 std::vector<PhysicalVariable> listVariable;
70 4 std::vector<std::size_t> listNumComp;
71
72 // primal variables
73
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 listVariable.push_back(velocity);
74
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 listNumComp.push_back(this->dimension());
75
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 listVariable.push_back(pressure);
76
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 listNumComp.push_back(1);
77
78 // dual variables with dummy names
79
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 listVariable.push_back(velocityDiv);
80
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 listNumComp.push_back(this->dimension());
81
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 listVariable.push_back(potThorax);
82
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 listNumComp.push_back(1);
83
84 //define unknown of the linear system.
85
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 m_listUnknown.push_back(velocity);
86
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 m_listUnknown.push_back(pressure);
87
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 m_listUnknown.push_back(velocityDiv);
88
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 m_listUnknown.push_back(potThorax);
89
90
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 userAddOtherUnknowns(listVariable,listNumComp);
91
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 userAddOtherVariables(listVariable,listNumComp);
92
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 definePhysicalVariable(listVariable,listNumComp);
93
94
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 m_iVelocity = m_listVariable.getVariableIdList(velocity);
95
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 m_iPressure = m_listVariable.getVariableIdList(pressure);
96
97
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 m_viscosity = FelisceParam::instance().viscosity;
98
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 m_useSymmetricStress = FelisceParam::instance().useSymmetricStress;
99 4 }
100
101 40 void LinearProblemStokesContinuation::initPerElementType(ElementType eltType, FlagMatrixRHS flagMatrixRHS) {
102 IGNORE_UNUSED_ARGUMENT(eltType);
103 IGNORE_UNUSED_ARGUMENT(flagMatrixRHS);
104 40 m_feVel = m_listCurrentFiniteElement[m_iVelocity];
105 40 m_fePres = m_listCurrentFiniteElement[m_iPressure];
106
107 // define elemField to store the given velocity measurements and the source terms
108 40 m_dataTerm.initialize(DOF_FIELD, *m_feVel, this->dimension());
109 40 m_sourceTerm.initialize(DOF_FIELD, *m_feVel, this->dimension());
110 40 }
111
112
113 1210 void LinearProblemStokesContinuation::computeElementArray(const std::vector<Point*>& elemPoint, const std::vector<felInt>& /*elemIdPoint*/, felInt& iel, FlagMatrixRHS flagMatrixRHS) {
114 1210 m_feVel->updateFirstDeriv(0, elemPoint);
115 1210 m_fePres->updateFirstDeriv(0, elemPoint);
116
117 1210 double hK = m_feVel->diameter();
118
119 // stabilization parameters
120 1210 double gamma_M = FelisceParam::instance().referenceValue2; // data fidelity coefficient
121 1210 double gamma_p = hK*hK*FelisceParam::instance().referenceValue3; // Brezzi-Pitkaranta coefficient
122 1210 double gamma_p_star = FelisceParam::instance().referenceValue4; // dual pressure coefficient
123 1210 double gamma_div = 0.1;
124 1210 double gamma_u_star = 0.1;
125
126 // time derivative coefficient
127 1210 double rhof = FelisceParam::instance(this->instanceIndex()).density;
128 1210 double coef_time = rhof/m_fstransient->timeStep;
129
130 // defining the block matrix of the system
131
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1210 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1210 if (flagMatrixRHS == FlagMatrixRHS::matrix_and_rhs || flagMatrixRHS == FlagMatrixRHS::only_matrix) {
132 // stabilizing div term acting on u, \int \nabla \cdot u \nabla \cdot v
133 1210 m_elementMat[0]->div_phi_j_div_phi_i(gamma_div, *m_feVel, 0, 0, this->dimension()); // block (0,0)
134 // data term, int_\Omega u \cdot v; to this block we will also add the cip stabilization
135 1210 m_elementMat[0]->phi_i_phi_j(gamma_M, *m_feVel, 0, 0, this->dimension()); // block (0,0)
136
137 // stabilizing term acting on p, int_\Omega grad p : grad q
138 1210 m_elementMat[0]->grad_phi_i_grad_phi_j(gamma_p, *m_fePres, this->dimension(), this->dimension(), 1); // block (1,1)
139
140 // time discretization for z, int_\Omega v \cdot z
141 1210 m_elementMat[0]->phi_i_phi_j(coef_time, *m_feVel, 0, 1+this->dimension(), this->dimension()); // block (0,2)
142
143 // Stokes blocks for z and y, int_\Omega \epsilon v : \epsilon z or int_\Omega \nabla v : \nabla z
144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1210 times.
1210 if (m_useSymmetricStress)
145 m_elementMat[0]->eps_phi_i_eps_phi_j(2*m_viscosity, *m_feVel, 0, 1+this->dimension(), this->dimension()); // block (0,2)
146 else
147 1210 m_elementMat[0]->grad_phi_i_grad_phi_j(m_viscosity, *m_feVel, 0, 1+this->dimension(), this->dimension()); // block (0,2)
148 // \int y \nabla \cdot v and -\int q \nabla \cdot z
149 1210 m_elementMat[0]->psi_j_div_phi_i(1., *m_feVel, *m_fePres, 0, 1+2*this->dimension()); // block (0,3)
150 1210 m_elementMat[0]->psi_i_div_phi_j(-1., *m_feVel, *m_fePres, this->dimension(), 1+this->dimension()); // block (1,2)
151
152 // time discretization for u, int_\Omega u \cdot w
153 1210 m_elementMat[0]->phi_i_phi_j(coef_time, *m_feVel, 1+this->dimension(), 0, this->dimension()); // block (2,0)
154
155 // Stokes blocks for u and p, int_\Omega \epsilon u : \epsilon v or int_\Omega \nabla u : \nabla v
156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1210 times.
1210 if (m_useSymmetricStress)
157 m_elementMat[0]->eps_phi_i_eps_phi_j(2*m_viscosity, *m_feVel, 1+this->dimension(), 0, this->dimension()); // block (2,0)
158 else
159 1210 m_elementMat[0]->grad_phi_i_grad_phi_j(m_viscosity, *m_feVel, 1+this->dimension(), 0, this->dimension()); // block (2,0)
160 // -int p \nabla \cdot w and \int x \nabla \cdot u
161 1210 m_elementMat[0]->psi_j_div_phi_i(-1., *m_feVel, *m_fePres, 1+this->dimension(), this->dimension()); // block (2,1)
162 1210 m_elementMat[0]->psi_i_div_phi_j(1., *m_feVel, *m_fePres, 1+2*this->dimension(), 0); // block (3,0)
163
164 // stabilizing term acting on z, -int_\Omega grad z : grad w
165 1210 m_elementMat[0]->grad_phi_i_grad_phi_j(-gamma_u_star, *m_feVel, 1+this->dimension(), 1+this->dimension(), this->dimension()); // block (2,2)
166 // stabilizing term acting on y, -int_\Omega y * x
167 1210 m_elementMat[0]->phi_i_phi_j(-gamma_p_star, *m_fePres, 1+2*this->dimension(), 1+2*this->dimension(), 1); // block (3,3)
168 }
169 // defining the rhs of the system
170
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1210 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1210 if (flagMatrixRHS == FlagMatrixRHS::matrix_and_rhs || flagMatrixRHS == FlagMatrixRHS::only_rhs) {
171 //rhs data term, using the measurements
172 1210 m_dataTerm.setValue(m_potData, *m_feVel, iel, m_iVelocity, m_ao, dof());
173
174 // gamma_M int_\Omega u_M \cdot v
175 1210 m_elementVector[0]->source(gamma_M, *m_feVel, m_dataTerm, 0, this->dimension());
176
177 //rhs f term, zero
178
179 // rhs source term, the solution at the previous time step
180 1210 m_sourceTerm.setValue(this->sequentialSolution(), *m_feVel, iel, m_iVelocity, m_ao, dof());
181
182 // rhof/tau int_\Omega u^{n-1} \cdot w
183 1210 m_elementVector[0]->source(coef_time, *m_feVel, m_sourceTerm, 1+this->dimension(), this->dimension());
184 }
185 1210 }
186
187 4 void LinearProblemStokesContinuation::userChangePattern(int numProc, int rankProc) {
188 IGNORE_UNUSED_ARGUMENT(numProc);
189 IGNORE_UNUSED_ARGUMENT(rankProc);
190 // compute initial (uniform) repartition of dof on processes
191
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 felInt numDofByProc = m_numDof/MpiInfo::numProc();
192
2/4
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 std::vector<felInt> numDofPerProc(MpiInfo::numProc());
193
3/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 4 times.
20 for(felInt i=0; i<MpiInfo::numProc(); ++i) {
194
3/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 12 times.
16 if(i == MpiInfo::numProc() - 1)
195 4 numDofPerProc[i] = m_numDof - i*numDofByProc;
196 else
197 12 numDofPerProc[i] = numDofByProc;
198 }
199
200 4 felInt shiftDof = 0;
201
3/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 4 times.
10 for(felInt i=0; i<MpiInfo::rankProc(); ++i)
202 6 shiftDof += numDofPerProc[i];
203
204
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 std::vector<felInt> rankDof(m_numDof, -1);
205
3/4
✓ Branch 1 taken 856 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 852 times.
✓ Branch 5 taken 4 times.
856 for(felInt i=0; i<numDofPerProc[MpiInfo::rankProc()]; ++i)
206
1/2
✓ Branch 1 taken 852 times.
✗ Branch 2 not taken.
852 rankDof[i + shiftDof] = MpiInfo::rankProc();
207
208 // build the edges or faces depending on the dimension (for the global mesh)
209 // In this function, "faces" refers to either edges or faces.
210
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if(dimension() == 2)
211
1/2
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
4 m_mesh[m_currentMesh]->buildEdges();
212 else
213 m_mesh[m_currentMesh]->buildFaces();
214
215 // variables
216 GeometricMeshRegion::ElementType eltType, eltTypeOpp;
217 felInt idVar1, idVar2;
218 felInt node1, node2;
219 felInt numFacesPerElement, numEltPerLabel;
220 felInt ielSupport, jelSupport;
221 felInt ielCurrentGeo, ielOppositeGeo;
222 4 std::vector<felInt> vecSupport, vecSupportOpposite;
223
1/2
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 std::vector<felInt> numElement(m_mesh[m_currentMesh]->m_numTypesOfElement, 0);
224
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 std::vector< std::set<felInt> > nodesNeighborhood(m_numDof);
225
226
227 // zeroth loop on the unknown of the linear problem
228
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 4 times.
20 for (size_t iUnknown1 = 0; iUnknown1 < m_listUnknown.size(); ++iUnknown1) {
229 16 idVar1 = m_listUnknown.idVariable(iUnknown1);
230
231 16 ielCurrentGeo = 0;
232
233 // first loop on element type
234
2/2
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 16 times.
32 for (size_t i=0; i<m_mesh[m_currentMesh]->bagElementTypeDomain().size(); ++i) {
235 16 eltType = m_mesh[m_currentMesh]->bagElementTypeDomain()[i];
236 16 const GeoElement* geoEle = GeometricMeshRegion::eltEnumToFelNameGeoEle[eltType].second;
237 16 numElement[eltType] = 0;
238 16 numFacesPerElement = geoEle->numBdEle();
239
240 // second loop on region of the mesh.
241
2/2
✓ Branch 10 taken 16 times.
✓ Branch 11 taken 16 times.
32 for(GeometricMeshRegion::IntRefToBegEndIndex_type::const_iterator itRef =m_mesh[m_currentMesh]->intRefToBegEndMaps[eltType].begin(); itRef !=m_mesh[m_currentMesh]->intRefToBegEndMaps[eltType].end(); itRef++) {
242 16 numEltPerLabel = itRef->second.second;
243
244 // Third loop on element
245
2/2
✓ Branch 0 taken 3872 times.
✓ Branch 1 taken 16 times.
3888 for (felInt iel = 0; iel < numEltPerLabel; iel++) {
246
1/2
✓ Branch 3 taken 3872 times.
✗ Branch 4 not taken.
3872 m_supportDofUnknown[iUnknown1].getIdElementSupport(eltType, numElement[eltType], vecSupport);
247
248
2/2
✓ Branch 1 taken 3872 times.
✓ Branch 2 taken 3872 times.
7744 for(size_t ielSup=0; ielSup<vecSupport.size(); ++ielSup) {
249 3872 ielSupport = vecSupport[ielSup];
250
251 // for all support dof in this support element
252
2/2
✓ Branch 2 taken 11616 times.
✓ Branch 3 taken 3872 times.
15488 for (felInt iSup = 0; iSup < m_supportDofUnknown[iUnknown1].getNumSupportDof(ielSupport); ++iSup) {
253 // for all component of the unknown
254
2/2
✓ Branch 2 taken 17424 times.
✓ Branch 3 taken 11616 times.
29040 for (size_t iComp = 0; iComp < m_listVariable[idVar1].numComponent(); iComp++) {
255 // get the global id of the support dof
256
1/2
✓ Branch 2 taken 17424 times.
✗ Branch 3 not taken.
17424 dof().loc2glob(ielSupport, iSup, idVar1, iComp, node1);
257
258 // if this node is on this process
259
3/4
✓ Branch 2 taken 17424 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4356 times.
✓ Branch 5 taken 13068 times.
17424 if(rankDof[node1] == MpiInfo::rankProc()) {
260 // loop over the boundaries of the element
261
2/2
✓ Branch 0 taken 13068 times.
✓ Branch 1 taken 4356 times.
17424 for(felInt iface=0; iface < numFacesPerElement; ++iface) {
262 // check if this face is an inner face or a boundary
263 13068 ielOppositeGeo = ielCurrentGeo;
264 13068 eltTypeOpp = eltType;
265
1/2
✓ Branch 3 taken 13068 times.
✗ Branch 4 not taken.
13068 bool isAnInnerFace =m_mesh[m_currentMesh]->getAdjElement(eltTypeOpp, ielOppositeGeo, iface);
266
267
2/2
✓ Branch 0 taken 12348 times.
✓ Branch 1 taken 720 times.
13068 if(isAnInnerFace) {
268 // for all unknown
269
2/2
✓ Branch 1 taken 49392 times.
✓ Branch 2 taken 12348 times.
61740 for (size_t iUnknown2 = 0; iUnknown2 < m_listUnknown.size(); ++iUnknown2) {
270 49392 idVar2 = m_listUnknown.idVariable(iUnknown2);
271
272 // get the support element of the opposite element
273
1/2
✓ Branch 2 taken 49392 times.
✗ Branch 3 not taken.
49392 m_supportDofUnknown[iUnknown2].getIdElementSupport(ielOppositeGeo, vecSupportOpposite);
274
275 // for all support element
276
2/2
✓ Branch 1 taken 49392 times.
✓ Branch 2 taken 49392 times.
98784 for(size_t jelSup=0; jelSup<vecSupportOpposite.size(); ++jelSup) {
277 49392 jelSupport = vecSupportOpposite[jelSup];
278
279 // for all support dof in this support element
280
2/2
✓ Branch 2 taken 148176 times.
✓ Branch 3 taken 49392 times.
197568 for (felInt jSup = 0; jSup < m_supportDofUnknown[iUnknown2].getNumSupportDof(jelSupport); ++jSup) {
281
282 // for all component of the second unknown
283
2/2
✓ Branch 2 taken 222264 times.
✓ Branch 3 taken 148176 times.
370440 for (size_t jComp = 0; jComp < m_listVariable[idVar2].numComponent(); jComp++) {
284
285 // If the two current components are connected
286
1/2
✓ Branch 2 taken 222264 times.
✗ Branch 3 not taken.
222264 felInt iConnect = dof().getNumGlobComp(iUnknown1, iComp);
287
1/2
✓ Branch 2 taken 222264 times.
✗ Branch 3 not taken.
222264 felInt jConnect = dof().getNumGlobComp(iUnknown2, jComp);
288
2/4
✓ Branch 2 taken 222264 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 222264 times.
✗ Branch 5 not taken.
222264 if (m_listUnknown.mask()(iConnect, jConnect) > 0) {
289 // get the global id of the second support dof
290
1/2
✓ Branch 2 taken 222264 times.
✗ Branch 3 not taken.
222264 dof().loc2glob(jelSupport, jSup, idVar2, jComp, node2);
291
292 // remove diagonal term to define pattern and use it in Parmetis.
293 // if the two global ids are different, they are neighboors
294
2/2
✓ Branch 0 taken 214032 times.
✓ Branch 1 taken 8232 times.
222264 if(node1 != node2)
295
1/2
✓ Branch 2 taken 214032 times.
✗ Branch 3 not taken.
214032 nodesNeighborhood[node1].insert(node2);
296 }
297 }
298 }
299 }
300 }
301 }
302 }
303 }
304 }
305 }
306 }
307 3872 ++ielCurrentGeo;
308 3872 ++numElement[eltType];
309 }
310 }
311 }
312 }
313
314 // Store the pattern in CSR style
315 4 std::vector<felInt> iCSR, jCSR;
316 4 felInt dofSize = 0;
317 4 felInt cptDof = 0;
318 felInt pos;
319
320
1/2
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
4 iCSR.resize(dof().pattern().numRows() + 1, 0);
321
2/2
✓ Branch 1 taken 3408 times.
✓ Branch 2 taken 4 times.
3412 for(size_t iNode=0; iNode<nodesNeighborhood.size(); ++iNode)
322 3408 dofSize += nodesNeighborhood[iNode].size();
323
324
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 jCSR.resize(dofSize, 0);
325
2/2
✓ Branch 1 taken 3408 times.
✓ Branch 2 taken 4 times.
3412 for(size_t iNode=0; iNode<nodesNeighborhood.size(); ++iNode) {
326
3/4
✓ Branch 2 taken 3408 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 852 times.
✓ Branch 5 taken 2556 times.
3408 if(rankDof[iNode] == MpiInfo::rankProc()) {
327 852 iCSR[cptDof + 1] = iCSR[cptDof] + nodesNeighborhood[iNode].size();
328 852 pos = 0;
329
2/2
✓ Branch 5 taken 55956 times.
✓ Branch 6 taken 852 times.
56808 for(std::set<felInt>::iterator it=nodesNeighborhood[iNode].begin(); it != nodesNeighborhood[iNode].end(); ++it) {
330 55956 jCSR[iCSR[cptDof] + pos] = *it;
331 55956 ++pos;
332 }
333 852 ++cptDof;
334 }
335 }
336
337 // Now, call merge pattern
338
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 dof().mergeGlobalPattern(iCSR, jCSR);
339 //std::cout<<"After global merge"<<std::endl;
340 //dof().pattern().print(1, std::cout);
341 4 }
342
343 // compared to the function linearProblemNS::assembleFaceOrientedStabilization, here we use different blocks and only the jumps in the velocity
344 20 void LinearProblemStokesContinuation::assembleCIPStabilization() {
345 // definition of variables
346 20 std::pair<bool, GeometricMeshRegion::ElementType> adjElt;
347 GeometricMeshRegion::ElementType eltType; // Type of element
348
349 20 felInt ielCurrentLocalGeo = 0; // local geometric id of the current element
350 20 felInt ielCurrentGlobalGeo = 0; // global geometric id of the current element
351 20 felInt ielOppositeGlobalGeo = 0; // global geometric id of the opposite element
352 felInt numFacesPerType; // number of faces of an element of a given type
353 felInt numPointPerElt; // number of vertices by element
354 felInt ielCurrentGlobalSup; // global support element id of the current element
355 felInt ielOppositeGlobalSup; // global support element id of the opposite element
356
357 20 std::vector<felInt> idOfFacesCurrent; // ids of the current element edges
358 20 std::vector<felInt> idOfFacesOpposite; // ids of the opposite element edges
359 20 std::vector<felInt> currentElemIdPoint; // ids of the vertices of the current element
360 20 std::vector<felInt> oppositeElemIdPoint; // ids of the vertices of the opposite element
361 20 std::vector<Point*> currentElemPoint; // point coordinates of the current element vertices
362 20 std::vector<Point*> oppositeElemPoint; // point coordinates of the opposite element vertices
363
364 20 FlagMatrixRHS flag = FlagMatrixRHS::only_matrix; // flag to only assemble the matrix
365 felInt idFaceToDo;
366 20 bool allDone = false;
367
368
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ElementField elemFieldAdvFace;
369
370 felInt rank;
371
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
372
373 // bag element type vector
374 20 const std::vector<ElementType>& bagElementTypeDomain = m_meshLocal[m_currentMesh]->bagElementTypeDomain();
375 20 eltType = bagElementTypeDomain[0];
376
377
378 // Finite Element With Bd for the opposite element
379 CurrentFiniteElementWithBd* ptmp;
380 CurrentFiniteElementWithBd* oppositeFEWithBd;
381
382
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 m_velocity = &m_listVariable[m_listVariable.getVariableIdList(velocity)];
383
384 20 const GeoElement *geoEle = m_mesh[m_currentMesh]->eltEnumToFelNameGeoEle[eltType].second;
385 20 felInt typeOfFEVel = m_velocity->finiteElementType();
386
387
1/2
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
20 const RefElement *refEleVel = geoEle->defineFiniteEle(eltType, typeOfFEVel, *m_mesh[m_currentMesh]);
388
2/4
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 20 times.
✗ Branch 7 not taken.
20 oppositeFEWithBd = new CurrentFiniteElementWithBd(*refEleVel, *geoEle, m_velocity->degreeOfExactness(), m_velocity->degreeOfExactness());
389
390 // initializing variables
391 20 numPointPerElt = m_meshLocal[m_currentMesh]->m_numPointsPerElt[eltType];
392 20 numFacesPerType = GeometricMeshRegion::eltEnumToFelNameGeoEle[eltType].second->numBdEle();
393
394 // resize of vectors
395
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 idOfFacesCurrent.resize(numFacesPerType, -1);
396
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 idOfFacesOpposite.resize(numFacesPerType, -1);
397
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 currentElemIdPoint.resize(numPointPerElt, -1);
398
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 oppositeElemIdPoint.resize(numPointPerElt, -1);
399
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 currentElemPoint.resize(numPointPerElt, NULL);
400
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 oppositeElemPoint.resize(numPointPerElt, NULL);
401
402 // define finite element
403
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 defineFiniteElement(eltType);
404
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 initElementArray();
405
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 defineCurrentFiniteElementWithBd(eltType);
406
407 // allocate arrays for assembling the matrix
408
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 allocateArrayForAssembleMatrixRHS(flag);
409
410 // init variables
411
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 initPerElementType(eltType, flag);
412 20 CurrentFiniteElementWithBd* feWithBd = m_listCurrentFiniteElementWithBd[m_iVelocity];
413
414 20 CurrentFiniteElementWithBd* firstCurrentFe = feWithBd;
415 20 CurrentFiniteElementWithBd* firstOppositeFe = oppositeFEWithBd;
416
417 // get informations on the current element
418
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 setElemPoint(eltType, 0, currentElemPoint, currentElemIdPoint, &ielCurrentGlobalSup);
419
420 // update the finite elements
421
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 feWithBd->updateFirstDeriv(0, currentElemPoint);
422
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 feWithBd->updateBdMeasNormal();
423
424 // get the global id of the first geometric element
425
1/2
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 ISLocalToGlobalMappingApply(m_mappingElem[m_currentMesh], 1, &ielCurrentLocalGeo, &ielCurrentGlobalGeo);
426
427 // the map to remember what contribution have already been computed
428 20 std::map<felInt, std::vector<bool> > contribDone;
429
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
20 addNewFaceOrientedContributor(numFacesPerType, ielCurrentGlobalGeo, contribDone[ielCurrentGlobalGeo]);
430
431 // build the stack to know what is the next element
432
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 std::stack<felInt> nextInStack;
433
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 nextInStack.push(ielCurrentGlobalGeo);
434
435 // get all the faces of the element
436
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 if(dimension() == 2)
437
1/2
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
20 m_mesh[m_currentMesh]->getAllEdgeOfElement(ielCurrentGlobalGeo, idOfFacesCurrent);
438 else
439 m_mesh[m_currentMesh]->getAllFaceOfElement(ielCurrentGlobalGeo, idOfFacesCurrent);
440
441 // loop over all the element (snake style)
442
2/2
✓ Branch 1 taken 2605 times.
✓ Branch 2 taken 20 times.
2625 while(!nextInStack.empty()) {
443 // check the faces and use the first one that is an inner face and that has not been done yet.
444 2605 idFaceToDo = -1;
445 2605 allDone = true;
446
3/4
✓ Branch 1 taken 10420 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7815 times.
✓ Branch 5 taken 2605 times.
10420 for(size_t iface=0; iface<contribDone[ielCurrentGlobalGeo].size(); ++iface) {
447
4/6
✓ Branch 1 taken 7815 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7815 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2890 times.
✓ Branch 8 taken 4925 times.
7815 if(!contribDone[ielCurrentGlobalGeo][iface]) {
448 // This is an inner face, check if the contribution has already been computed or not
449
2/2
✓ Branch 0 taken 1865 times.
✓ Branch 1 taken 1025 times.
2890 if(idFaceToDo == -1) {
450 1865 idFaceToDo = iface;
451 } else {
452 1025 allDone = false;
453 }
454 }
455 }
456
457 // update the stack
458
2/2
✓ Branch 0 taken 1020 times.
✓ Branch 1 taken 1585 times.
2605 if(!allDone)
459
1/2
✓ Branch 1 taken 1020 times.
✗ Branch 2 not taken.
1020 nextInStack.push(ielCurrentGlobalGeo);
460
461
6/6
✓ Branch 1 taken 2060 times.
✓ Branch 2 taken 545 times.
✓ Branch 3 taken 1040 times.
✓ Branch 4 taken 1020 times.
✓ Branch 5 taken 1040 times.
✓ Branch 6 taken 1565 times.
2605 if(nextInStack.top() == ielCurrentGlobalGeo && allDone)
462 1040 nextInStack.pop();
463
464
465 // assemble terms
466
2/2
✓ Branch 0 taken 1865 times.
✓ Branch 1 taken 740 times.
2605 if(idFaceToDo != -1) {
467 // get the opposite id of the element
468 1865 ielOppositeGlobalGeo = ielCurrentGlobalGeo;
469
1/2
✓ Branch 3 taken 1865 times.
✗ Branch 4 not taken.
1865 adjElt =m_mesh[m_currentMesh]->getAdjElement(ielOppositeGlobalGeo, idFaceToDo);
470
471 // get the type of the opposite element
472 // eltTypeOpp = adjElt.second;
473
474 // update the opposite finite element and set ielOppositeGlobalSup
475
1/2
✓ Branch 1 taken 1865 times.
✗ Branch 2 not taken.
1865 updateFaceOrientedFEWithBd(oppositeFEWithBd, idOfFacesOpposite, numPointPerElt, ielOppositeGlobalGeo, ielOppositeGlobalSup);
476
477 // find the local id of the edge in the opposite element
478 1865 felInt localIdFaceOpposite = -1;
479
2/2
✓ Branch 1 taken 5595 times.
✓ Branch 2 taken 1865 times.
7460 for(size_t jface=0; jface<idOfFacesOpposite.size(); ++jface) {
480
2/2
✓ Branch 2 taken 1865 times.
✓ Branch 3 taken 3730 times.
5595 if(idOfFacesCurrent[idFaceToDo] == idOfFacesOpposite[jface]) {
481 1865 localIdFaceOpposite = jface;
482 }
483 }
484
485 // compute coefficients
486
1/2
✓ Branch 1 taken 1865 times.
✗ Branch 2 not taken.
1865 CurvilinearFiniteElement* curvFe = &feWithBd->bdEle(idFaceToDo);
487 //CurvilinearFiniteElement* curvFeOP = &oppositeFEWithBd->bdEle(localIdFaceOpposite);
488
1/2
✓ Branch 1 taken 1865 times.
✗ Branch 2 not taken.
1865 double hK = curvFe->diameter(); //0.5 * (feWithBd->diameter() + oppositeFEWithBd->diameter());
489 //cout << hK - curvFeOP->diameter() << endl;
490
1/2
✓ Branch 1 taken 1865 times.
✗ Branch 2 not taken.
1865 double gamma_u = FelisceParam::instance().referenceValue1; // cip coefficient
491 1865 double gamma = hK*gamma_u;
492
493 // We can now compute all the integrals.
494 // current element for phi_i and phi_j
495
1/2
✓ Branch 3 taken 1865 times.
✗ Branch 4 not taken.
1865 m_elementMat[0]->zero();
496
1/2
✓ Branch 4 taken 1865 times.
✗ Branch 5 not taken.
1865 m_elementMat[0]->grad_phi_j_dot_n_grad_psi_i_dot_n(gamma, *feWithBd, *feWithBd, idFaceToDo, idFaceToDo, 0, 0, this->dimension()); // block (0,0)
497
1/2
✓ Branch 1 taken 1865 times.
✗ Branch 2 not taken.
1865 setValueMatrixRHS(ielCurrentGlobalSup, ielCurrentGlobalSup, flag);
498
499 // current element for phi_i and opposite element for phi_j
500
1/2
✓ Branch 3 taken 1865 times.
✗ Branch 4 not taken.
1865 m_elementMat[0]->zero();
501
1/2
✓ Branch 4 taken 1865 times.
✗ Branch 5 not taken.
1865 m_elementMat[0]->grad_phi_j_dot_n_grad_psi_i_dot_n(gamma, *oppositeFEWithBd, *feWithBd, localIdFaceOpposite, idFaceToDo, 0, 0, this->dimension()); // block (0,0)
502
1/2
✓ Branch 1 taken 1865 times.
✗ Branch 2 not taken.
1865 setValueMatrixRHS(ielCurrentGlobalSup, ielOppositeGlobalSup, flag);
503
504 // opposite element for phi_i and current element for phi_j
505
1/2
✓ Branch 3 taken 1865 times.
✗ Branch 4 not taken.
1865 m_elementMat[0]->zero();
506
1/2
✓ Branch 4 taken 1865 times.
✗ Branch 5 not taken.
1865 m_elementMat[0]->grad_phi_j_dot_n_grad_psi_i_dot_n(gamma, *feWithBd, *oppositeFEWithBd, idFaceToDo, localIdFaceOpposite, 0, 0, this->dimension()); // block (0,0)
507
1/2
✓ Branch 1 taken 1865 times.
✗ Branch 2 not taken.
1865 setValueMatrixRHS(ielOppositeGlobalSup, ielCurrentGlobalSup, flag);
508
509 // opposite element for phi_i and phi_j
510
1/2
✓ Branch 3 taken 1865 times.
✗ Branch 4 not taken.
1865 m_elementMat[0]->zero();
511
1/2
✓ Branch 4 taken 1865 times.
✗ Branch 5 not taken.
1865 m_elementMat[0]->grad_phi_j_dot_n_grad_psi_i_dot_n(gamma, *oppositeFEWithBd, *oppositeFEWithBd, localIdFaceOpposite, localIdFaceOpposite, 0, 0, this->dimension()); // block (0,0)
512
1/2
✓ Branch 1 taken 1865 times.
✗ Branch 2 not taken.
1865 setValueMatrixRHS(ielOppositeGlobalSup, ielOppositeGlobalSup, flag);
513
514 // update the map to say that this face is done
515
2/4
✓ Branch 1 taken 1865 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1865 times.
✗ Branch 5 not taken.
1865 contribDone[ielCurrentGlobalGeo][idFaceToDo] = true;
516
517 // check if the opposite element is on this proc
518
2/2
✓ Branch 2 taken 1550 times.
✓ Branch 3 taken 315 times.
1865 if(m_eltPart[m_currentMesh][ielOppositeGlobalGeo] == rank) {
519
3/4
✓ Branch 2 taken 1550 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1185 times.
✓ Branch 6 taken 365 times.
1550 if(contribDone.find(ielOppositeGlobalGeo) == contribDone.end()) {
520 // not found in the map, add it and initialize it.
521
2/4
✓ Branch 1 taken 1185 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1185 times.
✗ Branch 5 not taken.
1185 addNewFaceOrientedContributor(numFacesPerType, ielOppositeGlobalGeo, contribDone[ielOppositeGlobalGeo]);
522 }
523
2/4
✓ Branch 1 taken 1550 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1550 times.
✗ Branch 5 not taken.
1550 contribDone[ielOppositeGlobalGeo][localIdFaceOpposite] = true;
524
525 // update the finite element as the opposite finite element.
526 1550 ptmp = feWithBd;
527 1550 feWithBd = oppositeFEWithBd;
528 1550 oppositeFEWithBd = ptmp;
529
530 1550 ielCurrentGlobalGeo = ielOppositeGlobalGeo;
531 1550 ielCurrentGlobalSup = ielOppositeGlobalSup;
532
1/2
✓ Branch 1 taken 1550 times.
✗ Branch 2 not taken.
1550 idOfFacesCurrent = idOfFacesOpposite;
533 }
534 else {
535 // not on this rank, take the next one in the stack
536
1/2
✓ Branch 1 taken 315 times.
✗ Branch 2 not taken.
315 if(!nextInStack.empty()) {
537 315 ielCurrentGlobalGeo = nextInStack.top();
538
1/2
✓ Branch 1 taken 315 times.
✗ Branch 2 not taken.
315 updateFaceOrientedFEWithBd(feWithBd, idOfFacesCurrent, numPointPerElt, ielCurrentGlobalGeo, ielCurrentGlobalSup);
539 }
540 }
541 }
542 else {
543 // All contribution have been already computed on this element
544 // take the next element in the stack
545
2/2
✓ Branch 1 taken 720 times.
✓ Branch 2 taken 20 times.
740 if(!nextInStack.empty()) {
546 720 ielCurrentGlobalGeo = nextInStack.top();
547
1/2
✓ Branch 1 taken 720 times.
✗ Branch 2 not taken.
720 updateFaceOrientedFEWithBd(feWithBd, idOfFacesCurrent, numPointPerElt, ielCurrentGlobalGeo, ielCurrentGlobalSup);
548 }
549 }
550 }
551
552 // desallocate array use for assemble with petsc.
553
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 desallocateArrayForAssembleMatrixRHS(flag);
554
555 // desallocate opposite finite elements
556 20 feWithBd = firstCurrentFe;
557
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 delete firstOppositeFe;
558 20 }
559
560 1205 void LinearProblemStokesContinuation::addNewFaceOrientedContributor(felInt size, felInt idElt, std::vector<bool>& vec) {
561 felInt ielTmp;
562 1205 std::pair<bool, GeometricMeshRegion::ElementType> adjElt;
563
564
1/2
✓ Branch 1 taken 1205 times.
✗ Branch 2 not taken.
1205 vec.resize(size, false);
565
2/2
✓ Branch 0 taken 3615 times.
✓ Branch 1 taken 1205 times.
4820 for(felInt iface=0; iface<size; ++iface) {
566 // check if this face is an inner face or a boundary
567 3615 ielTmp = idElt;
568
1/2
✓ Branch 3 taken 3615 times.
✗ Branch 4 not taken.
3615 adjElt =m_mesh[m_currentMesh]->getAdjElement(ielTmp, iface);
569
570
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 3415 times.
3615 if(!adjElt.first) {
571 // not an inner face, set the contribution to done.
572
1/2
✓ Branch 1 taken 200 times.
✗ Branch 2 not taken.
200 vec[iface] = true;
573 }
574 }
575 1205 }
576
577 2900 void LinearProblemStokesContinuation::updateFaceOrientedFEWithBd(CurrentFiniteElementWithBd* fe, std::vector<felInt>& idOfFaces, felInt numPoints, felInt idElt, felInt& idSup) {
578
1/2
✓ Branch 2 taken 2900 times.
✗ Branch 3 not taken.
2900 std::vector<felInt> elemIdPoint(numPoints, -1);
579
1/2
✓ Branch 2 taken 2900 times.
✗ Branch 3 not taken.
2900 std::vector<Point*> elemPoint(numPoints, NULL);
580
581 // get information on the opposite element
582 // same as the function "setElemPoint" but here ielOppositeGlobalGeo is global
583 // we assume that the supportDofMesh is the same for all unknown (like in setElemPoint)
584
1/2
✓ Branch 2 taken 2900 times.
✗ Branch 3 not taken.
2900 m_supportDofUnknown[0].getIdElementSupport(idElt, idSup);
585
1/2
✓ Branch 3 taken 2900 times.
✗ Branch 4 not taken.
2900 m_mesh[m_currentMesh]->getOneElement(idElt, elemIdPoint);
586
2/2
✓ Branch 0 taken 8700 times.
✓ Branch 1 taken 2900 times.
11600 for (felInt iPoint=0; iPoint<numPoints; ++iPoint)
587 8700 elemPoint[iPoint] = &(m_mesh[m_currentMesh]->listPoints()[elemIdPoint[iPoint]]);
588
589 // update the finite elements
590
1/2
✓ Branch 1 taken 2900 times.
✗ Branch 2 not taken.
2900 fe->updateFirstDeriv(0, elemPoint);
591
1/2
✓ Branch 1 taken 2900 times.
✗ Branch 2 not taken.
2900 fe->updateBdMeasNormal();
592
593 // get all the faces of the element
594
1/2
✓ Branch 1 taken 2900 times.
✗ Branch 2 not taken.
2900 if(dimension() == 2)
595
1/2
✓ Branch 3 taken 2900 times.
✗ Branch 4 not taken.
2900 m_mesh[m_currentMesh]->getAllEdgeOfElement(idElt, idOfFaces);
596 else
597 m_mesh[m_currentMesh]->getAllFaceOfElement(idElt, idOfFaces);
598 2900 }
599 }
600