GCC Code Coverage Report


Directory: ./
File: Solver/linearProblemHyperElasticity.cpp
Date: 2024-04-14 07:32:34
Exec Total Coverage
Lines: 271 311 87.1%
Branches: 172 374 46.0%

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: S. Gilles
13 //
14
15 // System includes
16
17 // External includes
18
19 // Project includes
20 #include "Solver/linearProblemHyperElasticity.hpp"
21 #include "DegreeOfFreedom/boundaryCondition.hpp"
22 #include "Core/felisceTransient.hpp"
23
24 namespace felisce
25 {
26
27 /**
28 * \brief This function is given to SNES to compute the function.
29 *
30 * However as a matter of fact the jacobian will also be computed here, as it is the way Felisce works
31 * (it hence avoids duplication or storage of intermediate matrixes)
32 *
33 * \param[in] snes SNES object. Not explicitly used but required by Petsc prototype.
34 * \param[in] evaluationState State at which to evaluate residual.
35 * \param[in] residual Vector to put residual. What is used as residual in LinearProblem is #_RHS.
36 * \param[in] context_as_void Optional user-defined function context. In our case a #SnesContext object,
37 * of which LinearProblem object is an attribute.
38 */
39 1044 PetscErrorCode snesFunctionImpl(SNES snes, Vec evaluationState, Vec residual, void* context_as_void) {
40 static_cast<void>(snes);
41 // static_cast<void>(residual); // residual as input argument should in fact be the same as linear_problem.RHS()
42
43
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1044 times.
1044 FEL_ASSERT(context_as_void);
44
45 1044 SnesContext* context_ptr = static_cast<SnesContext*>(context_as_void);
46 1044 SnesContext& context = *context_ptr;
47 1044 LinearProblem* linear_problem = context.linearProblem;
48
49 {
50 // DEV TMP: not generic enough! (displacement is really related to my own peculiar problem...)
51
1/2
✓ Branch 1 taken 1044 times.
✗ Branch 2 not taken.
1044 PetscInt NdofLocalPerUnknown = linear_problem->numDofLocalPerUnknown(/*PhysicalVariable::*/displacement);
52
53 1044 PetscVector& lp_evaluation_state = linear_problem->evaluationState();
54 1044 PetscVector& lp_rhs = linear_problem->vector();
55
56
1/2
✓ Branch 2 taken 1044 times.
✗ Branch 3 not taken.
1044 std::vector<PetscInt> local_indexing(NdofLocalPerUnknown); // std::vector that contains integers from 0 to local size - 1
57 {
58 // std::iota(local_indexing.begin(), local_indexing.end(), 0); // std::iota only works with C++11!
59
60
2/2
✓ Branch 0 taken 2161602 times.
✓ Branch 1 taken 1044 times.
2162646 for (int i = 0; i < NdofLocalPerUnknown; ++i) // substitute that also works in C++ 98 (arguably more easy to understand anyway)
61 2161602 local_indexing[i] = i;
62 }
63
64
1/2
✓ Branch 2 taken 1044 times.
✗ Branch 3 not taken.
1044 std::vector<PetscInt> global_indexing(NdofLocalPerUnknown);
65
66
2/4
✓ Branch 2 taken 1044 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1044 times.
✗ Branch 6 not taken.
2088 ISLocalToGlobalMappingApply(linear_problem->mappingDofLocalToDofGlobal(/*PhysicalVariable::*/displacement),
67 NdofLocalPerUnknown,
68 1044 local_indexing.data(),
69 global_indexing.data());
70
71 {
72 PetscScalar * evaluation_state_array;
73
1/2
✓ Branch 1 taken 1044 times.
✗ Branch 2 not taken.
1044 VecGetArrayRead(evaluationState,(const PetscScalar**)&evaluation_state_array);
74
75 PetscScalar * residual_array;
76
1/2
✓ Branch 1 taken 1044 times.
✗ Branch 2 not taken.
1044 VecGetArray(residual,&residual_array);
77
78
1/2
✓ Branch 2 taken 1044 times.
✗ Branch 3 not taken.
1044 FEL_ASSERT_EQUAL(global_indexing.size(), NdofLocalPerUnknown);
79
80
1/2
✓ Branch 3 taken 1044 times.
✗ Branch 4 not taken.
1044 lp_evaluation_state.setValues(global_indexing.size(),global_indexing.data(),evaluation_state_array,INSERT_VALUES);
81
1/2
✓ Branch 1 taken 1044 times.
✗ Branch 2 not taken.
1044 lp_evaluation_state.assembly();
82
83
1/2
✓ Branch 3 taken 1044 times.
✗ Branch 4 not taken.
1044 lp_rhs.setValues(global_indexing.size(),global_indexing.data(),residual_array,INSERT_VALUES);
84
1/2
✓ Branch 1 taken 1044 times.
✗ Branch 2 not taken.
1044 lp_rhs.assembly();
85
86
1/2
✓ Branch 1 taken 1044 times.
✗ Branch 2 not taken.
1044 VecRestoreArray(residual,&residual_array);
87
1/2
✓ Branch 1 taken 1044 times.
✗ Branch 2 not taken.
1044 VecRestoreArrayRead(evaluationState,(const PetscScalar**)&evaluation_state_array);
88
89 }
90 1044 }
91
92 1044 linear_problem->preSNESAssemble();
93 1044 linear_problem->assembleMatrixRHS(context.rankProc, context.flag_matrix_rhs);
94 1044 linear_problem->computeSystemAfterAssembling();
95
96 //Apply boundary conditions.
97 1044 linear_problem->finalizeEssBCTransient();
98 {
99 enum { idBCforLinCombMethod = 0 };
100 1044 bool doPrintBC = false;
101 1044 linear_problem->applyBC(FelisceParam::instance().essentialBoundaryConditionsMethod,
102 context.rankProc,
103 FlagMatrixRHS::matrix_and_rhs,
104 FlagMatrixRHS::matrix_and_rhs,
105 idBCforLinCombMethod, doPrintBC,
106 context.do_apply_natural);
107 }
108
109 1044 VecCopy(linear_problem->vector().toPetsc(),residual);
110 //VecView(residual,PETSC_VIEWER_STDOUT_WORLD);
111 1044 PetscFunctionReturn(0);
112 }
113
114 /***********************************************************************************/
115 /***********************************************************************************/
116
117 /**
118 * \brief This function is supposed to be given to SNES to compute the jacobian.
119 *
120 * However the jacobian has already been computed within snesFunctionImpl, so this function is mostly a dummy one...
121 */
122 700 PetscErrorCode snesJacobianImpl(SNES snes, Vec evaluationState, Mat jacobian , Mat preconditioner, void* context_as_void) {
123 static_cast<void>(snes);
124 static_cast<void>(jacobian);
125 static_cast<void>(preconditioner);
126 static_cast<void>(evaluationState);
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 700 times.
700 FEL_ASSERT(context_as_void);
128
129 700 PetscFunctionReturn(0);
130 }
131
132 /***********************************************************************************/
133 /***********************************************************************************/
134
135 24 LinearProblemHyperElasticity::LinearProblemHyperElasticity(SpatialForce force)
136 : LinearProblem("HyperElasticity equation"),
137
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 m_force(force),
138 24 system_(HyperelasticityNS::static_),
139
8/16
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 24 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 24 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 24 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 24 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 24 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 24 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 24 times.
✗ Branch 26 not taken.
48 is_first_dynamic_iteration_done_(false)
140 {
141 24 }
142
143 /***********************************************************************************/
144 /***********************************************************************************/
145
146 96 LinearProblemHyperElasticity::~LinearProblemHyperElasticity()
147 = default;
148
149 /***********************************************************************************/
150 /***********************************************************************************/
151
152 24 void LinearProblemHyperElasticity::initialize(std::vector<GeometricMeshRegion::Pointer>& mesh, FelisceTransient::Pointer fstransient, MPI_Comm& comm, bool doUseSNES)
153 {
154 // Retrieve the instance
155
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 const auto& r_instance = FelisceParam::instance();
156
157 using namespace HyperelasticityNS;
158
159
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 LinearProblem::initialize(mesh, comm, doUseSNES);
160 24 m_fstransient = fstransient;
161
162
2/4
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 5 not taken.
24 m_typeOfForceApplied = Private::HyperElasticity::AssignForceType(FelisceParam::instance().volumicOrSurfacicForce);
163
164
1/2
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
24 r_instance.hyperElasticLaw.hyperElasticLaws->InitParameters();
165
166
2/6
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 24 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
24 FEL_ASSERT(FelisceParam::instance().volumic_mass > 0.);
167
168 24 std::vector<PhysicalVariable> listVariable;
169 24 std::vector<std::size_t> listNumComp;
170
171
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 listVariable.push_back(displacement);
172
1/2
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
24 listNumComp.push_back(this->dimension());
173
174
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 m_listUnknown.push_back(displacement);
175
176
2/4
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 24 times.
24 if (r_instance.hyperElasticLaw.pressureData->IsCompressible()) {
177 listVariable.push_back(pressure);
178 listNumComp.push_back(1);
179 m_listUnknown.push_back(pressure);
180 }
181
182
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 definePhysicalVariable(listVariable,listNumComp);
183
1/2
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
24 setNumberOfMatrix(MatrixNS::Nmatrices);
184
185
2/3
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
24 switch(r_instance.hyperElasticLaw.timeSchemeHyperelasticity) {
186 8 case none:
187 case midpoint:
188 8 break;
189 16 case half_sum:
190
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 setNumberOfVector(VectorNS::Nvector);
191 }
192 24 }
193
194 /***********************************************************************************/
195 /***********************************************************************************/
196
197 24 void LinearProblemHyperElasticity::InitializeDerivedAttributes()
198 {
199 // Retrieve the instance
200 24 const auto& r_instance = FelisceParam::instance();
201
202 using namespace HyperelasticityNS;
203
204 // Check here there are no Neumann or NeumannNormal boundary conditions in the case of the volumic force
205 // (it is not stricto sensu a limitation, so it could be lifted later, but at the moment it is a good way
206 // to make sure there is no mishap in the data parameter file, in which we could apply both volumic and
207 // surfacic force without being aware of it.)
208
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if (m_typeOfForceApplied == Private::HyperElasticity::volumic) {
209
3/6
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 24 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 24 times.
24 if (m_boundaryConditionList.numNeumannBoundaryCondition() || m_boundaryConditionList.numNeumannNormalBoundaryCondition()) {
210 FEL_ERROR("Neumann condition found along with a volumic force; it is not allowed at the moment. "
211 "Check there is no mishap in your data file.");
212 }
213 }
214
215 24 current_displacement_.duplicateFrom(this->solution());
216 24 current_velocity_.duplicateFrom(this->solution());
217 24 seq_current_displacement_.duplicateFrom(this->sequentialSolution());
218
219 24 current_velocity_.zeroEntries();
220 24 current_displacement_.zeroEntries();
221 24 seq_current_displacement_.zeroEntries();
222
223
2/3
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
24 switch(r_instance.hyperElasticLaw.timeSchemeHyperelasticity) {
224 8 case midpoint: {
225 8 midpoint_position_.duplicateFrom(this->solution());
226 8 seq_midpoint_position_.duplicateFrom(this->sequentialSolution());
227
228 8 midpoint_position_.zeroEntries();
229 8 seq_midpoint_position_.zeroEntries();
230 8 break;
231 }
232 16 case half_sum:
233 case none:
234 16 break;
235 }
236
237 24 m_snesContext.initialize(*this, MpiInfo::rankProc(), MpiInfo::numProc(), ApplyNaturalBoundaryConditions::no, FlagMatrixRHS::matrix_and_rhs);
238
239 24 snesInterface().setFunction(vector(), snesFunctionImpl, &m_snesContext);
240 24 snesInterface().setJacobian(matrix(0), matrix(0), snesJacobianImpl, &m_snesContext);
241 24 }
242
243 /***********************************************************************************/
244 /***********************************************************************************/
245
246 1044 void LinearProblemHyperElasticity::initPerElementType(ElementType eltType, FlagMatrixRHS flagMatrixRHS)
247 {
248 // Retrieve the instance
249 1044 const auto& r_instance = FelisceParam::instance();
250
251 1044 m_currentElementType = eltType;
252 1044 m_iDisplacement = m_listVariable.getVariableIdList(displacement);
253 1044 m_feDisplacement = m_listCurrentFiniteElement[m_iDisplacement];
254
255
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1044 times.
1044 if (r_instance.hyperElasticLaw.pressureData->IsCompressible()) {
256 r_instance.hyperElasticLaw.pressureData->Init(m_listVariable, m_listCurrentFiniteElement);
257
258 FEL_ASSERT(m_feDisplacement->numQuadraturePoint() == r_instance.hyperElasticLaw.pressureData->FiniteElementPressure()->numQuadraturePoint()
259 && "In its current state the code is unable to cope with different quadrature points for both variables.");
260 FEL_ASSERT(m_feDisplacement->numDof() == r_instance.hyperElasticLaw.pressureData->FiniteElementPressure()->numDof()
261 && "In its current state the code is unable to cope with different degres for both variables.");
262 }
263
264
2/4
✓ Branch 0 taken 1044 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1044 times.
✗ Branch 3 not taken.
1044 if (flagMatrixRHS == FlagMatrixRHS::only_rhs || flagMatrixRHS == FlagMatrixRHS::matrix_and_rhs)
265 1044 m_elemField.initialize(QUAD_POINT_FIELD, *m_feDisplacement, this->dimension());
266 1044 }
267
268 /***********************************************************************************/
269 /***********************************************************************************/
270
271 522000 void LinearProblemHyperElasticity::computeElementArray(
272 const std::vector<Point*>& elemPoint,
273 const std::vector<felInt>& elemIdPoint,
274 int& iel, FlagMatrixRHS flagMatrixRHS)
275 {
276 // Retrieve the instance
277
1/2
✓ Branch 1 taken 522000 times.
✗ Branch 2 not taken.
522000 const auto& r_instance = FelisceParam::instance();
278
279 IGNORE_UNUSED_ELEM_ID_POINT;
280 using namespace HyperelasticityNS;
281
282
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 522000 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
522000 FEL_ASSERT(m_feDisplacement);
283 522000 CurrentFiniteElement& feDisplacement = *m_feDisplacement; // alias
284
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 522000 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
522000 FEL_ASSERT(flagMatrixRHS == FlagMatrixRHS::matrix_and_rhs);
285
286
1/2
✓ Branch 1 taken 522000 times.
✗ Branch 2 not taken.
522000 feDisplacement.updateFirstDeriv(0, elemPoint);
287
288
2/4
✓ Branch 2 taken 522000 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 522000 times.
522000 if (r_instance.hyperElasticLaw.pressureData->IsCompressible())
289 r_instance.hyperElasticLaw.pressureData->FiniteElementPressure()->updateFirstDeriv(0, elemPoint);
290
291 522000 const int NquadraturePoint = feDisplacement.numQuadraturePoint();
292
293 522000 const std::size_t sizeMatrix = std::pow(this->dimension(), 2);
294
1/2
✓ Branch 1 taken 522000 times.
✗ Branch 2 not taken.
522000 UBlasMatrix nonLinearPart(sizeMatrix, sizeMatrix);
295 522000 ElementVector& elementVector = *m_elementVector[0];
296
1/2
✓ Branch 1 taken 522000 times.
✗ Branch 2 not taken.
522000 UBlasVector pressure;
297
298
2/3
✓ Branch 0 taken 42000 times.
✓ Branch 1 taken 480000 times.
✗ Branch 2 not taken.
522000 switch (system_) {
299 42000 case HyperelasticityNS::static_: {
300
1/2
✓ Branch 3 taken 42000 times.
✗ Branch 4 not taken.
42000 std::vector<UBlasVector> displacement_per_component = extractDisplacementPerComponent(iel, evaluationState(), seqEvaluationState());
301
302
2/4
✓ Branch 2 taken 42000 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 42000 times.
42000 if (r_instance.hyperElasticLaw.pressureData->IsCompressible()) {
303 pressure = extractPressure(iel, evaluationState(), seqEvaluationState());
304 }
305
306 // DEV NOTE: nonLinearPart size could be defined once and for all. See when profiling whether it is
307 // a performance bottleneck.
308 42000 ElementMatrix& elementMatrix = *m_elementMat[0];
309
310 // At the moment all variables must share the same integration pattern, so no need to split calculation
311 // for displacement and pressure.
312
2/2
✓ Branch 0 taken 126000 times.
✓ Branch 1 taken 42000 times.
168000 for(int quadraturePointIndex = 0; quadraturePointIndex < NquadraturePoint; ++quadraturePointIndex) {
313
1/2
✓ Branch 1 taken 126000 times.
✗ Branch 2 not taken.
126000 UBlasMatrix linearPart;
314
1/2
✓ Branch 1 taken 126000 times.
✗ Branch 2 not taken.
126000 UBlasVector rhsPart;
315
316 {
317 using namespace Private::HyperElasticity;
318
2/4
✓ Branch 1 taken 126000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 126000 times.
✗ Branch 5 not taken.
126000 calculateLinearAndNonLinearMatrixAndRhs(r_instance.hyperElasticLaw.hyperElasticLaws->GetHyperElasticLaw(this->m_currentLabel), feDisplacement,
319 displacement_per_component,
320 pressure,
321 quadraturePointIndex, linearPart,
322
1/2
✓ Branch 2 taken 126000 times.
✗ Branch 3 not taken.
126000 nonLinearPart, rhsPart, r_instance.hyperElasticLaw.pressureData->IsCompressible());
323 }
324
325
2/4
✓ Branch 1 taken 126000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 126000 times.
✗ Branch 5 not taken.
126000 UBlasMatrix tangentMatrix = linearPart + nonLinearPart;
326
327
1/2
✓ Branch 1 taken 126000 times.
✗ Branch 2 not taken.
126000 elementMatrix.grad_phi_i_GradientBasedHyperElastTensor_grad_phi_j(1., feDisplacement,
328 quadraturePointIndex,
329 tangentMatrix, 0, 0);
330
1/2
✓ Branch 1 taken 126000 times.
✗ Branch 2 not taken.
126000 elementVector.GradientBasedHyperElasticityVector_grad_phi_i(1., feDisplacement,
331 quadraturePointIndex,
332 rhsPart, 0);
333 126000 }
334
335 // Set the source in the case of a volumic force. Surfacic ones are handled differently (through Neumann boundary condition)
336
1/2
✓ Branch 0 taken 42000 times.
✗ Branch 1 not taken.
42000 if (m_typeOfForceApplied == Private::HyperElasticity::volumic) {
337 // Vector operators.
338
2/2
✓ Branch 1 taken 84000 times.
✓ Branch 2 taken 42000 times.
126000 for (int iComp = 0; iComp < this->dimension(); ++iComp)
339
1/2
✓ Branch 1 taken 84000 times.
✗ Branch 2 not taken.
84000 m_elemField.setValueVec(m_force, feDisplacement, iComp);
340
341
1/2
✓ Branch 2 taken 42000 times.
✗ Branch 3 not taken.
42000 elementVector.source(1., feDisplacement, m_elemField, 0, this->dimension());
342 }
343
344 42000 break;
345 42000 }
346 480000 case HyperelasticityNS::dynamic_: {
347
348 // Note: the system matrix and rhs are NOT assembled here: they are calculated afterward within method
349 // computeSystemAfterAssembling() with the matrix calculated below and others calculated beforehand.
350
351 // Assemble the mass matrix in very first dynamic iteration. As it remains constant, it will be kept
352 // unchanged and uncleared throughout the rest of the program lifetime.
353
2/2
✓ Branch 0 taken 8000 times.
✓ Branch 1 taken 472000 times.
480000 if (!is_first_dynamic_iteration_done_) {
354
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 8000 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
8000 FEL_ASSERT(m_elementMat[MatrixNS::mass_per_square_time]);
355 8000 ElementMatrix& elem_mass_matrix = *m_elementMat[MatrixNS::mass_per_square_time];
356
2/4
✓ Branch 1 taken 8000 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 8000 times.
✗ Branch 7 not taken.
8000 elem_mass_matrix.phi_i_phi_j(2. * FelisceParam::instance().volumic_mass / std::pow(m_fstransient->timeStep, 2),
357 8000 feDisplacement, 0, 0, this->dimension());
358 }
359
360
361 // Assemble the new stiffness matrix.
362 480000 std::vector<UBlasVector> displacement_per_component;
363 480000 std::vector<UBlasVector> current_displacement_per_component;
364
365
2/4
✓ Branch 0 taken 240000 times.
✓ Branch 1 taken 240000 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
480000 switch(r_instance.hyperElasticLaw.timeSchemeHyperelasticity) {
366 240000 case midpoint:
367
1/2
✓ Branch 1 taken 240000 times.
✗ Branch 2 not taken.
240000 displacement_per_component = extractDisplacementPerComponent(iel, midpoint_position_, seq_midpoint_position_);
368 240000 break;
369 240000 case half_sum: {
370
1/2
✓ Branch 3 taken 240000 times.
✗ Branch 4 not taken.
240000 displacement_per_component = extractDisplacementPerComponent(iel, evaluationState(), seqEvaluationState());
371
372
2/2
✓ Branch 0 taken 4000 times.
✓ Branch 1 taken 236000 times.
240000 if (!is_first_dynamic_iteration_done_)
373
1/2
✓ Branch 1 taken 4000 times.
✗ Branch 2 not taken.
4000 current_displacement_per_component = extractDisplacementPerComponent(iel, current_displacement_, seq_current_displacement_);
374 240000 break;
375 }
376 case none:
377 break;
378 }
379
380
381
2/2
✓ Branch 0 taken 1440000 times.
✓ Branch 1 taken 480000 times.
1920000 for (int quadraturePointIndex = 0; quadraturePointIndex < NquadraturePoint; ++quadraturePointIndex) {
382
1/2
✓ Branch 1 taken 1440000 times.
✗ Branch 2 not taken.
1440000 UBlasMatrix linearPart;
383
1/2
✓ Branch 1 taken 1440000 times.
✗ Branch 2 not taken.
1440000 UBlasVector rhsPart;
384
385 {
386 using namespace Private::HyperElasticity;
387
2/4
✓ Branch 1 taken 1440000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1440000 times.
✗ Branch 5 not taken.
1440000 calculateLinearAndNonLinearMatrixAndRhs(r_instance.hyperElasticLaw.hyperElasticLaws->GetHyperElasticLaw(this->m_currentLabel),
388 feDisplacement,
389 displacement_per_component,
390 pressure,
391 quadraturePointIndex,
392 linearPart,
393 nonLinearPart,
394 rhsPart,
395
1/2
✓ Branch 2 taken 1440000 times.
✗ Branch 3 not taken.
1440000 r_instance.hyperElasticLaw.pressureData->IsCompressible()
396 );
397 }
398
399
2/4
✓ Branch 1 taken 1440000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1440000 times.
✗ Branch 5 not taken.
1440000 UBlasMatrix tangentMatrix = linearPart + nonLinearPart;
400
401
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1440000 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1440000 FEL_ASSERT(flagMatrixRHS == FlagMatrixRHS::matrix_and_rhs);
402
403
2/4
✓ Branch 0 taken 720000 times.
✓ Branch 1 taken 720000 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1440000 switch(r_instance.hyperElasticLaw.timeSchemeHyperelasticity) {
404 720000 case midpoint: {
405
1/2
✓ Branch 3 taken 720000 times.
✗ Branch 4 not taken.
720000 m_elementMat[MatrixNS::new_stiffness]->grad_phi_i_GradientBasedHyperElastTensor_grad_phi_j(1., feDisplacement,
406 quadraturePointIndex,
407 tangentMatrix, 0, 0);
408
1/2
✓ Branch 1 taken 720000 times.
✗ Branch 2 not taken.
720000 elementVector.GradientBasedHyperElasticityVector_grad_phi_i(1., feDisplacement,
409 quadraturePointIndex,
410 rhsPart, 0);
411 720000 break;
412 }
413 720000 case half_sum: {
414
1/2
✓ Branch 3 taken 720000 times.
✗ Branch 4 not taken.
720000 m_elementMat[MatrixNS::new_stiffness]->grad_phi_i_GradientBasedHyperElastTensor_grad_phi_j(.5, feDisplacement,
415 quadraturePointIndex,
416 tangentMatrix, 0, 0);
417
1/2
✓ Branch 3 taken 720000 times.
✗ Branch 4 not taken.
720000 m_elementVector[VectorNS::new_stiffness]->GradientBasedHyperElasticityVector_grad_phi_i(1., feDisplacement,
418 quadraturePointIndex,
419 rhsPart, 0);
420
421
422
423
2/2
✓ Branch 0 taken 12000 times.
✓ Branch 1 taken 708000 times.
720000 if (!is_first_dynamic_iteration_done_) {
424 {
425 using namespace Private::HyperElasticity;
426
2/4
✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12000 times.
✗ Branch 5 not taken.
12000 calculateLinearAndNonLinearMatrixAndRhs(r_instance.hyperElasticLaw.hyperElasticLaws->GetHyperElasticLaw(this->m_currentLabel), feDisplacement,
427 current_displacement_per_component,
428 pressure,
429 quadraturePointIndex,
430 linearPart, nonLinearPart,
431 rhsPart,
432
1/2
✓ Branch 2 taken 12000 times.
✗ Branch 3 not taken.
12000 r_instance.hyperElasticLaw.pressureData->IsCompressible()
433 );
434 }
435
436
2/4
✓ Branch 1 taken 12000 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12000 times.
✗ Branch 5 not taken.
12000 tangentMatrix = linearPart + nonLinearPart;
437
438
439
1/2
✓ Branch 3 taken 12000 times.
✗ Branch 4 not taken.
12000 m_elementMat[MatrixNS::current_stiffness]->grad_phi_i_GradientBasedHyperElastTensor_grad_phi_j(.5, feDisplacement,
440 quadraturePointIndex,
441 tangentMatrix, 0, 0);
442
443
1/2
✓ Branch 3 taken 12000 times.
✗ Branch 4 not taken.
12000 m_elementVector[VectorNS::current_stiffness]->GradientBasedHyperElasticityVector_grad_phi_i(1., feDisplacement,
444 quadraturePointIndex,
445 rhsPart, 0);
446 }
447 720000 break;
448 }
449 case none:
450 break;
451 }
452 1440000 }
453 480000 break;
454
455 480000 }
456
457 } // switch(system_)
458 522000 }
459
460 /***********************************************************************************/
461 /***********************************************************************************/
462
463 1044 void LinearProblemHyperElasticity::preSNESAssembleAdditional()
464 {
465 // Retrieve the instance
466 1044 const auto& r_instance = FelisceParam::instance();
467
468 using namespace HyperelasticityNS;
469
470 // clearMatrixRHS(); useless: already performed in preSNESAssemble()
471 1044 clearMatrix(MatrixNS::new_stiffness);
472
473
2/4
✓ Branch 0 taken 508 times.
✓ Branch 1 taken 536 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1044 switch(r_instance.hyperElasticLaw.timeSchemeHyperelasticity) {
474 508 case midpoint: {
475
476 {
477 508 midpoint_position_.copyFrom(current_displacement_);
478 508 midpoint_position_.axpy(1., evaluationState());
479 508 midpoint_position_.scale(0.5);
480 }
481
482 {
483 508 gatherVector(midpoint_position_, seq_midpoint_position_);
484 }
485 508 break;
486 }
487 536 case half_sum: {
488 536 clearVector(VectorNS::new_stiffness);
489 536 break;
490 }
491 case none:
492 break;
493 }
494 1044 }
495
496 /***********************************************************************************/
497 /***********************************************************************************/
498
499 1044 void LinearProblemHyperElasticity::computeSystemAfterAssembling()
500 {
501 // Retrieve the instance
502 1044 const auto& r_instance = FelisceParam::instance();
503
504
2/2
✓ Branch 0 taken 960 times.
✓ Branch 1 taken 84 times.
1044 if (system_ == HyperelasticityNS::dynamic_) {
505 using namespace HyperelasticityNS;
506
507 // In the very first dynamic iteration the mass matrices are assembled once and for all.
508
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 944 times.
960 if (!is_first_dynamic_iteration_done_)
509 16 SetFirstDynamicIterationDone();
510
511 // Now all elements are settled to build the system.
512 {
513 // Tangent
514 960 matrix(MatrixNS::system).copyFrom(matrix(MatrixNS::mass_per_square_time), SAME_NONZERO_PATTERN);
515
516
2/4
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 480 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
960 switch(r_instance.hyperElasticLaw.timeSchemeHyperelasticity) {
517 480 case midpoint: {
518 480 matrix(MatrixNS::system).axpy(0.5, matrix(MatrixNS::new_stiffness), SAME_NONZERO_PATTERN);
519 480 break;
520 }
521 480 case half_sum: {
522 480 matrix(MatrixNS::system).axpy(1., matrix(MatrixNS::new_stiffness), SAME_NONZERO_PATTERN);
523 480 matrix(MatrixNS::system).axpy(1., matrix(MatrixNS::current_stiffness), SAME_NONZERO_PATTERN);
524 480 break;
525 }
526 case none:
527 break;
528 }
529 }
530
531 {
532 // Residual
533
1/2
✓ Branch 1 taken 960 times.
✗ Branch 2 not taken.
960 PetscVector vector;
534
1/2
✓ Branch 1 taken 960 times.
✗ Branch 2 not taken.
960 vector.duplicateFrom(current_displacement_);
535 // < the contribution to RHS of current displacement term.
536
537
1/2
✓ Branch 2 taken 960 times.
✗ Branch 3 not taken.
960 vector.copyFrom(evaluationState());
538
1/2
✓ Branch 1 taken 960 times.
✗ Branch 2 not taken.
960 vector.axpy(-1., current_displacement_);
539
1/2
✓ Branch 2 taken 960 times.
✗ Branch 3 not taken.
960 vector.axpy(-m_fstransient->timeStep, current_velocity_);
540
541
1/2
✓ Branch 1 taken 960 times.
✗ Branch 2 not taken.
960 PetscVector dynamic_contribution_to_rhs;
542
1/2
✓ Branch 2 taken 960 times.
✗ Branch 3 not taken.
960 dynamic_contribution_to_rhs.duplicateFrom(this->vector());
543
1/2
✓ Branch 2 taken 960 times.
✗ Branch 3 not taken.
960 mult(matrix(MatrixNS::mass_per_square_time), vector, dynamic_contribution_to_rhs);
544
545
1/2
✓ Branch 2 taken 960 times.
✗ Branch 3 not taken.
960 this->vector().axpy(1., dynamic_contribution_to_rhs);
546
547
548
2/4
✓ Branch 0 taken 480 times.
✓ Branch 1 taken 480 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
960 switch(r_instance.hyperElasticLaw.timeSchemeHyperelasticity) {
549 480 case midpoint:
550 480 break;
551 480 case half_sum: {
552
1/2
✓ Branch 3 taken 480 times.
✗ Branch 4 not taken.
480 this->vector().axpy(1., this->vector(VectorNS::new_stiffness));
553
1/2
✓ Branch 3 taken 480 times.
✗ Branch 4 not taken.
480 this->vector().axpy(1., this->vector(VectorNS::current_stiffness));
554 480 break;
555 }
556 case none:
557 break;
558 }
559 960 }
560 }
561 1044 }
562
563 /***********************************************************************************/
564 /***********************************************************************************/
565
566 526000 std::vector<UBlasVector> LinearProblemHyperElasticity::extractDisplacementPerComponent(
567 PetscInt iel,
568 PetscVector& mpi_vector,
569 PetscVector& seq_vector) const
570 {
571
1/2
✓ Branch 3 taken 526000 times.
✗ Branch 4 not taken.
526000 std::vector<UBlasVector> ret(this->dimension());
572
573
2/2
✓ Branch 1 taken 1052000 times.
✓ Branch 2 taken 526000 times.
1578000 for (int iComp = 0; iComp < this->dimension(); ++iComp) {
574
2/4
✓ Branch 1 taken 1052000 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1052000 times.
✗ Branch 6 not taken.
1052000 ret[iComp] = extractUnknownValue(m_iDisplacement, iComp, m_currentElementType, iel, mpi_vector, seq_vector);
575 }
576
577 526000 return ret;
578 }
579
580 /***********************************************************************************/
581 /***********************************************************************************/
582
583 inline UBlasVector LinearProblemHyperElasticity::extractPressure(
584 PetscInt iel,
585 PetscVector& mpi_vector,
586 PetscVector& seq_vector) const
587 {
588 // Retrieve the instance
589 const auto& r_instance = FelisceParam::instance();
590
591 FEL_ASSERT(r_instance.hyperElasticLaw.pressureData->IsCompressible());
592
593 return extractUnknownValue(r_instance.hyperElasticLaw.pressureData->IndexPressure(), 0, m_currentElementType, iel, mpi_vector, seq_vector);
594 }
595
596 /***********************************************************************************/
597 /***********************************************************************************/
598
599 1052000 UBlasVector LinearProblemHyperElasticity::extractUnknownValue(std::size_t index_unknown, std::size_t iComp, ElementType eltType,
600 std::size_t iel, PetscVector& mpi_vector, PetscVector& seq_vector) const
601 {
602 1052000 const SupportDofMesh& support = m_supportDofUnknown[index_unknown];
603
604 PetscInt id_element_support;
605
1/2
✓ Branch 1 taken 1052000 times.
✗ Branch 2 not taken.
1052000 support.getIdElementSupport(eltType, iel, id_element_support);
606
607 1052000 const std::size_t Nlocal_support_dof = static_cast<std::size_t>(support.getNumSupportDof(id_element_support));
608
609
1/2
✓ Branch 1 taken 1052000 times.
✗ Branch 2 not taken.
1052000 UBlasVector ret(Nlocal_support_dof);
610 PetscInt index_global_dof;
611
612
2/2
✓ Branch 0 taken 6312000 times.
✓ Branch 1 taken 1052000 times.
7364000 for (std::size_t iSupport = 0; iSupport < Nlocal_support_dof; ++iSupport) {
613
1/2
✓ Branch 1 taken 6312000 times.
✗ Branch 2 not taken.
6312000 m_dof.loc2glob(id_element_support, iSupport, index_unknown, iComp, index_global_dof);
614
615 PetscInt index_local_dof;
616
617 // m_mappingNodes is an empirical guess: it is the one that works not stupidly, ie returns a valid index if the dof is on current processor...
618 // DEV I'm not sure it will work with two variables, but the support that seems more logical failed utterly...
619
1/2
✓ Branch 1 taken 6312000 times.
✗ Branch 2 not taken.
6312000 ISGlobalToLocalMappingApply(m_mappingNodes,
620 IS_GTOLM_MASK,
621 1, &index_global_dof,
622 FELISCE_PETSC_NULLPTR, &index_local_dof);
623
624 # ifndef NDEBUG
625 PetscInt localSize;
626
1/2
✓ Branch 1 taken 6312000 times.
✗ Branch 2 not taken.
6312000 mpi_vector.getLocalSize(&localSize);
627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6312000 times.
6312000 if (index_local_dof >= localSize) {
628 int rank;
629 MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
630 std::cerr << '[' << rank << "] Dof index = " << index_local_dof
631 << " should be lower than local displacement size which "
632 "is " << localSize << std::endl;
633 FEL_ASSERT(false);
634 }
635 # endif // NDEBUG
636
637 // DEV \todo These indexes should be accessible locally with the use of ghost vertices...
638
2/2
✓ Branch 0 taken 103096 times.
✓ Branch 1 taken 6208904 times.
6312000 if (index_local_dof == -1) {
639 // Case in which the values aren't stored on the current processor... I must fetch the global value!!!!
640 PetscScalar * seq_vector_array;
641
1/2
✓ Branch 1 taken 103096 times.
✗ Branch 2 not taken.
103096 seq_vector.getArray(&seq_vector_array);
642
1/2
✓ Branch 1 taken 103096 times.
✗ Branch 2 not taken.
103096 AOApplicationToPetsc(m_ao, 1, &index_global_dof);
643
1/2
✓ Branch 1 taken 103096 times.
✗ Branch 2 not taken.
103096 ret(iSupport) = seq_vector_array[index_global_dof];
644
1/2
✓ Branch 1 taken 103096 times.
✗ Branch 2 not taken.
103096 seq_vector.restoreArray(&seq_vector_array);
645 } else {
646 PetscScalar* mpi_vector_array;
647
1/2
✓ Branch 1 taken 6208904 times.
✗ Branch 2 not taken.
6208904 mpi_vector.getArray(&mpi_vector_array);
648
1/2
✓ Branch 1 taken 6208904 times.
✗ Branch 2 not taken.
6208904 ret(iSupport) = mpi_vector_array[index_local_dof];
649
1/2
✓ Branch 1 taken 6208904 times.
✗ Branch 2 not taken.
6208904 mpi_vector.restoreArray(&mpi_vector_array);
650 }
651 }
652
653 2104000 return ret;
654 }
655
656 /***********************************************************************************/
657 /***********************************************************************************/
658
659 void LinearProblemHyperElasticity::computeElementArrayBoundaryCondition(
660 const std::vector<Point*>& elemPoint,
661 const std::vector<felInt>& elemIdPoint,
662 int& iel, FlagMatrixRHS flagMatrixRHS)
663 {
664 IGNORE_UNUSED_IEL;
665 IGNORE_UNUSED_ELEM_ID_POINT;
666
667 switch(flagMatrixRHS) {
668 case FlagMatrixRHS::only_rhs:
669 case FlagMatrixRHS::matrix_and_rhs: {
670 CurvilinearFiniteElement& feCurvDisplacement = *m_listCurvilinearFiniteElement[m_iDisplacement];
671 feCurvDisplacement.updateMeasNormal(0, elemPoint);
672
673 // Below: only when spatial function
674 if (m_boundaryConditionList.NeumannNormal(0)->typeValueBC() == FunctionS) {
675 {
676 const int component_index = 0;
677 m_elemFieldNeumannNormal[0].setValueVec(m_force, feCurvDisplacement, component_index);
678
679 // Important: in my first approach I added the following line, to mimic what was done in volumic force case:
680 //m_elemVecBD->source(1., feCurvDisplacement, m_elemFieldNeumannNormal[0], block, Ncomponent);
681 // It was wrong: the source was added more properly in applyNaturalBoundaryCondition()
682 }
683 }
684 break;
685 }
686 case FlagMatrixRHS::only_matrix:
687 break;
688 }
689 }
690
691 /***********************************************************************************/
692 /***********************************************************************************/
693
694 16 void LinearProblemHyperElasticity::GoToDynamic()
695 {
696 16 system_ = HyperelasticityNS::dynamic_;
697 16 UpdateDisplacementBetweenTimeStep();
698 16 }
699
700 /***********************************************************************************/
701 /***********************************************************************************/
702
703 320 void LinearProblemHyperElasticity::endIteration()
704 {
705 // Retrieve the instance
706 320 const auto& r_instance = FelisceParam::instance();
707
708 // First update velocities.
709 {
710
1/2
✓ Branch 1 taken 320 times.
✗ Branch 2 not taken.
320 current_velocity_.scale(-1.);
711
1/2
✓ Branch 1 taken 320 times.
✗ Branch 2 not taken.
320 PetscVector diff_displ;
712
1/2
✓ Branch 2 taken 320 times.
✗ Branch 3 not taken.
320 diff_displ.duplicateFrom(this->solution());
713 {
714
1/2
✓ Branch 2 taken 320 times.
✗ Branch 3 not taken.
320 diff_displ.copyFrom(this->solution());
715
1/2
✓ Branch 1 taken 320 times.
✗ Branch 2 not taken.
320 diff_displ.axpy(-1., current_displacement_);
716
1/2
✓ Branch 2 taken 320 times.
✗ Branch 3 not taken.
320 diff_displ.scale(2. / m_fstransient->timeStep);
717 }
718
1/2
✓ Branch 1 taken 320 times.
✗ Branch 2 not taken.
320 current_velocity_.axpy(1., diff_displ);
719 320 }
720
721 // Then update displacement.
722 320 UpdateDisplacementBetweenTimeStep();
723
724 using namespace HyperelasticityNS;
725
726
2/4
✓ Branch 0 taken 160 times.
✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
320 switch(r_instance.hyperElasticLaw.timeSchemeHyperelasticity) {
727 160 case midpoint:
728 160 break;
729 160 case half_sum:
730 160 matrix(MatrixNS::current_stiffness).copyFrom(matrix(MatrixNS::new_stiffness),SAME_NONZERO_PATTERN);
731 160 vector(VectorNS::current_stiffness).copyFrom(vector(VectorNS::new_stiffness));
732 160 break;
733 case none:
734 break;
735 }
736 320 }
737
738 /***********************************************************************************/
739 /***********************************************************************************/
740
741 16 inline void LinearProblemHyperElasticity::SetFirstDynamicIterationDone()
742 {
743
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
16 FEL_ASSERT(!is_first_dynamic_iteration_done_ && "Should only be called once!");
744 16 is_first_dynamic_iteration_done_ = true;
745 16 }
746
747 /***********************************************************************************/
748 /***********************************************************************************/
749
750 336 inline void LinearProblemHyperElasticity::UpdateDisplacementBetweenTimeStep()
751 {
752 336 current_displacement_.copyFrom(this->solution());
753 336 gatherSolution();
754 336 seq_current_displacement_.copyFrom(this->sequentialSolution());
755 336 }
756
757 }
758