GCC Code Coverage Report


Directory: ./
File: Model/NSModel.cpp
Date: 2024-04-14 07:32:34
Exec Total Coverage
Lines: 341 603 56.6%
Branches: 225 544 41.4%

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: Julien Castelneau, Dominique Chapelle, Miguel Fernandez
13 //
14
15 // System includes
16
17 // External includes
18
19 // Project includes
20 #include "Core/felisceTools.hpp"
21 #include "Model/NSModel.hpp"
22 #include "Solver/CVGraphInterface.hpp"
23 #include "Solver/linearProblemNS.hpp"
24 #include "Solver/linearProblemHarmonicExtension.hpp"
25 #ifdef FELISCE_WITH_CVGRAPH
26 #include "Model/cvgMainSlave.hpp"
27 #endif
28
29 namespace felisce {
30
31
17/34
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 42 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 42 times.
✗ Branch 9 not taken.
✓ Branch 13 taken 42 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 42 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 42 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 42 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 42 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 42 times.
✗ Branch 29 not taken.
✓ Branch 33 taken 42 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 42 times.
✗ Branch 37 not taken.
✓ Branch 39 taken 42 times.
✗ Branch 40 not taken.
✓ Branch 46 taken 42 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 42 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 42 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 42 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 42 times.
✗ Branch 59 not taken.
42 NSModel::NSModel():Model()
32 {
33 42 m_lumpedModelBC = nullptr;
34 42 m_risModel = nullptr;
35
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 m_name = "NS";
36 42 m_matrixWithoutBCcreated = false;
37 42 m_CrankNicolsonNS =nullptr;
38 42 }
39
40 /***********************************************************************************/
41 /***********************************************************************************/
42
43 116 NSModel::~NSModel()
44 {
45 84 auto& r_instance = FelisceParam::instance(instanceIndex());
46
47 // Write displacement and normal
48
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
84 if ( r_instance.useFDlagrangeMult ) {
49 const int ivar = m_pSolverNS->listVariable().getVariableIdList(lagMultiplier);
50 const int imesh = m_pSolverNS->listVariable()[ivar].idMesh();
51 writeCurrentDisplacement(imesh, "displacement");
52 writeCurrentNormalVector();
53
54 if ( r_instance.useFicItf )
55 writeCurrentDisplacement(2, "dispficstruc"); // TODO D.C.
56 }
57
58
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 38 times.
84 if ( m_lumpedModelBC )
59
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
8 delete m_lumpedModelBC;
60 116 }
61
62 /***********************************************************************************/
63 /***********************************************************************************/
64
65 42 void NSModel::setInitialCondition()
66 {
67 // Retrieve instance
68 42 auto& r_instance = FelisceParam::instance(instanceIndex());
69
70
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
42 if ( r_instance.hasInitialCondition && r_instance.useALEformulation ) {
71
72 // TODO D.C. only in case of ALE we can have an initial condition??? i don't think so...
73 int ivar = m_pSolverHE->listVariable().getVariableIdList(displacement);
74 int iunk = m_pSolverHE->listUnknown().getUnknownIdList(displacement);
75 int imesh = m_pSolverHE->listVariable()[ivar].idMesh();
76
77 // displacement
78 int numDof;
79 if( r_instance.FusionDof )
80 numDof = m_pSolverHE->supportDofUnknown(iunk).listNode().size() * m_pSolverHE->meshLocal(imesh)->numCoor();
81 else
82 numDof = m_pSolverHE->numDof();
83
84 // displacement
85 std::vector<double> vector( numDof, 0.);
86 m_ios[imesh]->readVariable(2, 0.0, vector.data(), numDof);
87
88 if( r_instance.FusionDof ) {
89 int numCompDisp = m_pSolverHE->dimension();
90 int numCoorMesh = m_pSolverHE->meshLocal(imesh)->numCoor();
91 int numNodes = m_pSolverHE->supportDofUnknown(iunk).listNode().size();
92 int idof;
93 std::vector<double> aux(vector);
94 for (int ip = 0; ip < numNodes; ip++) {
95 idof = m_pSolverHE->supportDofUnknown(iunk).listPerm()[ip];
96 for (felInt ic=0; ic < numCompDisp; ++ic)
97 vector[idof*numCompDisp+ic] = aux[ip*numCoorMesh+ic];
98 }
99 }
100
101 int low, high;
102 VecGetOwnershipRange(m_pSolverHE->solution().toPetsc(),&low,&high);
103
104 int localSize = high-low;
105 std::vector<int> ix(localSize);
106 std::vector<double> vv(localSize);
107 std::iota(ix.begin(),ix.end(),low); // fills ix with values from low to high
108
109 AOPetscToApplication(m_pSolverHE->ao(),localSize,ix.data());
110 for (int i=0; i<localSize;++i)
111 vv[i] = vector[ix[i]];
112 AOApplicationToPetsc(m_pSolverHE->ao(),localSize,ix.data());
113
114 m_pSolverHE->solution().setValues(localSize,ix.data(),vv.data(),INSERT_VALUES);
115 m_pSolverHE->solution().assembly();
116 m_pSolverHE->gatherSolution();
117 updateMesh();
118 }
119 42 }
120
121 /***********************************************************************************/
122 /***********************************************************************************/
123
124 42 void NSModel::initializeDerivedModel()
125 {
126 // Retrieve instance
127 42 auto& r_instance = FelisceParam::instance(instanceIndex());
128
129 42 m_pSolverNS = static_cast<LinearProblemNS*>(m_linearProblem[0]);
130
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 24 times.
42 if ( r_instance.useALEformulation )
131 18 m_pSolverHE = static_cast<LinearProblemHarmonicExtension*>(m_linearProblem[1]);
132
133
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (m_initializeCVGraphInterface) {
134 m_cvgraphInterf = felisce::make_shared<CVGraphInterface>();
135 m_cvgraphInterf->initialize(&m_pSolverNS->listVariable(), r_instance.CVGraphInterface);
136 m_cvgraphInterf->identifyIdDof(m_pSolverNS->dof());
137 m_pSolverNS->cvgraphInterf() = m_cvgraphInterf;
138 }
139
140
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 38 times.
42 if ( r_instance.lumpedModelBCLabel.size() ) {
141
2/4
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 m_lumpedModelBC = new LumpedModelBC(m_fstransient);
142 4 m_pSolverNS->initializeLumpedModelBC(m_lumpedModelBC);
143 }
144
145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if ( r_instance.RISModels ) {
146 m_risModel = new RISModel (m_fstransient, m_linearProblem) ;
147 m_pSolverNS->initializeRISModel(m_risModel);
148 m_chek_use_RISforward = false;
149 }
150
151
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if ( r_instance.CardiacCycle ) {
152 m_cardiacCycle = new CardiacCycle (m_fstransient, m_risModel, m_linearProblem) ;
153 m_pSolverNS->initializeCardiacCycle(m_cardiacCycle);
154 }
155
156
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 34 times.
42 if ( r_instance.hasImmersedData ) {
157
1/2
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 m_immersed.initialize(m_pSolverNS->mesh());
158 }
159
160 // monolithic fsi
161 // m_disp.duplicateFrom(m_pSolverNS->vector());
162 // m_disp.zeroEntries();
163
164
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 24 times.
42 if ( r_instance.useALEformulation ) {
165 18 const int ivar = m_pSolverHE->listVariable().getVariableIdList(displacement);
166 18 const int iunk = m_pSolverHE->listUnknown().getUnknownIdList(displacement);
167 18 const int iMesh = m_pSolverHE->listVariable()[ivar].idMesh();
168
169 18 m_numDofExtensionProblem = m_pSolverHE->numDof();
170
1/2
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
18 m_dispMeshVector.resize( m_pSolverHE->supportDofUnknown(iunk).listNode().size() * m_pSolverHE->meshLocal(iMesh)->numCoor() );
171 18 m_petscToGlobal.resize(m_numDofExtensionProblem);
172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if ( r_instance.readPreStressedDisplFromFile )
173 m_preStressedDispMeshVector.resize(m_numDofExtensionProblem);
174
2/2
✓ Branch 0 taken 252440 times.
✓ Branch 1 taken 18 times.
252458 for (int ipg=0; ipg< m_numDofExtensionProblem; ipg++)
175 252440 m_petscToGlobal[ipg] = ipg;
176
177 18 AOApplicationToPetsc(m_pSolverHE->ao(),m_numDofExtensionProblem,m_petscToGlobal.data());
178
179
2/4
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if ( r_instance.readDisplFromFile || r_instance.readPreStressedDisplFromFile ) {
180 // defined in linearProblemHarmonicExtention
181 m_pSolverHE->readMatchFile_ALE(m_pSolverHE->listVariable(), r_instance.MoveMeshMatchFile);
182 m_pSolverHE->identifyIdDofToMatch_ALE(m_pSolverHE->dof());
183
184 if (r_instance.hasInitialCondition || r_instance.readPreStressedDisplFromFile ) {
185 PetscPrintf(MpiInfo::petscComm(),"\nCycle 1, Read data displacement at time t = 0.00000\n");
186 m_pSolverHE->readDataDisplacement(m_ios, 0.0);
187 }
188 }
189 }
190
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if ( r_instance.orderBdfNS > 2 )
192 FEL_ERROR("BDF not yet implemented for order greater than 2 with Navier-Stokes.");
193
194 42 m_bdfNS.defineOrder(r_instance.orderBdfNS);
195 42 m_pSolverNS->initializeTimeScheme(&m_bdfNS);
196
197 // Crank-Nicolson time marching
198 // Manage midpoint approximation for the advection term
199 // TODO D.C. does it work???
200
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
42 if ( Tools::equal(r_instance.theta,0.5) ) {
201 m_CrankNicolsonNS = new Bdf;
202 m_CrankNicolsonNS->defineOrder(2);
203 // Second order approximation of the midpoint
204 m_CrankNicolsonNS->beta(0) = 3./2;
205 m_CrankNicolsonNS->beta(1) = -1./2;
206 }
207
208 // Initialization of residual stuff
209
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
42 if ( r_instance.withCVG && !r_instance.fsiCoupling ) {
210 m_rhsWihoutBC.duplicateFrom(m_pSolverNS->vector());
211 m_residual.duplicateFrom(m_pSolverNS->vector());
212 m_seqResidual.duplicateFrom(m_pSolverNS->sequentialSolution());
213 }
214
215
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 36 times.
42 if ( r_instance.fsiCoupling ) {
216 // TODO: we can use the functions createAndCopyMatrixRHSWithoutBC and computeResidual in LinearProblem
217 6 m_rhsWihoutBC.duplicateFrom(m_pSolverNS->vector());
218 6 m_residual.duplicateFrom(m_pSolverNS->vector());
219 6 m_lumpedMassRN.duplicateFrom(m_pSolverNS->vector());
220 6 m_seqResidual.duplicateFrom(m_pSolverNS->sequentialSolution());
221 }
222 42 }
223
224 /***********************************************************************************/
225 /***********************************************************************************/
226
227 42 void NSModel::setExternalVec()
228 {
229 // Retrieve instance
230 42 auto& r_instance = FelisceParam::instance(instanceIndex());
231
232 //=========
233 // ALE
234 //=========
235
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 24 times.
42 if ( r_instance.useALEformulation ) {
236 //1) Initialization of the vector containing the displacement of the mesh d^{n}, sequential std::vector
237 18 m_dispMesh.duplicateFrom(m_pSolverHE->sequentialSolution());
238 18 m_dispMesh.zeroEntries();
239
240 // fsi challenge
241
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
18 if ( r_instance.useElasticExtension ) {
242 6 m_dispMesho_pp.duplicateFrom(m_pSolverHE->solution());
243 6 m_dispMesho_pp.zeroEntries();
244 }
245
246
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
18 if ( Tools::equal(r_instance.theta,0.5) ) {
247 m_dispMesho.duplicateFrom(m_pSolverHE->sequentialSolution());
248 m_dispMesho.zeroEntries();
249 }
250
251 //2) Initialization of the std::vector containing the displacement of the mesh d^{n-1}, parallel std::vector
252 // m_solDispl == vectors of dispalcement at every time step (n>1)
253 // m_solDispl_0 == vectors of dispalcement at first time step (n==1)
254 // Two vectors of displacements are necessary because when a
255 // cardiac cycle re-start we need to read the std::vector of
256 // displacement at time 0, which is stored in m_solDispl_0
257 18 m_solDispl.duplicateFrom(m_pSolverHE->solution());
258 18 m_solDispl_0.duplicateFrom(m_pSolverHE->solution());
259 18 m_solDispl_0.zeroEntries();
260 18 m_solDispl.zeroEntries();
261
262 //3) Initialization of the vector containing the velocity of the mesh w, sequential vector
263 18 m_velMesh.duplicateFrom(m_pSolverHE->sequentialSolution());
264 18 m_velMesh.zeroEntries();
265
266 // Passing the ao and dof
267 18 m_pSolverNS->pushBackExternalAO(m_pSolverHE->ao());
268 18 m_pSolverNS->pushBackExternalDof(m_pSolverHE->dof());
269 // Passing the velocity of the mesh to the NS problem
270 18 m_pSolverNS->pushBackExternalVec(m_velMesh); //externalVec(0) in m_linearProblem[0]
271 // Resizing the auxiliar vectors needed in updateMesh()
272 18 m_tmpDisp.resize(m_numDofExtensionProblem);
273
274 18 m_displTimeStep = 0.;
275
276
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 14 times.
18 if (r_instance.nonLinearFluid) {
277 // create a sequential PetscVector whose size is equal to the total number of fluid elements
278 4 m_solPrev.duplicateFrom(m_pSolverNS->solution());
279 4 m_solPrev.zeroEntries();
280 // push it back to the sets of linear problems
281 4 m_pSolverNS->pushBackExternalVec(m_solPrev);
282 }
283 }
284
285
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
42 if ( r_instance.hasImmersedData && r_instance.hasDivDivStab ) {
286
287 // create a sequential PetscVector whose size is equal to the total number of fluid elements
288 4 int ivar = m_pSolverNS->listVariable().getVariableIdList(velocity);
289 4 int imesh = m_pSolverNS->listVariable()[ivar].idMesh();
290
291
2/4
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
4 m_delta.createSeq(PETSC_COMM_SELF, m_pSolverNS->mesh(imesh)->getNumDomainElement() );
292
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 m_delta.set(0.);
293
294 // push it back to the sets of linear problems
295 4 m_pSolverNS->pushBackExternalVec(m_delta); // TODO D.C. not really smart to do a pushBack in vector since the order may change depending on the problem we solve... mayba a map is better...
296 }
297
298 // for monolithic fsi
299 // m_dispSeq is a sequential PetscVector whose size is equal to the total number of fluid elements
300 // m_dispSeq.createSeq(PETSC_COMM_SELF, m_pSolverNS->numDof() );
301 // m_dispSeq.set(0.);
302 // m_pSolverNS->pushBackExternalVec(m_dispSeq); //externalVec(0) in m_pSolverNS or 1 if ALE
303 42 }
304
305 /***********************************************************************************/
306 /***********************************************************************************/
307
308 60 void NSModel::preAssemblingMatrixRHS(std::size_t iProblem)
309 {
310 // Retrieve instance
311 60 auto& r_instance = FelisceParam::instance(instanceIndex());
312
313
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 18 times.
60 if ( iProblem == 0 ) {
314 42 m_solExtrapolate.duplicateFrom(m_pSolverNS->vector());
315 42 m_solExtrapolate.zeroEntries();
316
317 42 m_pSolverNS->initExtrapol(m_solExtrapolate);
318
319 42 m_pSolverNS->solution().zeroEntries();
320
321 //! First assembly loop in iteration 0 to build static matrix.
322
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 18 times.
42 if ( r_instance.useALEformulation == 0 ) {
323
324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if ( r_instance.NSStabType == 1 )
325 m_pSolverNS->assembleFaceOrientedStabilization();
326
327 24 m_pSolverNS->assembleMatrixRHS(MpiInfo::rankProc());
328 }
329 }
330
331 //=========
332 // ALE
333 //=========
334
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 24 times.
60 if ( r_instance.useALEformulation ) {
335
4/4
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 6 times.
36 if ( (iProblem == 1) && (!r_instance.useElasticExtension) ) {
336 // First assembly loop in iteration 0 to build static matrix of the extension problem
337 12 m_pSolverHE->assembleMatrixRHS(MpiInfo::rankProc());
338 // Save the static part of the extension problem in the matrix _A
339 12 m_pSolverHE->copyMatrixRHS();
340 }
341
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
36 if ( (r_instance.useALEformulation == 2) && (iProblem == 0) ) {
342 // assembly loop to put values at the locations of the complementary pattern
343 if ( r_instance.NSStabType == 1 )
344 m_pSolverNS->assembleFaceOrientedStabilization();
345
346 // First assembly loop in iteration 0 to build the initial mass matrix (initial configuration)
347 m_pSolverNS->assembleMatrixRHS(MpiInfo::rankProc());
348 }
349 }
350 60 }
351
352 /***********************************************************************************/
353 /***********************************************************************************/
354
355 1904 void NSModel::postAssemblingMatrixRHS(std::size_t iProblem)
356 {
357 // Retrieve instance
358 1904 auto& r_instance = FelisceParam::instance(instanceIndex());
359
360 // matrix(0) = matrix(0) + matrix(1) (add static matrix to the dynamic matrix to build
361 // complete matrix of the system )
362 1904 m_linearProblem[iProblem]->addMatrixRHS();
363
364
3/4
✓ Branch 0 taken 1544 times.
✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1544 times.
1904 if ( iProblem == 0 && r_instance.withCVG )
365 m_pSolverNS->createAndCopyMatrixRHSWithoutBC();
366
367 //Apply CVGraphInterface condition directly in RHS
368
3/4
✓ Branch 0 taken 1544 times.
✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1544 times.
1904 if ( iProblem == 0 && r_instance.CVGraphInterfaceVariationalBC == 1 ) {
369 m_pSolverNS->vector().setValues(m_cvgraphInterf->SizeListOfDofForVariable(),
370 m_cvgraphInterf->listOfDofInInterface(), m_cvgraphInterf->ComputedVariableToImpose(), ADD_VALUES);
371 }
372 1904 }
373
374 /***********************************************************************************/
375 /***********************************************************************************/
376
377 void NSModel::RISforward()
378 {
379 // Retrieve instance
380 auto& r_instance = FelisceParam::instance(instanceIndex());
381
382 m_chek_use_RISforward = true;
383
384 if ( m_risModel->admissibleStatus() == 1 ) {
385 writeSolution();
386 if ( m_lumpedModelBC && MpiInfo::rankProc() == 0 )
387 m_lumpedModelBC->write(r_instance.resultDir+"/output_windkessel");
388
389 if ( MpiInfo::rankProc() == 0 )
390 m_risModel->write(r_instance.resultDir+"/outputValves");
391
392 // Advance time step.
393 updateTime();
394
395 if ( r_instance.useALEformulation == 2 ) {
396
397 if ( m_fstransient->iteration == 1 ) {
398 //create m_storedMatrix with the same structure of matrix(1)
399 m_storedMatrix.duplicateFrom(m_pSolverNS->matrix(1), MAT_COPY_VALUES);
400 }
401
402 if ( m_fstransient->iteration > 1 ) {
403 // add Matrix(1) to matrix(0)
404 m_pSolverNS->matrix(0).axpy(1,m_pSolverNS->matrix(1),SAME_NONZERO_PATTERN);
405 // copy matrix(1) in m_storedMatrix to use it in the NS recomputation
406 m_storedMatrix.copyFrom(m_pSolverNS->matrix(1), SAME_NONZERO_PATTERN);
407 //clear matrix(1) to be updated in the forward()
408 m_pSolverNS->clearMatrix(1);
409 }
410 }
411
412 // This is usefeul to read data_displacements
413 m_displTimeStep += m_fstransient->timeStep;
414 // Print time information
415 printNewTimeIterationBanner();
416
417 m_risModel->UpdateResistances();
418
419 if(r_instance.CardiacCycle)
420 m_cardiacCycle->ApplyCardiacCycleInput();
421
422 forward();
423 m_risModel->CheckValveStatus();
424 }
425
426 while( m_risModel->admissibleStatus() == 0 ) { // This "while" is important, an "if" does not work in all cases
427 PetscPrintf(MpiInfo::petscComm(),"\n Recomputation with the new RIS status\n");
428
429 for(std::size_t ilr=0; ilr<m_linearProblem.size(); ilr++) {
430 m_linearProblem[ilr]->clearMatrixRHS(FlagMatrixRHS::matrix_and_rhs); // 0 is flagMatrixRHS clear matrix(0) and RHS
431 }
432
433 if( (r_instance.useALEformulation == 2) && ( m_fstransient->iteration > 1 ) ) {
434 // we recomputed the matrix(0) at t^{n} and we add m_storedMatrix == matrix(1) a t^{n-1}
435 m_pSolverNS->matrix(0).axpy(1,m_storedMatrix,SAME_NONZERO_PATTERN);
436 m_storedMatrix.setUnfactored();
437 m_storedMatrix.zeroEntries();
438 }
439
440 m_risModel->UpdateResistances();
441
442 if( r_instance.CardiacCycle )
443 m_cardiacCycle->ApplyCardiacCycleInput();
444
445 forward();
446 m_risModel->CheckValveStatus();
447 }
448 }
449
450 /***********************************************************************************/
451 /***********************************************************************************/
452
453 1444 void NSModel::forward()
454 {
455 1444 prepareForward();
456 1444 solveNS();
457 1444 }
458
459 /***********************************************************************************/
460 /***********************************************************************************/
461
462 1544 void NSModel::prepareForward()
463 {
464 // Retrieve instance
465 1544 auto& r_instance = FelisceParam::instance(instanceIndex());
466
467 // Initial displacement for ALE
468
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1544 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1544 times.
1544 if ( r_instance.initALEDispByFile && (m_fstransient->iteration == 0 ) ) {
469
470 m_pSolverHE->readMatchFile_ALE(m_pSolverHE->listVariable(), r_instance.MoveMeshMatchFile);
471 m_pSolverHE->identifyIdDofToMatch_ALE(m_pSolverHE->dof());
472 m_pSolverHE->readDataDisplacement(m_ios, 0.0);
473 int low, high;
474 VecGetOwnershipRange(m_pSolverHE->solution().toPetsc(),&low,&high);
475 int size = high-low;
476 std::vector<double> vv(size);
477 std::vector<int> ix(size);
478 std::iota(ix.begin(),ix.end(),low); // fills ix with values from low to high
479
480 VecGetValues(m_pSolverHE->HarmExtSol().toPetsc(),size,ix.data(),vv.data());
481
482 VecSetValues(m_pSolverHE->solution().toPetsc(),size,ix.data(),vv.data(), INSERT_VALUES);
483 m_pSolverHE->solution().assembly();
484 m_pSolverHE->gatherSolution();
485 updateMesh();
486 }
487
488
1/2
✓ Branch 0 taken 1544 times.
✗ Branch 1 not taken.
1544 if ( !r_instance.RISModels ) {
489
490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1544 times.
1544 if ( r_instance.useFDlagrangeMult ) {
491
492 // Compute the displacements of the interface meshes
493 m_pSolverNS->computeItfDisp(*m_itfDisp);
494
495 // Move the interface meshes
496 m_pSolverNS->moveItfMeshes();
497
498 // Write displacement and normal
499 const int ivar = m_pSolverNS->listVariable().getVariableIdList(lagMultiplier);
500 const int imesh = m_pSolverNS->listVariable()[ivar].idMesh();
501 writeCurrentDisplacement(imesh, "displacement");
502 writeCurrentNormalVector();
503 }
504
505 // Write solution for postprocessing (if required)
506 1544 writeSolution();
507
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 1504 times.
1544 if ( m_lumpedModelBC ) {
508
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 30 times.
40 if ( MpiInfo::rankProc() == 0 )
509
1/2
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
10 m_lumpedModelBC->write(r_instance.resultDir+"/output_windkessel");
510 }
511
512 1544 updateTime(); //Here the matrix(0), the non constant one, is cleared and the rhs also.
513
514
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1544 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1544 times.
1544 if( (r_instance.useALEformulation == 2) && ( m_fstransient->iteration > 1 ) ) {
515 m_pSolverNS->matrix(0).axpy(1,m_pSolverNS->matrix(1),SAME_NONZERO_PATTERN);
516 m_pSolverNS->clearMatrix(1);
517 }
518
519 // Print time information
520 1544 printNewTimeIterationBanner();
521
522 // This is usefeul to read data_displacements
523 1544 m_displTimeStep += m_fstransient->timeStep;
524 }
525 else if ( /*r_instance.RISModels &&*/ m_chek_use_RISforward == false ) {
526
527 FEL_ERROR("Your are not using the corret forward for valve implementation !")
528 }
529
530 1544 m_pSolverNS->onPreviousMesh();
531
532 // Function only at iteration == 1
533 1544 firstIteration();
534
535
2/2
✓ Branch 1 taken 1502 times.
✓ Branch 2 taken 42 times.
1544 if ( m_fstransient->iteration > 1 ) {
536 1502 m_bdfNS.update(m_pSolverNS->solution());
537 1502 m_bdfNS.extrapolate(m_solExtrapolate);
538 1502 m_pSolverNS->updateExtrapol(m_solExtrapolate);
539
540
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1502 times.
1502 if ( Tools::equal(r_instance.theta,0.5) ) {
541 m_CrankNicolsonNS->update(m_pSolverNS->solution());
542 m_CrankNicolsonNS->extrapolate(m_solExtrapolate);
543 m_pSolverNS->updateExtrapol(m_solExtrapolate);
544 }
545 }
546
547 // If lumpedModel bc computation
548 1544 computeLumpedModelBC();
549
550 1544 m_bdfNS.computeRHSTime(m_fstransient->timeStep);
551 1544 m_pSolverNS->gatherVectorBeforeAssembleMatrixRHS();
552
553 // If fictitious domain + penalization update interface mesh
554
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 1224 times.
1544 if ( r_instance.hasImmersedData ) {
555 320 GeometricMeshRegion& mesh = *m_pSolverNS->mesh();
556 320 m_immersed.updateInterface(mesh); // TODO D.C. make more general
557
558
2/2
✓ Branch 0 taken 200 times.
✓ Branch 1 taken 120 times.
320 if ( r_instance.hasDivDivStab ) {
559 // call updateIntersection of the model "Immersed" in order to set the values of the PetscVector m_delta for the main process and to broadcast it to the other processes
560 200 m_immersed.updateIntersection(mesh, m_delta, MpiInfo::petscComm());
561 }
562 }
563
564 // If fictitious domain with lagrange multiplier
565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1544 times.
1544 if ( r_instance.useFDlagrangeMult ) {
566
567 // Localize interface quadrature point in fluid mesh and evaluate new pattern
568 m_pSolverNS->computeSolidFluidMaps();
569 m_pSolverNS->evaluateFluidStructurePattern();
570
571 m_pSolverNS->computeLagrangeMultiplierOnInterface(FlagMatrixRHS::only_matrix);
572
573 if ( r_instance.BHstab )
574 m_pSolverNS->assembleBarbosaHughesStab();
575
576 if ( r_instance.BPstab )
577 m_pSolverNS->assembleBrezziPitkarantaStab();
578
579 if ( r_instance.massConstraint ) {
580 m_pSolverNS->assembleJapanConstraintBoundary();
581 m_pSolverNS->assembleJapanConstraintInterface();
582 }
583 }
584
585
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 1184 times.
1544 if ( r_instance.useALEformulation ) {
586
587 360 computeALEterms();
588 } else {
589
590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1184 times.
1184 if ( r_instance.NSStabType == 1 )
591 m_pSolverNS->assembleFaceOrientedStabilization();
592
593 1184 m_pSolverNS->assembleMatrixRHS(MpiInfo::rankProc());
594 }
595
596 // TODO: we can use the functions createAndCopyMatrixRHSWithoutBC and computeResidual in LinearProblem
597
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 1444 times.
1544 if ( r_instance.fsiCoupling )
598 100 m_rhsWihoutBC.copyFrom(m_pSolverNS->vector());
599
600 // Specific operations before solve the system.
601 1544 postAssemblingMatrixRHS(0);
602
603 // TODO: we can use the functions createAndCopyMatrixRHSWithoutBC and computeResidual in LinearProblem
604
3/4
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 1444 times.
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
1544 if ( r_instance.fsiCoupling && !r_instance.useFDlagrangeMult ) {
605
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 94 times.
100 if ( m_matrixWithoutBCcreated == 0 ) {
606 6 m_matrixWithoutBC.duplicateFrom(m_pSolverNS->matrix(),MAT_COPY_VALUES);
607 6 m_matrixWithoutBCcreated = true;
608 }
609 100 m_matrixWithoutBC.copyFrom(m_pSolverNS->matrix(), SAME_NONZERO_PATTERN);
610 }
611 1544 }
612
613 /***********************************************************************************/
614 /***********************************************************************************/
615
616 1544 void NSModel::solveNS()
617 {
618 1544 const auto& r_instance = FelisceParam::instance(instanceIndex());
619
620 1544 const int ivar = m_pSolverNS->listVariable().getVariableIdList(velocity);
621 1544 const int imesh = m_pSolverNS->listVariable()[ivar].idMesh();
622
623
4/6
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 1444 times.
✓ Branch 2 taken 100 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 100 times.
✗ Branch 5 not taken.
1544 if ( r_instance.fsiCoupling && !r_instance.hasImmersedData && !r_instance.useFDlagrangeMult ) {
624
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 94 times.
100 if ( m_fstransient->iteration == 1 ) {
625
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if ( m_hasLumpedMassRN ) {
626 6 PetscScalar dti = 1./m_fstransient->timeStep;
627 6 m_lumpedMassRN.scale(dti);
628 }
629 }
630
631
3/4
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 70 times.
100 if ( r_instance.bcInRefConfiguration && !m_hasLumpedMassRN ) {
632 m_pSolverNS->meshLocal(imesh)->moveMesh(m_dispMeshVector,0.0);
633 }
634
3/4
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 70 times.
100 if ( r_instance.bcInRefConfiguration && r_instance.readPreStressedDisplFromFile ) {
635 m_pSolverNS->meshLocal(imesh)->moveMesh(m_preStressedDispMeshVector,1.0);
636 }
637
3/6
✓ Branch 0 taken 260 times.
✓ Branch 1 taken 1184 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 260 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1544 } else if ( r_instance.useALEformulation && r_instance.bcInRefConfiguration && r_instance.NSequationFlag != 0 ) {
638 m_pSolverNS->meshLocal(imesh)->moveMesh(m_dispMeshVector,0.0);
639 }
640
641
2/2
✓ Branch 1 taken 300 times.
✓ Branch 2 taken 1244 times.
1544 if ( FelisceParam::verbose() ) {
642
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 300 times.
300 if ( r_instance.nonLinearFluid )
643 PetscPrintf(MpiInfo::petscComm(),"NS non-linear problem \n");
644 else
645 300 PetscPrintf(MpiInfo::petscComm(),"NS linear problem \n");
646 }
647
648
2/2
✓ Branch 0 taken 320 times.
✓ Branch 1 taken 1224 times.
1544 if ( r_instance.hasImmersedData ) {
649 320 AO& ao = m_pSolverNS->ao();
650 320 PetscMatrix& matrix = m_pSolverNS->matrix(0);
651 320 PetscVector& rhs = m_pSolverNS->vector();
652 320 Dof& dof = m_pSolverNS->dof();
653 320 int idVarVel = m_pSolverNS->idVarVel();
654 320 m_immersed.applyPenaltyToMatrixAndRHS(ao,dof,idVarVel,matrix,rhs);
655 }
656
657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1544 times.
1544 if ( r_instance.useFDlagrangeMult)
658 m_pSolverNS->computeLagrangeMultiplierOnInterface(FlagMatrixRHS::only_rhs);
659
660
2/2
✓ Branch 1 taken 300 times.
✓ Branch 2 taken 1244 times.
1544 if ( FelisceParam::verbose() )
661 300 PetscPrintf(MpiInfo::petscComm(),"Applying BC \n");
662
663 //Apply essential transient boundary conditions.
664 1544 m_pSolverNS->finalizeEssBCTransient();
665
666 #ifdef FELISCE_WITH_CVGRAPH
667
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1544 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1544 times.
✗ Branch 7 not taken.
1544 if ( !r_instance.withCVG || ! m_pSolverNS->slave()->redoTimeStepOnlyCVGData() ) {
668 1544 m_pSolverNS->applyBC(r_instance.essentialBoundaryConditionsMethod, MpiInfo::rankProc());
669 } else {
670 m_pSolverNS->applyOnlyCVGBoundaryCondition();
671 }
672 #else
673 m_pSolverNS->applyBC(r_instance.essentialBoundaryConditionsMethod, MpiInfo::rankProc());
674 #endif
675
676
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 1444 times.
1544 if ( r_instance.fsiCoupling ) {
677
678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if ( r_instance.useLumpedMassRN ) {
679 m_pSolverNS->matrix().diagonalSet(m_lumpedMassRN,ADD_VALUES);
680 }
681
3/4
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 70 times.
100 if ( r_instance.bcInRefConfiguration && r_instance.readPreStressedDisplFromFile ) {
682 m_pSolverNS->meshLocal(imesh)->moveMesh(m_preStressedDispMeshVector,-1.0);
683 }
684
3/4
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 70 times.
100 if ( r_instance.bcInRefConfiguration && !m_hasLumpedMassRN ) {
685 m_pSolverNS->meshLocal(imesh)->moveMesh(m_dispMeshVector,1.0);
686 }
687
688 100 m_pSolverNS->kspInterface().setDiagonalScale();
689 }
690
3/6
✓ Branch 0 taken 260 times.
✓ Branch 1 taken 1184 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 260 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1444 else if ( r_instance.useALEformulation && r_instance.bcInRefConfiguration && r_instance.NSequationFlag != 0 ) {
691 m_pSolverNS->meshLocal(imesh)->moveMesh(m_dispMeshVector,1.0);
692 }
693
694
2/2
✓ Branch 1 taken 300 times.
✓ Branch 2 taken 1244 times.
1544 if ( FelisceParam::verbose() )
695 300 PetscPrintf(MpiInfo::petscComm(),"Solving NS system \n");
696
697
2/2
✓ Branch 0 taken 960 times.
✓ Branch 1 taken 584 times.
1544 if ( r_instance.nonLinearFluid ) {
698 // solve non Linear system
699 960 m_pSolverNS->iterativeSolve(MpiInfo::rankProc(), MpiInfo::numProc(), ApplyNaturalBoundaryConditions::no, FlagMatrixRHS::matrix_and_rhs);
700 } else {
701 // solve Linear system
702 584 m_pSolverNS->solve(MpiInfo::rankProc(), MpiInfo::numProc());
703 }
704
705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1544 times.
1544 if ( r_instance.withCVG ) {
706 m_pSolverNS->computeResidual();
707 }
708
709
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 1444 times.
1544 if ( r_instance.fsiCoupling ) {
710 100 m_pSolverNS->gatherSolution();
711
712
1/2
✓ Branch 1 taken 100 times.
✗ Branch 2 not taken.
100 if ( FelisceParam::verbose() )
713 100 PetscPrintf(MpiInfo::petscComm(),"Evaluating residual \n");
714
715 // TODO: we can use the functions createAndCopyMatrixRHSWithoutBC and computeResidual in LinearProblemNS
716 // Compute residual
717
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if ( r_instance.useFDlagrangeMult ) {
718 m_pSolverNS->computeInterfaceStress();
719
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 } else if ( r_instance.hasImmersedData ) {
720 AO& ao = m_pSolverNS->ao();
721 PetscVector& seqVel = m_pSolverNS->sequentialSolution();
722 Dof& dof = m_pSolverNS->dof();
723 int idVarVel = m_pSolverNS->idVarVel();
724 m_immersed.computePenaltyForce(ao,dof,idVarVel,seqVel);
725 } else {
726 100 m_matrixWithoutBC.scale(-1.);
727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if ( r_instance.nonLinearFluid )
728 m_rhsWihoutBC.scale(-1.);
729
730 100 multAdd(m_matrixWithoutBC,m_pSolverNS->solution(),m_rhsWihoutBC,m_residual);
731
732 100 m_pSolverNS->gatherVector(m_residual, m_seqResidual);
733 100 m_matrixWithoutBC.scale(-1.);
734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
100 if ( r_instance.nonLinearFluid )
735 m_rhsWihoutBC.scale(-1.);
736 }
737 }
738
739 // (interface) displacement update, monolthic FSI
740 // d^n = d^{n-1} + \tau * u^n
741 // m_disp.axpy(m_fstransient->timeStep,m_pSolverNS->solution());
742 // m_pSolverNS->gatherVector(m_disp, m_dispSeq);
743 // m_pSolverNS->gatherSolution();
744 1544 }
745
746 /***********************************************************************************/
747 /***********************************************************************************/
748
749 984 void NSModel::solveLinearizedNS(bool linearFlag)
750 {
751 // Retrieve instance
752 984 auto& r_instance = FelisceParam::instance(instanceIndex());
753
754 984 m_pSolverNS->linearizedFlag() = linearFlag;
755
756 // back to original matrix
757 984 m_pSolverNS->kspInterface().setDiagonalScaleFix();
758
759
2/2
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 110 times.
984 if ( linearFlag )
760 874 m_pSolverNS->vector().zeroEntries();
761 else
762 110 m_pSolverNS->vector().copyFrom(m_rhsWihoutBC);
763
764
5/6
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 110 times.
✓ Branch 3 taken 874 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 874 times.
✓ Branch 6 taken 110 times.
984 if ( linearFlag && FelisceParam::verbose() )
765 874 PetscPrintf(MpiInfo::petscComm(),"NS linearized solver \n");
766
1/2
✓ Branch 1 taken 110 times.
✗ Branch 2 not taken.
110 else if ( FelisceParam::verbose() )
767 110 PetscPrintf(MpiInfo::petscComm(),"NS solver \n");
768
769
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 984 times.
984 if ( r_instance.hasImmersedData ) {
770 AO& ao = m_pSolverNS->ao();
771 PetscMatrix& matrix = m_pSolverNS->matrix(0);
772 PetscVector& rhs = m_pSolverNS->vector();
773 Dof& dof = m_pSolverNS->dof();
774 int idVarVel = m_pSolverNS->idVarVel();
775 m_immersed.applyPenaltyToMatrixAndRHS(ao,dof,idVarVel,matrix,rhs,true);
776 }
777
778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 984 times.
984 if ( r_instance.useFDlagrangeMult) {
779 m_pSolverNS->computeLagrangeMultiplierOnInterface(FlagMatrixRHS::only_rhs);
780 }
781
782
1/2
✓ Branch 1 taken 984 times.
✗ Branch 2 not taken.
984 if (FelisceParam::verbose())
783 984 PetscPrintf(MpiInfo::petscComm(),"Applying BC \n");
784
785 // Apply essential transient boundary conditions.
786 984 m_pSolverNS->finalizeEssBCTransient();
787
788
2/2
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 110 times.
984 if ( linearFlag ) // only Dirichlet BC on the interface is applied (RHS)
789 874 m_pSolverNS->applyBC(r_instance.essentialBoundaryConditionsMethod, MpiInfo::rankProc(), FlagMatrixRHS::only_rhs, FlagMatrixRHS::only_rhs, 0, true, ApplyNaturalBoundaryConditions::no);
790 else // all BC applied (RHS)
791 110 m_pSolverNS->applyBC(r_instance.essentialBoundaryConditionsMethod, MpiInfo::rankProc(), FlagMatrixRHS::only_rhs, FlagMatrixRHS::only_rhs, 0, true, ApplyNaturalBoundaryConditions::yes);
792
793 984 m_pSolverNS->kspInterface().setDiagonalScale();
794
795
1/2
✓ Branch 1 taken 984 times.
✗ Branch 2 not taken.
984 if ( FelisceParam::verbose() ) {
796
2/2
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 110 times.
984 if ( linearFlag )
797 874 PetscPrintf(MpiInfo::petscComm(),"Solving linearized NS system (same matrix) \n");
798 else
799 110 PetscPrintf(MpiInfo::petscComm(),"Solving NS system (same matrix) \n");
800 }
801
802 // Solve linear system with same matrix as in solveNS
803 984 m_pSolverNS->solveWithSameMatrix();
804
805 984 m_pSolverNS->gatherSolution();
806
807
1/2
✓ Branch 1 taken 984 times.
✗ Branch 2 not taken.
984 if ( FelisceParam::verbose() )
808 984 PetscPrintf(MpiInfo::petscComm(),"Evaluating residual \n");
809
810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 984 times.
984 if ( r_instance.useFDlagrangeMult ) {
811 m_pSolverNS->computeInterfaceStress();
812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 984 times.
984 } else if ( r_instance.hasImmersedData ) {
813 AO& ao = m_pSolverNS->ao();
814 PetscVector& seqVel = m_pSolverNS->sequentialSolution();
815 Dof& dof = m_pSolverNS->dof();
816 int idVarVel = m_pSolverNS->idVarVel();
817 m_immersed.computePenaltyForce(ao,dof,idVarVel,seqVel);
818 } else {
819 //Compute residual
820 984 m_matrixWithoutBC.scale(-1.);
821
2/2
✓ Branch 0 taken 874 times.
✓ Branch 1 taken 110 times.
984 if ( linearFlag ) {
822 874 m_pSolverNS->vector().zeroEntries();
823 874 multAdd(m_matrixWithoutBC,m_pSolverNS->solution(),m_pSolverNS->vector(),m_residual);
824 }
825 else
826 110 multAdd(m_matrixWithoutBC,m_pSolverNS->solution(),m_rhsWihoutBC,m_residual);
827 984 m_pSolverNS->gatherVector(m_residual, m_seqResidual);
828 984 m_matrixWithoutBC.scale(-1.);
829 }
830
831 984 m_pSolverNS->linearizedFlag() = false;
832 984 }
833
834 /***********************************************************************************/
835 /***********************************************************************************/
836
837 1544 void NSModel::computeLumpedModelBC()
838 {
839 // Retrieve instance
840 1544 auto& r_instance = FelisceParam::instance(instanceIndex());
841
842
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 1504 times.
1544 if (m_lumpedModelBC) {
843 // update the fluxes
844 40 m_pSolverNS->computeMeanQuantity(velocity, m_labelFluxListLumpedModelBC, m_fluxLumpedModelBC);
845
846
2/2
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 40 times.
120 for(std::size_t i=0; i<m_lumpedModelBC->size(); i++) {
847 80 m_lumpedModelBC->Q(i) = m_fluxLumpedModelBC[i] ;
848 }
849
850 // update compliance if non linear compliance
851
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 if ( r_instance.lumpedModelBC_C_type == 2 ) {
852 m_pSolverNS->updateVolume();
853 }
854
855 // iterate the lumpedModelBC parameters
856 40 m_lumpedModelBC->iterate();
857 }
858 1544 }
859
860 /***********************************************************************************/
861 /***********************************************************************************/
862
863 1544 void NSModel::firstIteration()
864 {
865 // Retrieve instance
866 1544 auto& r_instance = FelisceParam::instance(instanceIndex());
867
868
2/2
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 1502 times.
1544 if ( m_fstransient->iteration == 1 ) {
869
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 24 times.
42 if ( r_instance.useALEformulation ) {
870 18 m_tau = 1./(m_fstransient->timeStep);
871 18 m_cycl = 1; // For movemesh case
872 }
873
874
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 38 times.
42 if (m_lumpedModelBC) {
875 // m_labelFluxListLumpedModelBC computation with LumpedModelBC labels
876 4 m_labelFluxListLumpedModelBC.clear();
877
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 4 times.
12 for(std::size_t i=0; i<m_lumpedModelBC->size(); i++) {
878 8 m_labelFluxListLumpedModelBC.push_back(r_instance.lumpedModelBCLabel[i]);
879 }
880 }
881
882 42 m_bdfNS.initialize(m_pSolverNS->solution());
883 42 m_bdfNS.extrapolate(m_solExtrapolate);
884 42 m_pSolverNS->initExtrapol(m_solExtrapolate);
885
886 // Crank-Nicolson time marching
887
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
42 if ( Tools::equal(r_instance.theta,0.5) ) {
888 m_CrankNicolsonNS->initialize(m_pSolverNS->solution());
889 m_CrankNicolsonNS->extrapolate(m_solExtrapolate);
890 m_pSolverNS->updateExtrapol(m_solExtrapolate);
891 }
892
893
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if ( r_instance.readPreStressedDisplFromFile ) {
894 computePreStressedDispMeshVector();
895 }
896 }
897 1544 }
898
899 /***********************************************************************************/
900 /***********************************************************************************/
901
902 int NSModel::getNstate() const
903 {
904 return m_pSolverNS->numDof();
905 }
906
907 /***********************************************************************************/
908 /***********************************************************************************/
909
910 void NSModel::getState(double* & state)
911 {
912 m_pSolverNS->getSolution(state, MpiInfo::numProc(), MpiInfo::rankProc());
913 }
914
915 /***********************************************************************************/
916 /***********************************************************************************/
917
918 felInt NSModel::numDof_swig()
919 {
920 return m_pSolverNS->numDof();
921 }
922
923 /***********************************************************************************/
924 /***********************************************************************************/
925
926 void NSModel::getState_swig(double* data, felInt numDof)
927 {
928 double * state;
929 m_pSolverNS->getSolution(state, MpiInfo::numProc(), MpiInfo::rankProc());
930 for (felInt i=0 ; i<numDof ; i++) {
931 data[i] = state[i];
932 }
933 }
934
935 /***********************************************************************************/
936 /***********************************************************************************/
937
938 void NSModel::setState(double* & state)
939 {
940 m_pSolverNS->setSolution(state, MpiInfo::numProc(), MpiInfo::rankProc());
941 }
942
943 /***********************************************************************************/
944 /***********************************************************************************/
945
946 360 void NSModel::computeALEterms()
947 {
948 // Retrieve instance
949 360 auto& r_instance = FelisceParam::instance(instanceIndex());
950
951 // Assembly the RHS (flagMatrixRHS = FlagMatrixRHS::only_rhs) in the previous mesh configuration:
952 // \dfrac{\rho}{\dt} \int_{\Omega^{n-1}} u^{n-1} v + \int_{\Omega^{n-1}} f v
953 360 m_pSolverNS->onPreviousMesh();
954 360 m_pSolverNS->assembleMatrixRHS(MpiInfo::rankProc(), FlagMatrixRHS::only_rhs);
955
956 //Save velocity previous mesh
957
2/2
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 200 times.
360 if ( r_instance.nonLinearFluid ) {
958 160 m_solPrev.zeroEntries();
959 160 m_solPrev.copyFrom(m_pSolverNS->vector());
960 }
961
962 //First distinguish the elastic extension and harmonic extension.
963
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 290 times.
360 if ( r_instance.useElasticExtension ) {
964 70 UpdateMeshByDisplacement();
965 }
966 else{
967 // Solve the extension problem and move the mesh of m_pSolverNS
968 // according to the mesh displacement obtained
969
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 290 times.
290 if( r_instance.updateMeshByVelocity ) {
970 // the HarmonicExtention unknown is velocity
971 // dispalcement is computed analitycally
972 UpdateMeshByVelocity();
973 } else {
974 // the HarmonicExtention unknown is displacement
975 // velocity is computed analitycally
976 290 UpdateMeshByDisplacement();
977 }
978 }
979
980 360 m_pSolverNS->onCurrentMesh();
981
982 // Assembly the Matrix (flagMatrixRHS = FlagMatrixRHS::only_matrix) in the current mesh configuration
983
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360 times.
360 if ( r_instance.NSStabType == 1 )
984 m_pSolverNS->assembleFaceOrientedStabilization();
985
986 360 m_pSolverNS->assembleMatrixRHS(MpiInfo::rankProc(), FlagMatrixRHS::only_matrix);
987 360 m_pSolverNS->assembleMatrixRHS(MpiInfo::rankProc(), FlagMatrixRHS::only_rhs);
988 360 }
989
990 /***********************************************************************************/
991 /***********************************************************************************/
992
993 void NSModel::UpdateMeshByVelocity()
994 {
995 // Retrieve instance
996 auto& r_instance = FelisceParam::instance(instanceIndex());
997
998 if ( r_instance.hasInitialCondition ) { // m_solDispl_0 = d^{0} != 0
999 m_solDispl_0.copyFrom(m_pSolverHE->solution());
1000 //else m_solDispl_0 = d^{0} == 0 defined in ExternalVec()
1001 }
1002
1003 if(m_fstransient->iteration>1 ) {
1004 m_solDispl.copyFrom(m_pSolverHE->solution());
1005 }
1006
1007 felInt displIterMax = r_instance.timeMaxCaseFile; // todo: it should be taken automatically form displacement file.case
1008
1009 if(m_fstransient->iteration == m_cycl * displIterMax +1) { // to read the file case in cycle
1010 m_displTimeStep = m_fstransient->timeStep ;
1011 m_cycl++;
1012 }
1013 PetscPrintf(MpiInfo::petscComm(),"Cycle %d, Read data at time t = %f\n", m_cycl, m_displTimeStep);
1014 m_pSolverHE->readDataDisplacement(m_ios, m_displTimeStep); // defined in linearProblemHarmonicExtention
1015
1016 //Solve the extension problem
1017 solveHarmExt();
1018
1019 // Store velocity and apply it to the NS problem. seqSolution is the velocity
1020 m_pSolverHE->gatherSolution();
1021 m_velMesh.copyFrom(m_pSolverHE->sequentialSolution());
1022 m_velMesh.scale(-1.);
1023
1024 /*In which follow compute displacement: d^n = w^n*dt + d^{n-1}
1025 VecAXPBY(Vec y,PetscScalar a,PetscScalar b,Vec x); -> y=a∗x+b∗y
1026 solution() == w^n
1027 m_solDispl == d^{n-1}
1028 when a cardiac cycle re-start we need to initilize the displacement(t==0)
1029 because the displacement(0) != dispalcement(timeMaxCaseFile),
1030 where timeMaxCaseFile is last time step*/
1031 if(m_fstransient->iteration == m_cycl * displIterMax + 1)
1032 m_pSolverHE->solution().axpby(1, r_instance.timeStep, m_solDispl_0);
1033 else
1034 m_pSolverHE->solution().axpby(1, r_instance.timeStep, m_solDispl);
1035
1036 m_pSolverHE->gatherSolution();
1037 // seqSolution() is now the displacement because in VecAXPBY we change solution()
1038
1039 updateMesh();
1040 }
1041
1042 /***********************************************************************************/
1043 /***********************************************************************************/
1044
1045 360 void NSModel::UpdateMeshByDisplacement()
1046 {
1047 // Retrieve instance
1048 360 auto& r_instance = FelisceParam::instance(instanceIndex());
1049
1050
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 360 times.
360 if ( r_instance.readDisplFromFile )
1051 m_pSolverHE->readDataDisplacement(m_ios, m_displTimeStep); // defined in linearProblemHarmonicExtention
1052
1053 // fsi challenge
1054
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 290 times.
360 if ( r_instance.useElasticExtension )
1055 70 m_dispMesho_pp.copyFrom( m_pSolverHE->solution() );
1056
1057
1058
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 360 times.
360 if ( Tools::equal(r_instance.theta,0.5) ) {
1059 m_velMesh.copyFrom(m_dispMesho);
1060 m_dispMesho.copyFrom(m_dispMesh);
1061 } else {
1062 // m_dispMesh = 0 at m_fstransient->iteration = 1
1063 360 m_velMesh.copyFrom(m_dispMesh);
1064 }
1065
1066 //Solve the extension problem
1067 360 solveHarmExt();
1068 360 m_pSolverHE->gatherSolution();
1069
1070 360 updateMesh();
1071
1072
1073 // Compute velocity and apply it to the NS problem. seqSolution is the displacement
1074 //VecAXPBY(Vec y,PetscScalar a,PetscScalar b,Vec x); -> y=a∗x+b∗y
1075 // now m_velMesh == d^{n-1}
1076 // and m_dispMesh == d^{n}
1077 360 m_velMesh.axpby(-m_tau,m_tau,m_dispMesh);
1078 // Result: m_velMesh = -w^{n} = \dfrac{1}{\dt} (-d^{n} + d^{n-1})
1079
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 360 times.
360 if ( Tools::equal(r_instance.theta,0.5) )
1080 m_velMesh.scale(0.5);
1081 // Result: m_velMesh = -w^{n+1/2} = 0.5 \dfrac{1}{\dt} (-d^{n} + d^{n-2})
1082 360 }
1083
1084 /***********************************************************************************/
1085 /***********************************************************************************/
1086
1087 360 void NSModel::solveHarmExt()
1088 {
1089 // Retrieve instance
1090 360 auto& r_instance = FelisceParam::instance(instanceIndex());
1091
1092 //Assemble matrix and RHS
1093 360 m_pSolverHE->assembleMatrixRHS(MpiInfo::rankProc());
1094 //Specific operations before solve the system
1095 360 postAssemblingMatrixRHS(1);
1096 //Apply essential transient boundary conditions
1097 360 m_pSolverHE->finalizeEssBCTransient();
1098 360 m_pSolverHE->applyBC(r_instance.essentialBoundaryConditionsMethod, MpiInfo::rankProc());
1099 //Solve linear system
1100 360 m_pSolverHE->solve(MpiInfo::rankProc(), MpiInfo::numProc());
1101
1102 // fsi challenge (update displacement with increment)
1103
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 290 times.
360 if ( r_instance.useElasticExtension )
1104 70 m_pSolverHE->solution().axpy(1.,m_dispMesho_pp);
1105 360 }
1106
1107 /***********************************************************************************/
1108 /***********************************************************************************/
1109
1110 360 void NSModel::updateMesh()
1111 {
1112 // Retrieve instance
1113 360 auto& r_instance = FelisceParam::instance(instanceIndex());
1114
1115 360 const int ivar = m_pSolverHE->listVariable().getVariableIdList(displacement);
1116 360 const int iunk = m_pSolverHE->listUnknown().getUnknownIdList(displacement);
1117 360 const int iMesh = m_pSolverHE->listVariable()[ivar].idMesh();
1118
1119 //=========
1120 // ALE
1121 //=========
1122 360 PetscPrintf(MpiInfo::petscComm(),"Update mesh\n");
1123
1124 360 m_dispMesh.copyFrom(m_pSolverHE->sequentialSolution());
1125 // m_dispMesh is the solution obtained with solveHarmExt()
1126 // Extract the values of m_dispMesh and put them in the std::vector m_dispMeshVector
1127 // according to the application ordering of the nodes
1128 360 m_dispMesh.getValues(m_numDofExtensionProblem, m_petscToGlobal.data(), m_tmpDisp.data());
1129
1130 360 felInt numNodes = m_pSolverHE->supportDofUnknown(iunk).listNode().size();
1131 felInt idof;
1132 360 felInt numCompDisp = m_pSolverHE->dimension();
1133 360 felInt numCoorMesh = m_pSolverHE->meshLocal(iMesh)->numCoor();
1134
1135
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 320 times.
360 if ( r_instance.FusionDof ) {
1136
2/2
✓ Branch 0 taken 40800 times.
✓ Branch 1 taken 40 times.
40840 for (felInt ip = 0; ip < numNodes; ip++) {
1137 40800 idof = m_pSolverHE->supportDofUnknown(iunk).listPerm()[ip];
1138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40800 times.
40800 if ( numCompDisp < numCoorMesh ) {
1139 m_dispMeshVector[ip*3] = m_tmpDisp[idof*2];
1140 m_dispMeshVector[ip*3+1] = m_tmpDisp[idof*2+1];
1141 m_dispMeshVector[ip*3+2] = 0.;
1142 }
1143
1/2
✓ Branch 0 taken 40800 times.
✗ Branch 1 not taken.
40800 else if ( numCompDisp == numCoorMesh ) {
1144
2/2
✓ Branch 0 taken 122400 times.
✓ Branch 1 taken 40800 times.
163200 for (felInt ic = 0; ic < numCoorMesh; ++ic)
1145 122400 m_dispMeshVector[ip*numCoorMesh+ic] = m_tmpDisp[idof*numCoorMesh+ic];
1146 }
1147 }
1148 }
1149 else // to be modified: does not work if numCompDisp < numCoorMesh // TODO
1150 320 m_dispMeshVector = m_tmpDisp;
1151
1152 //Move the mesh in the fluid problem
1153
1/2
✓ Branch 0 taken 360 times.
✗ Branch 1 not taken.
360 if ( r_instance.NSequationFlag != 0 ) {
1154
1/2
✓ Branch 3 taken 360 times.
✗ Branch 4 not taken.
360 m_pSolverNS->meshLocal(iMesh)->moveMesh(m_dispMeshVector,1.0);
1155
4/6
✓ Branch 1 taken 115 times.
✓ Branch 2 taken 245 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 115 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 360 times.
360 if ( (MpiInfo::rankProc() == 0) && r_instance.hasImmersedData ) // Attention: we move also the points of the global mesh, this can impact the fluid.geo if written at each time-step
1156 m_pSolverNS->mesh(iMesh)->moveMesh(m_dispMeshVector,1.0);
1157
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 290 times.
360 if ( r_instance.useElasticExtension )
1158 // extension computed on the deformed mesh (takes into account the size of the deformed elements)
1159
1/2
✓ Branch 3 taken 70 times.
✗ Branch 4 not taken.
70 m_pSolverHE->meshLocal(iMesh)->moveMesh(m_dispMeshVector,1.0);
1160 }
1161 360 }
1162
1163 /***********************************************************************************/
1164 /***********************************************************************************/
1165
1166 void NSModel::computePreStressedDispMeshVector()
1167 {
1168 // Retrieve instance
1169 auto& r_instance = FelisceParam::instance(instanceIndex());
1170
1171 m_pSolverHE->HarmExtSol().getValues(m_numDofExtensionProblem, m_petscToGlobal.data(), m_tmpDisp.data());
1172
1173 const int iunk = m_pSolverHE->listUnknown().getUnknownIdList(displacement);
1174
1175 felInt numNodes = m_pSolverHE->supportDofUnknown(iunk).listNode().size();
1176 if(r_instance.FusionDof) {
1177
1178 // if there are e.g. RIS model, the number of dofs are re-numerated.
1179 m_preStressedDispMeshVector.resize(numNodes*3, 0.);
1180 for (felInt ip = 0; ip < numNodes; ip++) {
1181 m_preStressedDispMeshVector[ip*3] = m_tmpDisp[m_pSolverHE->supportDofUnknown(iunk).listPerm()[ip]*3]; // TODO D.C. supportDofUnknown(0) is velocity? maybe is better get the id of the unknow from listVariable
1182 m_preStressedDispMeshVector[ip*3+1] = m_tmpDisp[m_pSolverHE->supportDofUnknown(iunk).listPerm()[ip]*3+1];
1183 m_preStressedDispMeshVector[ip*3+2] = m_tmpDisp[m_pSolverHE->supportDofUnknown(iunk).listPerm()[ip]*3+2];
1184 }
1185 } else
1186 m_preStressedDispMeshVector = m_tmpDisp;
1187 }
1188
1189 /***********************************************************************************/
1190 /***********************************************************************************/
1191
1192 542 PetscVector& NSModel::seqResidual()
1193 {
1194 542 return m_seqResidual;
1195 }
1196
1197 /***********************************************************************************/
1198 /***********************************************************************************/
1199
1200 PetscVector& NSModel::residual()
1201 {
1202 return m_residual;
1203 }
1204
1205 /***********************************************************************************/
1206 /***********************************************************************************/
1207
1208 6 int& NSModel::hasLumpedMassRN()
1209 {
1210 6 return m_hasLumpedMassRN;
1211 }
1212
1213 /***********************************************************************************/
1214 /***********************************************************************************/
1215
1216 18 PetscVector& NSModel::lumpedMassRN()
1217 {
1218 18 return m_lumpedMassRN;
1219 }
1220
1221 /***********************************************************************************/
1222 /***********************************************************************************/
1223
1224 8 Immersed & NSModel::immersed()
1225 {
1226 8 return m_immersed;
1227 }
1228
1229 /***********************************************************************************/
1230 /***********************************************************************************/
1231
1232 void NSModel::writeCurrentDisplacement(const int mesh_id, const std::string name)
1233 {
1234
1235 if ( MpiInfo::rankProc() != 0 )
1236 return;
1237
1238 const int points = m_mesh[mesh_id]->numPoints();
1239 const int dim = 3*points;
1240 double* disp = new double[dim];
1241
1242 for (int i = 0; i < points; ++i){
1243 for (int j = 0; j < 3; ++j)
1244 disp[3*i+j] = m_mesh[mesh_id]->listPoints()[i].coor(j) - m_mesh[mesh_id]->listReferencePoints()[i].coor(j);
1245 }
1246 m_ios[mesh_id]->writeSolution(MpiInfo::rankProc(), m_fstransient->time, m_fstransient->iteration, 1, name , disp, points, 3, true);
1247 }
1248
1249 /***********************************************************************************/
1250 /***********************************************************************************/
1251
1252 void NSModel::writeCurrentNormalVector()
1253 {
1254 if ( MpiInfo::rankProc() != 0 )
1255 return;
1256
1257 const felInt iUnknownLag = m_pSolverNS->iUnknownLag();
1258 const felInt iLagrange = m_pSolverNS->idVarLag();
1259 const felInt lagMesh = m_pSolverNS->listVariable()[iLagrange].idMesh();
1260 const int nodes = m_pSolverNS->supportDofUnknown(iUnknownLag).listNode().size();
1261 const int dim = 3*nodes;
1262 double* normal = new double[dim];
1263 for (int i = 0; i < nodes; ++i){
1264 for (int j = 0; j < 3; ++j)
1265 normal[3*i+j] = m_pSolverNS->mesh(lagMesh)->listNormal(i).coor(j);
1266 }
1267 std::string name = "normal";
1268 m_ios[lagMesh]->writeSolution(MpiInfo::rankProc(), m_fstransient->time, m_fstransient->iteration, 1, name , normal, nodes, 3, true);
1269 }
1270
1271 /***********************************************************************************/
1272 /************************* CVGRAPH *************************************************/
1273
1274 #ifdef FELISCE_WITH_CVGRAPH
1275 void NSModel::cvgraphNewTimeStep()
1276 {
1277 this->prepareForward();
1278 }
1279 #endif
1280 }
1281