Directory: | ./ |
---|---|
File: | Model/immersed.cpp |
Date: | 2024-04-14 07:32:34 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 135 | 260 | 51.9% |
Branches: | 110 | 476 | 23.1% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | // ______ ______ _ _ _____ ______ | ||
2 | // | ____| ____| | (_)/ ____| | ____| | ||
3 | // | |__ | |__ | | _| (___ ___| |__ | ||
4 | // | __| | __| | | | |\___ \ / __| __| | ||
5 | // | | | |____| |____| |____) | (__| |____ | ||
6 | // |_| |______|______|_|_____/ \___|______| | ||
7 | // Finite Elements for Life Sciences and Engineering | ||
8 | // | ||
9 | // License: LGL2.1 License | ||
10 | // FELiScE default license: LICENSE in root folder | ||
11 | // | ||
12 | // Main authors: M. Fernandez & L. Boilevin-Kayl | ||
13 | // | ||
14 | |||
15 | // System includes | ||
16 | |||
17 | // External includes | ||
18 | |||
19 | // Project includes | ||
20 | #include "Model/immersed.hpp" | ||
21 | #include "InputOutput/io.hpp" | ||
22 | |||
23 | namespace felisce | ||
24 | { | ||
25 | 42 | Immersed::Immersed() { | |
26 | |||
27 | 42 | m_intfDisp = nullptr; | |
28 | 42 | m_intfVelo = nullptr; | |
29 | 42 | m_intfForc = nullptr; | |
30 | 42 | m_velFluid = nullptr; | |
31 | 42 | m_indexTime = 0; | |
32 | |||
33 |
1/2✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
|
42 | m_allowProjection = FelisceParam::instance().allowProjectionImmersedStruct; |
34 | 42 | } | |
35 | |||
36 | 42 | Immersed::~Immersed() = default; | |
37 | |||
38 | 8 | void Immersed::initialize(GeometricMeshRegion::Pointer backMesh){ | |
39 | |||
40 | 8 | m_backMesh = backMesh; | |
41 | |||
42 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 6 times.
|
8 | if ( MpiInfo::rankProc() == 0 ) { // only the first processor possesses the full immersed mesh and will be responsible for the interpolation |
43 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m_readInterfaceMesh(); // read the immersed structure mesh and put it into m_interfMesh |
44 | |||
45 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | const int verbose = FelisceParam::verbose(); |
46 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | const double tolrescaling = FelisceParam::instance().Geo.tolrescaling; |
47 | |||
48 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | m_interpolator = felisce::make_shared<Interpolator>(m_backMesh.get(), m_allowProjection, tolrescaling, verbose); |
49 |
1/2✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
2 | m_intersector = felisce::make_shared<Intersector>(m_backMesh.get(), m_interfMesh.get(), tolrescaling, verbose); |
50 | } | ||
51 | |||
52 | 8 | MPI_Bcast(&m_nbPoints, 1, MPI_INT, 0, MpiInfo::petscComm()); | |
53 | 8 | MPI_Bcast(&m_nbCoor, 1, MPI_INT, 0, MpiInfo::petscComm()); | |
54 | 8 | } | |
55 | |||
56 | 8 | void Immersed::setInterfaceExchangedData( | |
57 | std::vector<double>* intfDisp, | ||
58 | std::vector<double>* intfVelo, | ||
59 | std::vector<double>* intfForc, | ||
60 | std::vector<double>* velFluid | ||
61 | ) { | ||
62 | |||
63 | 8 | m_intfDisp = intfDisp; | |
64 | 8 | m_intfVelo = intfVelo; | |
65 | 8 | m_intfForc = intfForc; | |
66 | 8 | m_velFluid = velFluid; | |
67 | |||
68 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | m_intfDisp->resize(m_nbCoor*m_nbPoints,0.); |
69 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | m_intfVelo->resize(m_nbCoor*m_nbPoints,0.); |
70 | 8 | } | |
71 | |||
72 | 320 | void Immersed::updateInterface(GeometricMeshRegion& mesh) { | |
73 | |||
74 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 320 times.
|
320 | FEL_CHECK(m_nbPoints != 0,"Empty list of immersed points"); |
75 | |||
76 |
2/2✓ Branch 1 taken 80 times.
✓ Branch 2 taken 240 times.
|
320 | if ( MpiInfo::rankProc() == 0 ) { |
77 | // WARNING: the interpolation only works so far for tetrahedral (in 3D) and triangular (in 2D) meshes | ||
78 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 78 times.
|
80 | if ( m_nbVertices == 0 ) { |
79 | 2 | m_nbVertices = mesh.domainDim()+1; // number of coordinates = dimension + 1 | |
80 | } | ||
81 | |||
82 | // update interface points | ||
83 |
2/2✓ Branch 0 taken 1750 times.
✓ Branch 1 taken 80 times.
|
1830 | for (int l = 0; l < m_nbPoints; ++l) { |
84 |
2/2✓ Branch 0 taken 3500 times.
✓ Branch 1 taken 1750 times.
|
5250 | for (int ic = 0; ic < m_nbCoor; ++ic) |
85 | 3500 | m_listPoints[l].coor(ic) = m_listPointsRef[l].coor(ic) + (*m_intfDisp)[ic+l*m_nbCoor]; | |
86 | } | ||
87 | |||
88 | // update the mesh with m_intfDisp | ||
89 |
1/2✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
|
80 | m_interfMesh->moveMesh(*m_intfDisp, 1); // move the immersed structure mesh |
90 | 80 | m_buildLumpedMassMatrixOfStructure(); // update the lumped mass matrix of the immersed structure mesh | |
91 | |||
92 | // interpolation of the immersed structure mesh | ||
93 | 80 | m_interpolator->interpolate(m_indElt, m_intOp_val, m_listPoints); | |
94 | } | ||
95 | 320 | } | |
96 | |||
97 | 200 | void Immersed::updateIntersection(GeometricMeshRegion& mesh, PetscVector& delta, const MPI_Comm& comm) { | |
98 | |||
99 | // TODO remove mesh and use m_backMesh | ||
100 | |||
101 | // only first process will modify the value of the PetscVector delta and will write the files "intersection" | ||
102 |
2/2✓ Branch 1 taken 50 times.
✓ Branch 2 taken 150 times.
|
200 | if ( MpiInfo::rankProc() == 0 ) { |
103 | |||
104 | // locate the elements near the structure interface and the ones in star of the previous elements where the SUPG-PSPG and div-div stabilization will be modified | ||
105 |
1/2✓ Branch 4 taken 50 times.
✗ Branch 5 not taken.
|
50 | std::vector<felInt> elementID(m_interfMesh->numPoints()); |
106 | 50 | std::vector<GeometricMeshRegion::seedElement> elementIDstar; | |
107 |
1/2✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
|
50 | double coef = 1./FelisceParam::instance().localDivDivPenalty; |
108 |
1/2✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
|
50 | delta.set(1.0); |
109 |
1/2✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
50 | m_intersector->intersectMeshes(m_indElt, elementID); |
110 | |||
111 |
2/2✓ Branch 1 taken 1100 times.
✓ Branch 2 taken 50 times.
|
1150 | for (std::size_t i=0; i < elementID.size(); ++i) { |
112 |
1/2✓ Branch 2 taken 1100 times.
✗ Branch 3 not taken.
|
1100 | delta.setValue(elementID[i], coef, INSERT_VALUES); |
113 |
1/2✓ Branch 4 taken 1100 times.
✗ Branch 5 not taken.
|
1100 | mesh.getElementPatch(mesh.bagElementTypeDomain()[0], elementID[i], elementIDstar); |
114 |
2/2✓ Branch 1 taken 13500 times.
✓ Branch 2 taken 1100 times.
|
14600 | for (std::size_t j=0; j < elementIDstar.size(); ++j) { |
115 |
1/2✓ Branch 2 taken 13500 times.
✗ Branch 3 not taken.
|
13500 | delta.setValue(elementIDstar[j].second, coef, INSERT_VALUES); |
116 | } | ||
117 | } | ||
118 | |||
119 |
2/4✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
|
50 | if ( FelisceParam::instance().divDivStabPostProcess ) { |
120 | ✗ | m_divDivStabPostProcess(elementID); | |
121 | } | ||
122 | |||
123 | 50 | ++m_indexTime; | |
124 | 50 | } | |
125 | |||
126 | // once the PetscVector delta has been modified by the main process, broadcast it to all other processes of the communicator | ||
127 | 200 | delta.broadCastSequentialVector(comm, 0); | |
128 | 200 | } | |
129 | |||
130 | 320 | void Immersed::applyPenaltyToMatrixAndRHS(AO& ao, Dof& dof, int idVarVel, PetscMatrix& matrix, PetscVector& rhs, bool only_rhs) { | |
131 | |||
132 | double lambda_i, lambda_j; | ||
133 |
1/2✓ Branch 1 taken 320 times.
✗ Branch 2 not taken.
|
320 | double eps = FelisceParam::instance().penaltyCoeffImmersedStruct; |
134 | int k, ig, jg; | ||
135 | 320 | double val = 0.0, coef = 1.0; | |
136 | |||
137 |
3/4✓ Branch 1 taken 320 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 80 times.
✓ Branch 4 taken 240 times.
|
320 | if ( MpiInfo::rankProc() == 0 ) { // only the first processor add the "penalized" terms to the NS matrix |
138 | |||
139 | // matrix and rhs contributions for NS matrix | ||
140 |
2/2✓ Branch 0 taken 1750 times.
✓ Branch 1 taken 80 times.
|
1830 | for (int l=0; l< m_nbPoints; ++l) { |
141 | 1750 | k = m_indElt[l]; // the element containing the point | |
142 |
1/2✓ Branch 0 taken 1750 times.
✗ Branch 1 not taken.
|
1750 | if ( k != -1 ) { // if the interpolation of the immersed structure mesh into the fluid mesh has been successful |
143 | |||
144 | // implicit method | ||
145 |
2/4✓ Branch 1 taken 1750 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1750 times.
✗ Branch 4 not taken.
|
1750 | if ( FelisceParam::instance().fsiRNscheme == -1000 ) { |
146 |
2/4✓ Branch 1 taken 1750 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1750 times.
|
1750 | if ( FelisceParam::instance().useMassMatrix == 1 ) { // with use of the lumped mass matrix in the fourth block of the fluid problem matrix |
147 | ✗ | coef = 1.0/(eps*m_lumpedMassMatrix[l]); | |
148 | } | ||
149 | else { // with only penalisation coefficient in the fourth block of the fluid problem matrix | ||
150 | 1750 | coef = 1.0/eps; | |
151 | } | ||
152 | } | ||
153 | |||
154 | // explicit method without penalisation coefficient | ||
155 | ✗ | else if ( FelisceParam::instance().fsiRNscheme == 1 ) { | |
156 | ✗ | coef = (m_lumpedMassMatrix[l]*(FelisceParam::instance().densitySolid)*(FelisceParam::instance().thickness))/(FelisceParam::instance().timeStep); | |
157 | } | ||
158 | |||
159 | |||
160 | // if the specified fsiRNscheme has not been recognized, returns an error | ||
161 | else { | ||
162 | ✗ | std::ostringstream tmp; | |
163 | ✗ | tmp << FelisceParam::instance().fsiRNscheme; | |
164 | ✗ | std::string fsiRNscheme_as_string(tmp.str()); | |
165 | ✗ | FEL_ERROR(("Immersed::computePenaltyForce: value of fsiRNscheme = " + fsiRNscheme_as_string + " not recognized! STOP HERE.\n")); | |
166 | } | ||
167 | |||
168 | // | ||
169 |
2/2✓ Branch 0 taken 5250 times.
✓ Branch 1 taken 1750 times.
|
7000 | for (int i=0; i < m_nbVertices; ++i) { |
170 | 5250 | lambda_i = m_intOp_val[m_nbVertices*l+i ]; | |
171 | |||
172 |
1/2✓ Branch 0 taken 5250 times.
✗ Branch 1 not taken.
|
5250 | if ( not only_rhs ) { |
173 | // matrix | ||
174 |
2/2✓ Branch 0 taken 15750 times.
✓ Branch 1 taken 5250 times.
|
21000 | for (int j=0; j < m_nbVertices; ++j) { |
175 | 15750 | lambda_j = m_intOp_val[m_nbVertices*l+j ]; | |
176 | 15750 | val = coef*lambda_i*lambda_j; ///(1 + eps*coef); | |
177 |
2/2✓ Branch 0 taken 31500 times.
✓ Branch 1 taken 15750 times.
|
47250 | for (int ic=0; ic < m_nbCoor; ++ic){ |
178 |
1/2✓ Branch 1 taken 31500 times.
✗ Branch 2 not taken.
|
31500 | dof.loc2glob(k, i, idVarVel, ic,ig); |
179 |
1/2✓ Branch 1 taken 31500 times.
✗ Branch 2 not taken.
|
31500 | dof.loc2glob(k, j, idVarVel, ic,jg); |
180 |
1/2✓ Branch 1 taken 31500 times.
✗ Branch 2 not taken.
|
31500 | AOApplicationToPetsc(ao,1,&ig); |
181 |
1/2✓ Branch 1 taken 31500 times.
✗ Branch 2 not taken.
|
31500 | AOApplicationToPetsc(ao,1,&jg); |
182 |
1/2✓ Branch 1 taken 31500 times.
✗ Branch 2 not taken.
|
31500 | matrix.setValues(1,&ig,1,&jg,&val,ADD_VALUES); |
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | // rhs | ||
188 |
2/2✓ Branch 0 taken 10500 times.
✓ Branch 1 taken 5250 times.
|
15750 | for (int ic=0; ic < m_nbCoor; ++ic) { |
189 | |||
190 | // implicit method | ||
191 |
2/4✓ Branch 1 taken 10500 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10500 times.
✗ Branch 4 not taken.
|
10500 | if ( FelisceParam::instance().fsiRNscheme == -1000 ) { |
192 | 10500 | val = coef*lambda_i*(*m_intfVelo)[ic + l*m_nbCoor ]; | |
193 | } | ||
194 | |||
195 | // explicit method without penalisation coefficient | ||
196 | ✗ | else if ( (FelisceParam::instance().fsiRNscheme == 1) || (FelisceParam::instance().fsiRNscheme == -1) ) { | |
197 | ✗ | val = coef*lambda_i*(*m_intfVelo)[ic + l*m_nbCoor ] - lambda_i*m_intfForcOld[ic + l*m_nbCoor ]; | |
198 | } | ||
199 | |||
200 | // if the specified fsiRNscheme has not been recognized, returns an error | ||
201 | else { | ||
202 | ✗ | std::ostringstream tmp; | |
203 | ✗ | tmp << FelisceParam::instance().fsiRNscheme; | |
204 | ✗ | std::string fsiRNscheme_as_string(tmp.str()); | |
205 | ✗ | FEL_ERROR(("Immersed::computePenaltyForce: value of fsiRNscheme = " + fsiRNscheme_as_string + " not recognized! STOP HERE.\n")); | |
206 | } | ||
207 | |||
208 |
1/2✓ Branch 1 taken 10500 times.
✗ Branch 2 not taken.
|
10500 | dof.loc2glob(k,i, idVarVel, ic,ig); |
209 |
1/2✓ Branch 1 taken 10500 times.
✗ Branch 2 not taken.
|
10500 | AOApplicationToPetsc(ao,1,&ig); |
210 |
1/2✓ Branch 1 taken 10500 times.
✗ Branch 2 not taken.
|
10500 | rhs.setValues(1,&ig,&val,ADD_VALUES); |
211 | } | ||
212 | } | ||
213 | } | ||
214 | } | ||
215 | } // end of MpiInfo::rankProc() == 0 | ||
216 | |||
217 |
1/2✓ Branch 1 taken 320 times.
✗ Branch 2 not taken.
|
320 | matrix.assembly(MAT_FINAL_ASSEMBLY); |
218 |
1/2✓ Branch 1 taken 320 times.
✗ Branch 2 not taken.
|
320 | rhs.assembly(); |
219 | 320 | } | |
220 | |||
221 | ✗ | void Immersed::computePenaltyForce(AO& ao, Dof& dof, int idVarVel, PetscVector& seqVel) { | |
222 | |||
223 | double lambda_i; | ||
224 | ✗ | double eps = FelisceParam::instance().penaltyCoeffImmersedStruct; | |
225 | |||
226 | int k, ig; | ||
227 | ✗ | double val = 0.0, coef = 1.0; | |
228 | ✗ | std::vector<double> aux(m_nbPoints*m_nbCoor); | |
229 | |||
230 | ✗ | if ( MpiInfo::rankProc() == 0 ) { // only the first processor add the "penalized" terms to the NS matrix | |
231 | |||
232 | // compute | ||
233 | ✗ | for (int l=0; l< m_nbPoints; ++l) { | |
234 | ✗ | k= m_indElt[l]; // the element containing the point | |
235 | ✗ | if ( k != -1 ) { | |
236 | |||
237 | // implicit method | ||
238 | ✗ | if ( FelisceParam::instance().fsiRNscheme == -1000 ) { | |
239 | ✗ | if ( FelisceParam::instance().useMassMatrix == 1 ) { // with use of the lumped mass matrix in the fourth block of the fluid problem matrix | |
240 | ✗ | coef = 1.0/(eps*m_lumpedMassMatrix[l]); | |
241 | } | ||
242 | else { // with only penalisation coefficient in the fourth block of the fluid problem matrix | ||
243 | ✗ | coef = 1.0/eps; | |
244 | } | ||
245 | } | ||
246 | |||
247 | // explicit method without penalisation coefficient | ||
248 | ✗ | else if ( FelisceParam::instance().fsiRNscheme == 1 ) { | |
249 | ✗ | coef = (m_lumpedMassMatrix[l]*(FelisceParam::instance().densitySolid)*(FelisceParam::instance().thickness))/(FelisceParam::instance().timeStep); | |
250 | } | ||
251 | |||
252 | // if the specified fsiRNscheme has not been recognized, returns an error | ||
253 | else { | ||
254 | ✗ | std::ostringstream tmp; | |
255 | ✗ | tmp << FelisceParam::instance().fsiRNscheme; | |
256 | ✗ | std::string fsiRNscheme_as_string(tmp.str()); | |
257 | ✗ | FEL_ERROR(("Immersed::computePenaltyForce: value of fsiRNscheme = " + fsiRNscheme_as_string + " not recognized! STOP HERE.\n")); | |
258 | } | ||
259 | |||
260 | ✗ | for (int ic=0; ic < m_nbCoor; ++ic) { | |
261 | ✗ | (*m_velFluid)[l*m_nbCoor + ic] = 0.0; | |
262 | |||
263 | ✗ | for (int i=0; i < m_nbVertices; ++i) { | |
264 | ✗ | lambda_i = m_intOp_val[m_nbVertices*l+i ]; | |
265 | ✗ | dof.loc2glob(k,i, idVarVel, ic,ig); | |
266 | ✗ | AOApplicationToPetsc(ao,1,&ig); | |
267 | ✗ | seqVel.getValues(1,&ig,&val); | |
268 | ✗ | (*m_velFluid)[l*m_nbCoor + ic] += val*lambda_i; | |
269 | } | ||
270 | |||
271 | // implicit method | ||
272 | ✗ | if ( FelisceParam::instance().fsiRNscheme == -1000 ) { | |
273 | ✗ | (*m_intfForc)[l*m_nbCoor + ic] = coef*((*m_velFluid)[l*m_nbCoor + ic] - (*m_intfVelo)[l*m_nbCoor + ic]); | |
274 | } | ||
275 | |||
276 | // explicit method without penalisation coefficient | ||
277 | ✗ | else if ( FelisceParam::instance().fsiRNscheme == 1 ) { | |
278 | ✗ | (*m_intfForc)[l*m_nbCoor + ic] = coef*((*m_velFluid)[l*m_nbCoor + ic] - (*m_intfVelo)[l*m_nbCoor + ic]) + m_intfForcOld[l*m_nbCoor + ic] ; | |
279 | } | ||
280 | |||
281 | // if the specified fsiRNscheme has not been recognized, returns an error | ||
282 | else { | ||
283 | ✗ | std::ostringstream tmp; | |
284 | ✗ | tmp << FelisceParam::instance().fsiRNscheme; | |
285 | ✗ | std::string fsiRNscheme_as_string(tmp.str()); | |
286 | ✗ | FEL_ERROR(("Immersed::computePenaltyForce: value of fsiRNscheme = " + fsiRNscheme_as_string + " not recognized! STOP HERE.\n")); | |
287 | } | ||
288 | } | ||
289 | } | ||
290 | |||
291 | else { | ||
292 | |||
293 | ✗ | std::ostringstream tmp; | |
294 | ✗ | tmp << l; | |
295 | ✗ | std::string l_as_string(tmp.str()); | |
296 | ✗ | FEL_ERROR(("Immersed::computePenaltyForce: it seems that the interpolation table met some problems for localising the structure node of label " + l_as_string + ", hence the m_intForc std::vector has been std::set to 0! STOP HERE.\n")); | |
297 | } | ||
298 | } | ||
299 | |||
300 | // explicit method without penalisation coefficient | ||
301 | ✗ | if ( FelisceParam::instance().fsiRNscheme == 1 ) { | |
302 | ✗ | m_intfForcOld = (*m_intfForc); | |
303 | } | ||
304 | } | ||
305 | } | ||
306 | |||
307 | 2 | void Immersed::m_readInterfaceMesh() { | |
308 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::string inputDirectory1 = "./"; |
309 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::string inputFile1 = ""; |
310 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | std::string inputMesh1 = FelisceParam::instance().meshFileImmersedStruct; |
311 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::string outputMesh1 = "toto.geo"; |
312 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | std::string meshDir1 = FelisceParam::instance().meshDirImmersedStruct; |
313 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::string resultDir1 = ""; |
314 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::string prefixName1 = ""; |
315 | |||
316 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | IO io(inputDirectory1, inputFile1, inputMesh1, outputMesh1, meshDir1, resultDir1, prefixName1); |
317 | |||
318 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m_interfMesh = felisce::make_shared<GeometricMeshRegion>(); |
319 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | io.readMesh(*m_interfMesh, 1.0); |
320 | |||
321 | 2 | std::vector<Point>& listPoints = m_interfMesh->listPoints(); | |
322 | 2 | m_nbPoints = listPoints.size(); | |
323 | |||
324 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m_listPointsRef = listPoints; |
325 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | m_listPoints = listPoints; |
326 | |||
327 | 2 | m_nbCoor = m_interfMesh->domainDim()+1; // number of coordinates = dimension + 1 // TODO D.C. doesn't work for .geo mesh | |
328 | |||
329 | 2 | m_nbVertices = 0; // set in method updateInterface | |
330 | |||
331 | // whent the method used is the implicit one with use of the lumped mass matrix in the fourth block of the fluid problem matrix OR the explicit method | ||
332 |
7/14✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 2 times.
|
2 | if ( (( FelisceParam::instance().fsiRNscheme == -1000 ) && ( FelisceParam::instance().useMassMatrix == 1 ) ) || ( FelisceParam::instance().fsiRNscheme == 1 ) ) { // |
333 | ✗ | m_buildLumpedMassMatrixOfStructure(); // build the lumped mass matrix of the immersed structure mesh | |
334 | |||
335 | ✗ | if ( FelisceParam::instance().fsiRNscheme == 1) { // if explicit method | |
336 | ✗ | m_intfForcOld.resize(m_nbCoor*m_nbPoints, 0); // std::vector to store the previous force required for the computation of the new force in the explicit scheme | |
337 | } | ||
338 | } | ||
339 | 2 | } | |
340 | |||
341 | 80 | void Immersed::m_buildLumpedMassMatrixOfStructure() { | |
342 | |||
343 | // The purpose of this method is to build the lumped mass matrix of the structure used into the semi-implicit/explicit scheme | ||
344 | |||
345 |
2/4✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 80 times.
|
80 | if ( FelisceParam::verbose() > 1 ) { |
346 | ✗ | std::cout << " -- Building of the lumped mass matrix of the structure..." << std::endl; | |
347 | } | ||
348 | |||
349 | // initialization of the lumped mass matrix of the structure | ||
350 |
1/2✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
|
80 | m_lumpedMassMatrix.resize(m_nbPoints); |
351 |
2/2✓ Branch 0 taken 1750 times.
✓ Branch 1 taken 80 times.
|
1830 | for(int l = 0; l < m_nbPoints; ++l) { |
352 | 1750 | m_lumpedMassMatrix[l] = 0.; | |
353 | } | ||
354 | |||
355 | typedef felisce::GeometricMeshRegion::ElementType ElementType; | ||
356 | ElementType eltType; // geometric element type in the mesh. | ||
357 | 80 | int numPointsPerElt = 0; // number of points per geometric element. | |
358 | 80 | std::vector<Point*> elemPoint; // points of the current element. | |
359 | 80 | std::vector<felInt> elemIdPoint; // id of points of the element. | |
360 | |||
361 | // first loop on geometry type. | ||
362 | 80 | const std::vector<GeometricMeshRegion::ElementType>& bagElementTypeDomain = m_interfMesh->bagElementTypeDomain(); // list of domain element types in the mesh | |
363 |
2/2✓ Branch 1 taken 80 times.
✓ Branch 2 taken 80 times.
|
160 | for (std::size_t i = 0; i < bagElementTypeDomain.size(); ++i) { // for each domain element type |
364 | 80 | eltType = bagElementTypeDomain[i]; | |
365 | |||
366 | // resize array. | ||
367 | 80 | numPointsPerElt = GeometricMeshRegion::m_numPointsPerElt[eltType]; | |
368 |
1/2✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
|
80 | elemPoint.resize(numPointsPerElt, nullptr); |
369 |
1/2✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
|
80 | elemIdPoint.resize(numPointsPerElt, 0); |
370 | |||
371 | 80 | int typeOfFiniteElement = 0; | |
372 | 80 | const GeoElement *geoEle = GeometricMeshRegion::eltEnumToFelNameGeoEle[eltType].second; | |
373 |
1/2✓ Branch 2 taken 80 times.
✗ Branch 3 not taken.
|
80 | const RefElement* refEle = geoEle->defineFiniteEle(eltType, typeOfFiniteElement, *m_interfMesh); |
374 |
1/2✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
|
80 | CurvilinearFiniteElement fe(*refEle, *geoEle, DegreeOfExactness_0); |
375 | |||
376 | // second loop on the number of elements for each geometry type. | ||
377 |
2/2✓ Branch 2 taken 1670 times.
✓ Branch 3 taken 80 times.
|
1750 | for(int j = 0; j<m_interfMesh->numElements(eltType); ++j) { // for each element |
378 |
1/2✓ Branch 2 taken 1670 times.
✗ Branch 3 not taken.
|
1670 | m_interfMesh->getOneElement(eltType, j, elemIdPoint, 0); |
379 |
2/2✓ Branch 0 taken 3340 times.
✓ Branch 1 taken 1670 times.
|
5010 | for(int iPoint = 0; iPoint < numPointsPerElt; iPoint++) { |
380 | 3340 | elemPoint[iPoint] = &m_interfMesh->listPoints()[elemIdPoint[iPoint]]; | |
381 | } | ||
382 |
1/2✓ Branch 1 taken 1670 times.
✗ Branch 2 not taken.
|
1670 | fe.updateMeas(0, elemPoint); // update the measure |
383 |
2/2✓ Branch 0 taken 3340 times.
✓ Branch 1 taken 1670 times.
|
5010 | for(int iPoint = 0; iPoint < numPointsPerElt; ++iPoint) { |
384 |
1/2✓ Branch 1 taken 3340 times.
✗ Branch 2 not taken.
|
3340 | m_lumpedMassMatrix[elemIdPoint[iPoint]] += fe.measure()/numPointsPerElt; |
385 | } | ||
386 | } | ||
387 | 80 | } | |
388 | |||
389 |
2/4✓ Branch 1 taken 80 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 80 times.
|
80 | if ( FelisceParam::verbose() > 1 ) { |
390 | ✗ | std::cout << " -- The lumped mass matrix of the structure for the immersed method has been successfully built!" << std::endl; | |
391 | } | ||
392 | 80 | } | |
393 | |||
394 | ✗ | void Immersed::m_divDivStabPostProcess(std::vector<felInt>& elementID){ | |
395 | |||
396 | ✗ | double dt = FelisceParam::instance().timeStep; | |
397 | |||
398 | ✗ | std::vector<GeometricMeshRegion::seedElement> elementIDstar; | |
399 | ✗ | std::vector<felInt> value(m_backMesh->getNumDomainElement(),0.); | |
400 | |||
401 | ✗ | for (std::size_t i=0; i < elementID.size(); ++i) { | |
402 | ✗ | value[elementID[i]] = 1; | |
403 | ✗ | m_backMesh->getElementPatch(m_backMesh->bagElementTypeDomain()[0], elementID[i],elementIDstar); | |
404 | ✗ | for (std::size_t j=0; j < elementIDstar.size(); ++j) { | |
405 | ✗ | value[elementIDstar[j].second] = 1; | |
406 | } | ||
407 | } | ||
408 | |||
409 | { | ||
410 | // write case | ||
411 | FILE * pFile; | ||
412 | ✗ | std::string fileName, fileNameDir, fileNameCase; | |
413 | |||
414 | ✗ | fileNameDir = FelisceParam::instance().resultDir; | |
415 | ✗ | fileNameCase = fileNameDir+"intersection.case"; | |
416 | |||
417 | ✗ | pFile = fopen (fileNameCase.c_str(),"w"); | |
418 | ✗ | if (pFile==NULL) { | |
419 | ✗ | std::string command = "mkdir -p " + fileNameDir; | |
420 | ✗ | int ierr = system(command.c_str()); | |
421 | ✗ | if( ierr > 0) | |
422 | ✗ | FEL_ERROR("Impossible to write "+fileNameCase+" case file"); | |
423 | ✗ | pFile = fopen (fileNameCase.c_str(),"w"); | |
424 | } | ||
425 | ✗ | fprintf( pFile,"FORMAT\n"); | |
426 | // fprintf( pFile,"type: ensight\n"); | ||
427 | ✗ | fprintf( pFile,"type: ensight gold\n"); | |
428 | ✗ | fprintf( pFile,"GEOMETRY\n"); | |
429 | // fprintf( pFile,"model: 1 fluid.geo.*****.geo\n"); | ||
430 | ✗ | fprintf( pFile,"model: 1 fluid.geo\n"); | |
431 | ✗ | fprintf( pFile,"VARIABLE\n"); | |
432 | ✗ | fprintf( pFile,"scalar per element: 1 intersection intersection.*****.scl\n"); | |
433 | ✗ | fprintf( pFile,"TIME\n"); | |
434 | ✗ | fprintf( pFile, "time set: %d\n", 1); | |
435 | ✗ | fprintf( pFile,"number of steps: %d \n", m_indexTime+1); | |
436 | ✗ | fprintf( pFile, "filename start number: %d\n", 0); | |
437 | ✗ | fprintf( pFile, "filename increment: %d\n", 1); | |
438 | ✗ | fprintf( pFile, "time values:\n"); | |
439 | |||
440 | ✗ | int count=0; | |
441 | ✗ | for (int i=0; i < m_indexTime+1; ++i) { | |
442 | ✗ | fprintf( pFile, "%12.5e",i*dt); | |
443 | ✗ | ++count; | |
444 | ✗ | if ( count == 6) { | |
445 | ✗ | fprintf( pFile, "\n" ); | |
446 | ✗ | count=0; | |
447 | } | ||
448 | } | ||
449 | ✗ | fclose(pFile); | |
450 | } | ||
451 | |||
452 | { | ||
453 | ✗ | std::string fileName = FelisceParam::instance().resultDir + "intersection"; | |
454 | ✗ | std::stringstream oss; | |
455 | ✗ | oss << m_indexTime; | |
456 | ✗ | std::string aux = oss.str(); | |
457 | ✗ | if ( m_indexTime < 10 ) { | |
458 | ✗ | aux = "0000" + aux; | |
459 | ✗ | } else if ( m_indexTime < 100 ) { | |
460 | ✗ | aux = "000" + aux; | |
461 | ✗ | } else if ( m_indexTime < 1000 ) { | |
462 | ✗ | aux = "00" + aux; | |
463 | ✗ | } else if ( m_indexTime < 10000 ) { | |
464 | ✗ | aux = "0" + aux; | |
465 | } | ||
466 | |||
467 | ✗ | fileName = fileName + "." + aux + ".scl"; | |
468 | FILE * pFile; | ||
469 | ✗ | pFile = fopen (fileName.c_str(),"w"); | |
470 | |||
471 | ✗ | if (pFile==nullptr) { | |
472 | ✗ | FEL_ERROR("Impossible to write " + fileName + " scalar ensight solution"); | |
473 | } | ||
474 | |||
475 | ✗ | fprintf(pFile, "Scalar per element\n"); | |
476 | ✗ | fprintf(pFile, "part\n"); | |
477 | ✗ | fprintf(pFile, "%10d\n",1); // change the value at the end of the line depending on the part in your .geo file which will receive the "intersection" variable for the post-processing part | |
478 | ✗ | if (m_backMesh->domainDim() == 2) { // if the fluid mesh is a 2D mesh | |
479 | ✗ | fprintf(pFile, "tria3\n"); // consider the triangle elements | |
480 | } | ||
481 | ✗ | else if (m_backMesh->domainDim() == 3) { // if the fluid mesh is a 3D mesh | |
482 | ✗ | fprintf(pFile, "tetra4\n"); // consider the tetraedra elements | |
483 | } | ||
484 | |||
485 | ✗ | for (std::size_t i=0; i < value.size(); ++i) { | |
486 | ✗ | fprintf(pFile,"%d\n", value[i]); | |
487 | } | ||
488 | |||
489 | ✗ | fprintf(pFile, "\n"); | |
490 | ✗ | fclose(pFile); | |
491 | } | ||
492 | } | ||
493 | } | ||
494 | |||
495 |