Directory: | ./ |
---|---|
File: | Solver/linearProblemPoissonContinuation.cpp |
Date: | 2024-04-14 07:32:34 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 247 | 254 | 97.2% |
Branches: | 207 | 346 | 59.8% |
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/linearProblemPoissonContinuation.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 linearProblemPoisson.cpp | ||
30 | \date 17/02/2022 | ||
31 | \brief Continuation method for Poisson's equation | ||
32 | */ | ||
33 | namespace felisce { | ||
34 | 4 | LinearProblemPoissonContinuation::LinearProblemPoissonContinuation(): | |
35 |
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") |
36 | { | ||
37 | 4 | } | |
38 | |||
39 | 4 | void LinearProblemPoissonContinuation::readData(IO& io,double iteration) { | |
40 | // Read variable from file | ||
41 | 4 | std::vector<double> potData; | |
42 |
1/2✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | potData.resize(m_mesh[m_currentMesh]->numPoints(),0.); |
43 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | io.readVariable(0,iteration, potData.data(), potData.size()); |
44 | |||
45 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | m_potData.duplicateFrom(this->sequentialSolution()); |
46 | |||
47 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | std::vector<PetscInt> ao_potData( potData.size()); |
48 |
2/2✓ Branch 1 taken 568 times.
✓ Branch 2 taken 4 times.
|
572 | for (size_t i=0; i < potData.size(); ++i) { |
49 | 568 | ao_potData[i]=i; | |
50 | } | ||
51 | |||
52 |
1/2✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | AOApplicationToPetsc(this->ao(),potData.size(),ao_potData.data()); |
53 |
2/4✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
4 | VecSetValues(m_potData.toPetsc(),potData.size(),ao_potData.data(), potData.data(), INSERT_VALUES); |
54 | 4 | } | |
55 | |||
56 | 4 | void LinearProblemPoissonContinuation::initialize(std::vector<GeometricMeshRegion::Pointer>& mesh, FelisceTransient::Pointer fstransient, MPI_Comm& comm, bool doUseSNES) { | |
57 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | LinearProblem::initialize(mesh,comm, doUseSNES); |
58 | 4 | this->m_fstransient = fstransient; | |
59 | |||
60 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | std::vector<PhysicalVariable> listVariable(2); |
61 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | std::vector<size_t> listNumComp(2); |
62 | 4 | listVariable[0] = temperature; // primal variable, the discrete solution u_h | |
63 | 4 | listNumComp[0] = 1; | |
64 | 4 | listVariable[1] = potThorax; // dummy name for dual variable, the Langrange multiplier z_h | |
65 | 4 | listNumComp[1] = 1; | |
66 | |||
67 | //define unknown of the linear system. | ||
68 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | m_listUnknown.push_back(temperature); |
69 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | m_listUnknown.push_back(potThorax); |
70 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | definePhysicalVariable(listVariable,listNumComp); |
71 | |||
72 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | m_iTemperature = m_listVariable.getVariableIdList(temperature); |
73 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | m_iPotThorax = m_listVariable.getVariableIdList(potThorax); |
74 | 4 | } | |
75 | |||
76 | 8 | void LinearProblemPoissonContinuation::initPerElementType(ElementType /*eltType*/, FlagMatrixRHS /*flagMatrixRHS*/) { | |
77 | 8 | m_feTemp = m_listCurrentFiniteElement[m_iTemperature]; | |
78 | |||
79 | // initialize elemField to store the data | ||
80 | 8 | m_elemField.initialize(DOF_FIELD, *m_feTemp, 1); | |
81 | 8 | } | |
82 | |||
83 | 242 | void LinearProblemPoissonContinuation::computeElementArray(const std::vector<Point*>& elemPoint, const std::vector<felInt>& /*elemIdPoint*/, felInt& iel, FlagMatrixRHS flagMatrixRHS) { | |
84 | 242 | m_feTemp->updateFirstDeriv(0, elemPoint); | |
85 | |||
86 | 242 | const double gamma_M = FelisceParam::instance(this->instanceIndex()).referenceValue2; // data fidelity coefficient | |
87 | 242 | const int labelDataSubdomain = FelisceParam::instance(this->instanceIndex()).testCase; // label of the subdomain where data is given; 0 for the whole domain | |
88 | |||
89 | // defining the block matrix of the system | ||
90 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 242 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
242 | if (flagMatrixRHS == FlagMatrixRHS::matrix_and_rhs || flagMatrixRHS == FlagMatrixRHS::only_matrix) { |
91 | // block (0,0): gamma_M * int_\Omega_data u * v; in this block we will also add the cip stabilization | ||
92 |
1/2✓ Branch 0 taken 242 times.
✗ Branch 1 not taken.
|
242 | if (labelDataSubdomain == 0) { |
93 | 242 | m_elementMat[0]->phi_i_phi_j(gamma_M, *m_feTemp, 0, 0, 1); | |
94 | } | ||
95 | ✗ | else if (m_currentLabel == labelDataSubdomain) { | |
96 | ✗ | m_elementMat[0]->phi_i_phi_j(gamma_M, *m_feTemp, 0, 0, 1); | |
97 | } | ||
98 | |||
99 | // block (0,1): int_\Omega grad v . grad z | ||
100 | 242 | m_elementMat[0]->grad_phi_i_grad_phi_j(1., *m_feTemp, 0, 1, 1); | |
101 | |||
102 | // block (1,0): int_\Omega grad u . grad w | ||
103 | 242 | m_elementMat[0]->grad_phi_i_grad_phi_j(1., *m_feTemp, 1, 0, 1); | |
104 | |||
105 | // block (1,1): -int_\Omega grad z . grad w | ||
106 | 242 | m_elementMat[0]->grad_phi_i_grad_phi_j(-1., *m_feTemp, 1, 1, 1); | |
107 | } | ||
108 | |||
109 | // defining the rhs of the system | ||
110 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 242 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
242 | if (flagMatrixRHS == FlagMatrixRHS::matrix_and_rhs || flagMatrixRHS == FlagMatrixRHS::only_rhs) { |
111 | // assuming that f is zero | ||
112 | |||
113 | // rhs data term | ||
114 | 242 | m_elemField.setValue(m_potData, *m_feTemp, iel, m_iTemperature, m_ao, dof()); | |
115 |
1/2✓ Branch 0 taken 242 times.
✗ Branch 1 not taken.
|
242 | if (labelDataSubdomain == 0) { |
116 | 242 | m_elementVector[0]->source(gamma_M, *m_feTemp, m_elemField, 0, 1); | |
117 | } | ||
118 | ✗ | else if (m_currentLabel == labelDataSubdomain) { | |
119 | ✗ | m_elementVector[0]->source(gamma_M, *m_feTemp, m_elemField, 0, 1); | |
120 | } | ||
121 | } | ||
122 | 242 | } | |
123 | |||
124 | 4 | void LinearProblemPoissonContinuation::userChangePattern(int numProc, int rankProc) { | |
125 | IGNORE_UNUSED_ARGUMENT(numProc); | ||
126 | IGNORE_UNUSED_ARGUMENT(rankProc); | ||
127 | // compute initial (uniform) repartition of dof on processes | ||
128 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | felInt numDofByProc = m_numDof/MpiInfo::numProc(); |
129 |
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()); |
130 |
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) { |
131 |
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) |
132 | 4 | numDofPerProc[i] = m_numDof - i*numDofByProc; | |
133 | else | ||
134 | 12 | numDofPerProc[i] = numDofByProc; | |
135 | } | ||
136 | |||
137 | 4 | felInt shiftDof = 0; | |
138 |
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) |
139 | 6 | shiftDof += numDofPerProc[i]; | |
140 | |||
141 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | std::vector<felInt> rankDof(m_numDof, -1); |
142 |
3/4✓ Branch 1 taken 288 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 284 times.
✓ Branch 5 taken 4 times.
|
288 | for(felInt i=0; i<numDofPerProc[MpiInfo::rankProc()]; ++i) |
143 |
1/2✓ Branch 1 taken 284 times.
✗ Branch 2 not taken.
|
284 | rankDof[i + shiftDof] = MpiInfo::rankProc(); |
144 | |||
145 | // build the edges or faces depending on the dimension (for the global mesh) | ||
146 | // In this function, "faces" refers to either edges or faces. | ||
147 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | if(dimension() == 2) |
148 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | m_mesh[m_currentMesh]->buildEdges(); |
149 | else | ||
150 | ✗ | m_mesh[m_currentMesh]->buildFaces(); | |
151 | |||
152 | // variables | ||
153 | GeometricMeshRegion::ElementType eltType, eltTypeOpp; | ||
154 | felInt idVar1, idVar2; | ||
155 | felInt node1, node2; | ||
156 | felInt numFacesPerElement, numEltPerLabel; | ||
157 | felInt ielSupport, jelSupport; | ||
158 | felInt ielCurrentGeo, ielOppositeGeo; | ||
159 | 4 | std::vector<felInt> vecSupport, vecSupportOpposite; | |
160 |
1/2✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | std::vector<felInt> numElement(m_mesh[m_currentMesh]->m_numTypesOfElement, 0); |
161 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | std::vector< std::set<felInt> > nodesNeighborhood(m_numDof); |
162 | |||
163 | // zeroth loop on the unknown of the linear problem | ||
164 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 4 times.
|
12 | for (size_t iUnknown1 = 0; iUnknown1 < m_listUnknown.size(); ++iUnknown1) { |
165 | 8 | idVar1 = m_listUnknown.idVariable(iUnknown1); | |
166 | |||
167 | 8 | ielCurrentGeo = 0; | |
168 | |||
169 | // first loop on element type | ||
170 |
2/2✓ Branch 4 taken 8 times.
✓ Branch 5 taken 8 times.
|
16 | for (size_t i=0; i<m_mesh[m_currentMesh]->bagElementTypeDomain().size(); ++i) { |
171 | 8 | eltType = m_mesh[m_currentMesh]->bagElementTypeDomain()[i]; | |
172 | 8 | const GeoElement* geoEle = GeometricMeshRegion::eltEnumToFelNameGeoEle[eltType].second; | |
173 | 8 | numElement[eltType] = 0; | |
174 | 8 | numFacesPerElement = geoEle->numBdEle(); | |
175 | |||
176 | // second loop on region of the mesh. | ||
177 |
2/2✓ Branch 10 taken 8 times.
✓ Branch 11 taken 8 times.
|
16 | for(GeometricMeshRegion::IntRefToBegEndIndex_type::const_iterator itRef =m_mesh[m_currentMesh]->intRefToBegEndMaps[eltType].begin(); itRef !=m_mesh[m_currentMesh]->intRefToBegEndMaps[eltType].end(); itRef++) { |
178 | 8 | numEltPerLabel = itRef->second.second; | |
179 | |||
180 | // Third loop on element | ||
181 |
2/2✓ Branch 0 taken 1936 times.
✓ Branch 1 taken 8 times.
|
1944 | for (felInt iel = 0; iel < numEltPerLabel; iel++) { |
182 |
1/2✓ Branch 3 taken 1936 times.
✗ Branch 4 not taken.
|
1936 | m_supportDofUnknown[iUnknown1].getIdElementSupport(eltType, numElement[eltType], vecSupport); |
183 | |||
184 |
2/2✓ Branch 1 taken 1936 times.
✓ Branch 2 taken 1936 times.
|
3872 | for(size_t ielSup=0; ielSup<vecSupport.size(); ++ielSup) { |
185 | 1936 | ielSupport = vecSupport[ielSup]; | |
186 | |||
187 | // for all support dof in this support element | ||
188 |
2/2✓ Branch 2 taken 5808 times.
✓ Branch 3 taken 1936 times.
|
7744 | for (felInt iSup = 0; iSup < m_supportDofUnknown[iUnknown1].getNumSupportDof(ielSupport); ++iSup) { |
189 | // for all component of the unknown | ||
190 |
2/2✓ Branch 2 taken 5808 times.
✓ Branch 3 taken 5808 times.
|
11616 | for (size_t iComp = 0; iComp < m_listVariable[idVar1].numComponent(); iComp++) { |
191 | // get the global id of the support dof | ||
192 |
1/2✓ Branch 2 taken 5808 times.
✗ Branch 3 not taken.
|
5808 | dof().loc2glob(ielSupport, iSup, idVar1, iComp, node1); |
193 | |||
194 | // if this node is on this process | ||
195 |
3/4✓ Branch 2 taken 5808 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1452 times.
✓ Branch 5 taken 4356 times.
|
5808 | if(rankDof[node1] == MpiInfo::rankProc()) { |
196 | // loop over the boundaries of the element | ||
197 |
2/2✓ Branch 0 taken 4356 times.
✓ Branch 1 taken 1452 times.
|
5808 | for(felInt iface=0; iface < numFacesPerElement; ++iface) { |
198 | // check if this face is an inner face or a boundary | ||
199 | 4356 | ielOppositeGeo = ielCurrentGeo; | |
200 | 4356 | eltTypeOpp = eltType; | |
201 |
1/2✓ Branch 3 taken 4356 times.
✗ Branch 4 not taken.
|
4356 | bool isAnInnerFace =m_mesh[m_currentMesh]->getAdjElement(eltTypeOpp, ielOppositeGeo, iface); |
202 | |||
203 |
2/2✓ Branch 0 taken 4116 times.
✓ Branch 1 taken 240 times.
|
4356 | if(isAnInnerFace) { |
204 | // for all unknown | ||
205 |
2/2✓ Branch 1 taken 8232 times.
✓ Branch 2 taken 4116 times.
|
12348 | for (size_t iUnknown2 = 0; iUnknown2 < m_listUnknown.size(); ++iUnknown2) { |
206 | 8232 | idVar2 = m_listUnknown.idVariable(iUnknown2); | |
207 | |||
208 | // get the support element of the opposite element | ||
209 |
1/2✓ Branch 2 taken 8232 times.
✗ Branch 3 not taken.
|
8232 | m_supportDofUnknown[iUnknown2].getIdElementSupport(ielOppositeGeo, vecSupportOpposite); |
210 | |||
211 | // for all support element | ||
212 |
2/2✓ Branch 1 taken 8232 times.
✓ Branch 2 taken 8232 times.
|
16464 | for(size_t jelSup=0; jelSup<vecSupportOpposite.size(); ++jelSup) { |
213 | 8232 | jelSupport = vecSupportOpposite[jelSup]; | |
214 | |||
215 | // for all support dof in this support element | ||
216 |
2/2✓ Branch 2 taken 24696 times.
✓ Branch 3 taken 8232 times.
|
32928 | for (felInt jSup = 0; jSup < m_supportDofUnknown[iUnknown2].getNumSupportDof(jelSupport); ++jSup) { |
217 | |||
218 | // for all component of the second unknown | ||
219 |
2/2✓ Branch 2 taken 24696 times.
✓ Branch 3 taken 24696 times.
|
49392 | for (size_t jComp = 0; jComp < m_listVariable[idVar2].numComponent(); jComp++) { |
220 | |||
221 | // If the two current components are connected | ||
222 |
1/2✓ Branch 2 taken 24696 times.
✗ Branch 3 not taken.
|
24696 | felInt iConnect = dof().getNumGlobComp(iUnknown1, iComp); |
223 |
1/2✓ Branch 2 taken 24696 times.
✗ Branch 3 not taken.
|
24696 | felInt jConnect = dof().getNumGlobComp(iUnknown2, jComp); |
224 |
2/4✓ Branch 2 taken 24696 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 24696 times.
✗ Branch 5 not taken.
|
24696 | if (m_listUnknown.mask()(iConnect, jConnect) > 0) { |
225 | // get the global id of the second support dof | ||
226 |
1/2✓ Branch 2 taken 24696 times.
✗ Branch 3 not taken.
|
24696 | dof().loc2glob(jelSupport, jSup, idVar2, jComp, node2); |
227 | |||
228 | // remove diagonal term to define pattern and use it in Parmetis. | ||
229 | // if the two global ids are different, they are neighboors | ||
230 |
2/2✓ Branch 0 taken 21952 times.
✓ Branch 1 taken 2744 times.
|
24696 | if(node1 != node2) |
231 |
1/2✓ Branch 2 taken 21952 times.
✗ Branch 3 not taken.
|
21952 | nodesNeighborhood[node1].insert(node2); |
232 | } | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | 1936 | ++ielCurrentGeo; | |
244 | 1936 | ++numElement[eltType]; | |
245 | } | ||
246 | } | ||
247 | } | ||
248 | } | ||
249 | |||
250 | // Store the pattern in CSR style | ||
251 | 4 | std::vector<felInt> iCSR, jCSR; | |
252 | 4 | felInt dofSize = 0; | |
253 | 4 | felInt cptDof = 0; | |
254 | felInt pos; | ||
255 | |||
256 |
1/2✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | iCSR.resize(dof().pattern().numRows() + 1, 0); |
257 |
2/2✓ Branch 1 taken 1136 times.
✓ Branch 2 taken 4 times.
|
1140 | for(size_t iNode=0; iNode<nodesNeighborhood.size(); ++iNode) |
258 | 1136 | dofSize += nodesNeighborhood[iNode].size(); | |
259 | |||
260 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | jCSR.resize(dofSize, 0); |
261 |
2/2✓ Branch 1 taken 1136 times.
✓ Branch 2 taken 4 times.
|
1140 | for(size_t iNode=0; iNode<nodesNeighborhood.size(); ++iNode) { |
262 |
3/4✓ Branch 2 taken 1136 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 284 times.
✓ Branch 5 taken 852 times.
|
1136 | if(rankDof[iNode] == MpiInfo::rankProc()) { |
263 | 284 | iCSR[cptDof + 1] = iCSR[cptDof] + nodesNeighborhood[iNode].size(); | |
264 | 284 | pos = 0; | |
265 |
2/2✓ Branch 5 taken 6028 times.
✓ Branch 6 taken 284 times.
|
6312 | for(std::set<felInt>::iterator it=nodesNeighborhood[iNode].begin(); it != nodesNeighborhood[iNode].end(); ++it) { |
266 | 6028 | jCSR[iCSR[cptDof] + pos] = *it; | |
267 | 6028 | ++pos; | |
268 | } | ||
269 | 284 | ++cptDof; | |
270 | } | ||
271 | } | ||
272 | |||
273 | // Now, call merge pattern | ||
274 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | dof().mergeGlobalPattern(iCSR, jCSR); |
275 | 4 | } | |
276 | |||
277 | 4 | void LinearProblemPoissonContinuation::assembleFaceOrientedStabilization() { | |
278 | // definition of variables | ||
279 | 4 | std::pair<bool, GeometricMeshRegion::ElementType> adjElt; | |
280 | GeometricMeshRegion::ElementType eltType; // Type of element | ||
281 | |||
282 | 4 | felInt ielCurrentLocalGeo = 0; // local geometric id of the current element | |
283 | 4 | felInt ielCurrentGlobalGeo = 0; // global geometric id of the current element | |
284 | 4 | felInt ielOppositeGlobalGeo = 0; // global geometric id of the opposite element | |
285 | felInt numFacesPerType; // number of faces of an element of a given type | ||
286 | felInt numPointPerElt; // number of vertices by element | ||
287 | felInt ielCurrentGlobalSup; // global support element id of the current element | ||
288 | felInt ielOppositeGlobalSup; // global support element id of the opposite element | ||
289 | |||
290 | 4 | std::vector<felInt> idOfFacesCurrent; // ids of the current element edges | |
291 | 4 | std::vector<felInt> idOfFacesOpposite; // ids of the opposite element edges | |
292 | 4 | std::vector<felInt> currentElemIdPoint; // ids of the vertices of the current element | |
293 | 4 | std::vector<felInt> oppositeElemIdPoint; // ids of the vertices of the opposite element | |
294 | 4 | std::vector<Point*> currentElemPoint; // point coordinates of the current element vertices | |
295 | 4 | std::vector<Point*> oppositeElemPoint; // point coordinates of the opposite element vertices | |
296 | |||
297 | 4 | FlagMatrixRHS flag = FlagMatrixRHS::only_matrix; // flag to only assemble the matrix | |
298 | felInt idFaceToDo; | ||
299 | 4 | bool allDone = false; | |
300 | |||
301 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | ElementField elemFieldAdvFace; |
302 | |||
303 | felInt rank; | ||
304 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | MPI_Comm_rank(PETSC_COMM_WORLD, &rank); |
305 | |||
306 | // bag element type vector | ||
307 | 4 | const std::vector<ElementType>& bagElementTypeDomain = m_meshLocal[m_currentMesh]->bagElementTypeDomain(); | |
308 | 4 | eltType = bagElementTypeDomain[0]; | |
309 | |||
310 | |||
311 | // Finite Element With Bd for the opposite element | ||
312 | CurrentFiniteElementWithBd* ptmp; | ||
313 | CurrentFiniteElementWithBd* oppositeFEWithBd; | ||
314 | |||
315 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | m_temperature = &m_listVariable[m_listVariable.getVariableIdList(temperature)]; |
316 | |||
317 | 4 | const GeoElement *geoEle = m_mesh[m_currentMesh]->eltEnumToFelNameGeoEle[eltType].second; | |
318 | 4 | felInt typeOfFEVel = m_temperature->finiteElementType(); | |
319 | |||
320 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | const RefElement *refEleVel = geoEle->defineFiniteEle(eltType, typeOfFEVel, *m_mesh[m_currentMesh]); |
321 |
2/4✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
4 | oppositeFEWithBd = new CurrentFiniteElementWithBd(*refEleVel, *geoEle, m_temperature->degreeOfExactness(), m_temperature->degreeOfExactness()); |
322 | |||
323 | // initializing variables | ||
324 | 4 | numPointPerElt = m_meshLocal[m_currentMesh]->m_numPointsPerElt[eltType]; | |
325 | 4 | numFacesPerType = GeometricMeshRegion::eltEnumToFelNameGeoEle[eltType].second->numBdEle(); | |
326 | |||
327 | // resize of vectors | ||
328 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | idOfFacesCurrent.resize(numFacesPerType, -1); |
329 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | idOfFacesOpposite.resize(numFacesPerType, -1); |
330 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | currentElemIdPoint.resize(numPointPerElt, -1); |
331 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | oppositeElemIdPoint.resize(numPointPerElt, -1); |
332 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | currentElemPoint.resize(numPointPerElt, NULL); |
333 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | oppositeElemPoint.resize(numPointPerElt, NULL); |
334 | |||
335 | // define finite element | ||
336 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | defineFiniteElement(eltType); |
337 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | initElementArray(); |
338 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | defineCurrentFiniteElementWithBd(eltType); |
339 | |||
340 | // allocate arrays for assembling the matrix | ||
341 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | allocateArrayForAssembleMatrixRHS(flag); |
342 | |||
343 | // init variables | ||
344 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | initPerElementType(eltType, flag); |
345 | 4 | CurrentFiniteElementWithBd* feWithBd = m_listCurrentFiniteElementWithBd[m_iTemperature]; | |
346 | |||
347 | 4 | CurrentFiniteElementWithBd* firstCurrentFe = feWithBd; | |
348 | 4 | CurrentFiniteElementWithBd* firstOppositeFe = oppositeFEWithBd; | |
349 | |||
350 | // get informations on the current element | ||
351 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | setElemPoint(eltType, 0, currentElemPoint, currentElemIdPoint, &ielCurrentGlobalSup); |
352 | |||
353 | // update the finite elements | ||
354 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | feWithBd->updateFirstDeriv(0, currentElemPoint); |
355 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | feWithBd->updateBdMeasNormal(); |
356 | |||
357 | // get the global id of the first geometric element | ||
358 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | ISLocalToGlobalMappingApply(m_mappingElem[m_currentMesh], 1, &ielCurrentLocalGeo, &ielCurrentGlobalGeo); |
359 | |||
360 | // the map to remember what contribution have already been computed | ||
361 | 4 | std::map<felInt, std::vector<bool> > contribDone; | |
362 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | addNewFaceOrientedContributor(numFacesPerType, ielCurrentGlobalGeo, contribDone[ielCurrentGlobalGeo]); |
363 | |||
364 | // build the stack to know what is the next element | ||
365 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | std::stack<felInt> nextInStack; |
366 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | nextInStack.push(ielCurrentGlobalGeo); |
367 | |||
368 | // get all the faces of the element | ||
369 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | if(dimension() == 2) |
370 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | m_mesh[m_currentMesh]->getAllEdgeOfElement(ielCurrentGlobalGeo, idOfFacesCurrent); |
371 | else | ||
372 | ✗ | m_mesh[m_currentMesh]->getAllFaceOfElement(ielCurrentGlobalGeo, idOfFacesCurrent); | |
373 | |||
374 | // loop over all the element (snake style) | ||
375 |
2/2✓ Branch 1 taken 530 times.
✓ Branch 2 taken 4 times.
|
534 | while(!nextInStack.empty()) { |
376 | // check the faces and use the first one that is an inner face and that has not been done yet. | ||
377 | 530 | idFaceToDo = -1; | |
378 | 530 | allDone = true; | |
379 |
3/4✓ Branch 1 taken 2120 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1590 times.
✓ Branch 5 taken 530 times.
|
2120 | for(size_t iface=0; iface<contribDone[ielCurrentGlobalGeo].size(); ++iface) { |
380 |
4/6✓ Branch 1 taken 1590 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1590 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 577 times.
✓ Branch 8 taken 1013 times.
|
1590 | if(!contribDone[ielCurrentGlobalGeo][iface]) { |
381 | // This is an inner face, check if the contribution has already been computed or not | ||
382 |
2/2✓ Branch 0 taken 370 times.
✓ Branch 1 taken 207 times.
|
577 | if(idFaceToDo == -1) { |
383 | 370 | idFaceToDo = iface; | |
384 | } else { | ||
385 | 207 | allDone = false; | |
386 | } | ||
387 | } | ||
388 | } | ||
389 | |||
390 | // update the stack | ||
391 |
2/2✓ Branch 0 taken 206 times.
✓ Branch 1 taken 324 times.
|
530 | if(!allDone) |
392 |
1/2✓ Branch 1 taken 206 times.
✗ Branch 2 not taken.
|
206 | nextInStack.push(ielCurrentGlobalGeo); |
393 | |||
394 |
6/6✓ Branch 1 taken 416 times.
✓ Branch 2 taken 114 times.
✓ Branch 3 taken 210 times.
✓ Branch 4 taken 206 times.
✓ Branch 5 taken 210 times.
✓ Branch 6 taken 320 times.
|
530 | if(nextInStack.top() == ielCurrentGlobalGeo && allDone) |
395 | 210 | nextInStack.pop(); | |
396 | |||
397 | |||
398 | // assemble terms | ||
399 |
2/2✓ Branch 0 taken 370 times.
✓ Branch 1 taken 160 times.
|
530 | if(idFaceToDo != -1) { |
400 | // get the opposite id of the element | ||
401 | 370 | ielOppositeGlobalGeo = ielCurrentGlobalGeo; | |
402 |
1/2✓ Branch 3 taken 370 times.
✗ Branch 4 not taken.
|
370 | adjElt =m_mesh[m_currentMesh]->getAdjElement(ielOppositeGlobalGeo, idFaceToDo); |
403 | |||
404 | // get the type of the opposite element | ||
405 | // eltTypeOpp = adjElt.second; | ||
406 | |||
407 | // update the opposite finite element and set ielOppositeGlobalSup | ||
408 |
1/2✓ Branch 1 taken 370 times.
✗ Branch 2 not taken.
|
370 | updateFaceOrientedFEWithBd(oppositeFEWithBd, idOfFacesOpposite, numPointPerElt, ielOppositeGlobalGeo, ielOppositeGlobalSup); |
409 | |||
410 | // find the local id of the edge in the opposite element | ||
411 | 370 | felInt localIdFaceOpposite = -1; | |
412 |
2/2✓ Branch 1 taken 1110 times.
✓ Branch 2 taken 370 times.
|
1480 | for(size_t jface=0; jface<idOfFacesOpposite.size(); ++jface) { |
413 |
2/2✓ Branch 2 taken 370 times.
✓ Branch 3 taken 740 times.
|
1110 | if(idOfFacesCurrent[idFaceToDo] == idOfFacesOpposite[jface]) { |
414 | 370 | localIdFaceOpposite = jface; | |
415 | } | ||
416 | } | ||
417 | |||
418 | // compute coefficients | ||
419 |
1/2✓ Branch 1 taken 370 times.
✗ Branch 2 not taken.
|
370 | const CurvilinearFiniteElement* curvFe = &feWithBd->bdEle(idFaceToDo); |
420 | //CurvilinearFiniteElement* curvFeOP = &oppositeFEWithBd->bdEle(localIdFaceOpposite); | ||
421 |
1/2✓ Branch 1 taken 370 times.
✗ Branch 2 not taken.
|
370 | double hK = curvFe->diameter(); //0.5 * (feWithBd->diameter() + oppositeFEWithBd->diameter()); |
422 |
2/4✓ Branch 1 taken 370 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 370 times.
✗ Branch 5 not taken.
|
370 | const double gamma_u = FelisceParam::instance(this->instanceIndex()).referenceValue1; // cip stabilization parameter |
423 | 370 | double gamma = hK*gamma_u; | |
424 | |||
425 | // We can now compute all the integrals. | ||
426 | // current element for phi_i and phi_j | ||
427 |
1/2✓ Branch 3 taken 370 times.
✗ Branch 4 not taken.
|
370 | m_elementMat[0]->zero(); |
428 |
1/2✓ Branch 3 taken 370 times.
✗ Branch 4 not taken.
|
370 | m_elementMat[0]->grad_phi_j_dot_n_grad_psi_i_dot_n(gamma, *feWithBd, *feWithBd, idFaceToDo, idFaceToDo, 0, 0, 1); // block (0,0) |
429 |
1/2✓ Branch 1 taken 370 times.
✗ Branch 2 not taken.
|
370 | setValueMatrixRHS(ielCurrentGlobalSup, ielCurrentGlobalSup, flag); |
430 | |||
431 | // current element for phi_i and opposite element for phi_j | ||
432 |
1/2✓ Branch 3 taken 370 times.
✗ Branch 4 not taken.
|
370 | m_elementMat[0]->zero(); |
433 |
1/2✓ Branch 3 taken 370 times.
✗ Branch 4 not taken.
|
370 | m_elementMat[0]->grad_phi_j_dot_n_grad_psi_i_dot_n(gamma, *oppositeFEWithBd, *feWithBd, localIdFaceOpposite, idFaceToDo, 0, 0, 1); // block (0,0) |
434 |
1/2✓ Branch 1 taken 370 times.
✗ Branch 2 not taken.
|
370 | setValueMatrixRHS(ielCurrentGlobalSup, ielOppositeGlobalSup, flag); |
435 | |||
436 | // opposite element for phi_i and current element for phi_j | ||
437 |
1/2✓ Branch 3 taken 370 times.
✗ Branch 4 not taken.
|
370 | m_elementMat[0]->zero(); |
438 |
1/2✓ Branch 3 taken 370 times.
✗ Branch 4 not taken.
|
370 | m_elementMat[0]->grad_phi_j_dot_n_grad_psi_i_dot_n(gamma, *feWithBd, *oppositeFEWithBd, idFaceToDo, localIdFaceOpposite, 0, 0, 1); // block (0,0) |
439 |
1/2✓ Branch 1 taken 370 times.
✗ Branch 2 not taken.
|
370 | setValueMatrixRHS(ielOppositeGlobalSup, ielCurrentGlobalSup, flag); |
440 | |||
441 | // opposite element for phi_i and phi_j | ||
442 |
1/2✓ Branch 3 taken 370 times.
✗ Branch 4 not taken.
|
370 | m_elementMat[0]->zero(); |
443 |
1/2✓ Branch 3 taken 370 times.
✗ Branch 4 not taken.
|
370 | m_elementMat[0]->grad_phi_j_dot_n_grad_psi_i_dot_n(gamma, *oppositeFEWithBd, *oppositeFEWithBd, localIdFaceOpposite, localIdFaceOpposite, 0, 0, 1); // block (0,0) |
444 |
1/2✓ Branch 1 taken 370 times.
✗ Branch 2 not taken.
|
370 | setValueMatrixRHS(ielOppositeGlobalSup, ielOppositeGlobalSup, flag); |
445 | |||
446 | // update the map to say that this face is done | ||
447 |
2/4✓ Branch 1 taken 370 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 370 times.
✗ Branch 5 not taken.
|
370 | contribDone[ielCurrentGlobalGeo][idFaceToDo] = true; |
448 | |||
449 | // check if the opposite element is on this proc | ||
450 |
2/2✓ Branch 2 taken 316 times.
✓ Branch 3 taken 54 times.
|
370 | if(m_eltPart[m_currentMesh][ielOppositeGlobalGeo] == rank) { |
451 |
3/4✓ Branch 2 taken 316 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 238 times.
✓ Branch 6 taken 78 times.
|
316 | if(contribDone.find(ielOppositeGlobalGeo) == contribDone.end()) { |
452 | // not found in the map, add it and initialize it. | ||
453 |
2/4✓ Branch 1 taken 238 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 238 times.
✗ Branch 5 not taken.
|
238 | addNewFaceOrientedContributor(numFacesPerType, ielOppositeGlobalGeo, contribDone[ielOppositeGlobalGeo]); |
454 | } | ||
455 |
2/4✓ Branch 1 taken 316 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 316 times.
✗ Branch 5 not taken.
|
316 | contribDone[ielOppositeGlobalGeo][localIdFaceOpposite] = true; |
456 | |||
457 | // update the finite element as the opposite finite element. | ||
458 | 316 | ptmp = feWithBd; | |
459 | 316 | feWithBd = oppositeFEWithBd; | |
460 | 316 | oppositeFEWithBd = ptmp; | |
461 | |||
462 | 316 | ielCurrentGlobalGeo = ielOppositeGlobalGeo; | |
463 | 316 | ielCurrentGlobalSup = ielOppositeGlobalSup; | |
464 |
1/2✓ Branch 1 taken 316 times.
✗ Branch 2 not taken.
|
316 | idOfFacesCurrent = idOfFacesOpposite; |
465 | } | ||
466 | else { | ||
467 | // not on this rank, take the next one in the stack | ||
468 |
1/2✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
|
54 | if(!nextInStack.empty()) { |
469 | 54 | ielCurrentGlobalGeo = nextInStack.top(); | |
470 |
1/2✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
|
54 | updateFaceOrientedFEWithBd(feWithBd, idOfFacesCurrent, numPointPerElt, ielCurrentGlobalGeo, ielCurrentGlobalSup); |
471 | } | ||
472 | } | ||
473 | } | ||
474 | else { | ||
475 | // All contribution have been already computed on this element | ||
476 | // take the next element in the stack | ||
477 |
2/2✓ Branch 1 taken 156 times.
✓ Branch 2 taken 4 times.
|
160 | if(!nextInStack.empty()) { |
478 | 156 | ielCurrentGlobalGeo = nextInStack.top(); | |
479 |
1/2✓ Branch 1 taken 156 times.
✗ Branch 2 not taken.
|
156 | updateFaceOrientedFEWithBd(feWithBd, idOfFacesCurrent, numPointPerElt, ielCurrentGlobalGeo, ielCurrentGlobalSup); |
480 | } | ||
481 | } | ||
482 | } | ||
483 | |||
484 | // desallocate array use for assemble with petsc. | ||
485 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | desallocateArrayForAssembleMatrixRHS(flag); |
486 | |||
487 | // desallocate opposite finite elements | ||
488 | 4 | feWithBd = firstCurrentFe; | |
489 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | delete firstOppositeFe; |
490 | 4 | } | |
491 | |||
492 | 242 | void LinearProblemPoissonContinuation::addNewFaceOrientedContributor(felInt size, felInt idElt, std::vector<bool>& vec) { | |
493 | felInt ielTmp; | ||
494 | 242 | std::pair<bool, GeometricMeshRegion::ElementType> adjElt; | |
495 | |||
496 |
1/2✓ Branch 1 taken 242 times.
✗ Branch 2 not taken.
|
242 | vec.resize(size, false); |
497 |
2/2✓ Branch 0 taken 726 times.
✓ Branch 1 taken 242 times.
|
968 | for(felInt iface=0; iface<size; ++iface) { |
498 | // check if this face is an inner face or a boundary | ||
499 | 726 | ielTmp = idElt; | |
500 |
1/2✓ Branch 3 taken 726 times.
✗ Branch 4 not taken.
|
726 | adjElt = m_mesh[m_currentMesh]->getAdjElement(ielTmp, iface); |
501 | |||
502 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 686 times.
|
726 | if(!adjElt.first) { |
503 | // not an inner face, set the contribution to done. | ||
504 |
1/2✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
|
40 | vec[iface] = true; |
505 | } | ||
506 | } | ||
507 | 242 | } | |
508 | |||
509 | 580 | void LinearProblemPoissonContinuation::updateFaceOrientedFEWithBd(CurrentFiniteElementWithBd* fe, std::vector<felInt>& idOfFaces, felInt numPoints, felInt idElt, felInt& idSup) { | |
510 |
1/2✓ Branch 2 taken 580 times.
✗ Branch 3 not taken.
|
580 | std::vector<felInt> elemIdPoint(numPoints, -1); |
511 |
1/2✓ Branch 2 taken 580 times.
✗ Branch 3 not taken.
|
580 | std::vector<Point*> elemPoint(numPoints, NULL); |
512 | |||
513 | // get information on the opposite element | ||
514 | // same as the function "setElemPoint" but here ielOppositeGlobalGeo is global | ||
515 | // we assume that the supportDofMesh is the same for all unknown (like in setElemPoint) | ||
516 |
1/2✓ Branch 2 taken 580 times.
✗ Branch 3 not taken.
|
580 | m_supportDofUnknown[0].getIdElementSupport(idElt, idSup); |
517 |
1/2✓ Branch 3 taken 580 times.
✗ Branch 4 not taken.
|
580 | m_mesh[m_currentMesh]->getOneElement(idElt, elemIdPoint); |
518 |
2/2✓ Branch 0 taken 1740 times.
✓ Branch 1 taken 580 times.
|
2320 | for (felInt iPoint=0; iPoint<numPoints; ++iPoint) |
519 | 1740 | elemPoint[iPoint] = &(m_mesh[m_currentMesh]->listPoints()[elemIdPoint[iPoint]]); | |
520 | |||
521 | // update the finite elements | ||
522 |
1/2✓ Branch 1 taken 580 times.
✗ Branch 2 not taken.
|
580 | fe->updateFirstDeriv(0, elemPoint); |
523 |
1/2✓ Branch 1 taken 580 times.
✗ Branch 2 not taken.
|
580 | fe->updateBdMeasNormal(); |
524 | |||
525 | // get all the faces of the element | ||
526 |
1/2✓ Branch 1 taken 580 times.
✗ Branch 2 not taken.
|
580 | if(dimension() == 2) |
527 |
1/2✓ Branch 3 taken 580 times.
✗ Branch 4 not taken.
|
580 | m_mesh[m_currentMesh]->getAllEdgeOfElement(idElt, idOfFaces); |
528 | else | ||
529 | ✗ | m_mesh[m_currentMesh]->getAllFaceOfElement(idElt, idOfFaces); | |
530 | 580 | } | |
531 | } | ||
532 |