GCC Code Coverage Report


Directory: ./
File: Solver/linearProblemElasticity.cpp
Date: 2024-04-14 07:32:34
Exec Total Coverage
Lines: 201 235 85.5%
Branches: 154 330 46.7%

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 #include <numeric>
17 #include <cmath>
18
19 // External includes
20 #include "Core/NoThirdPartyWarning/Petsc/mat.hpp"
21
22 // Project includes
23 #include "linearProblemElasticity.hpp"
24 #include "Core/felisceTools.hpp"
25 #include "Core/felisceTransient.hpp"
26 #include "Geometry/geometricMeshRegion.hpp"
27 #include "FiniteElement/elementMatrix.hpp"
28 #include "FiniteElement/elementVector.hpp"
29 #include "DegreeOfFreedom/boundaryCondition.hpp"
30
31 namespace felisce
32 {
33
34 namespace { // anonymous
35
36 enum KinematicParameter2D {
37 planeStress = 1,
38 planeStrain = 2
39 };
40
41 /*!
42 * \brief Matrix defined so that strain = Gradient2Strain x gradient(displacement)
43 *
44 * No definition provided on purpose: this function is intended to be specialized
45 */
46 template<int DimensionT>
47 UBlasMatrix Gradient2Strain();
48
49
50 /*!
51 * \brief Engineering elasticity tensor
52 *
53 *
54 * \param[in] E Young modulus
55 * \param[in] nu Poisson coefficient
56 */
57 UBlasMatrix EngineeringElastTensor_2D(double E, double nu, int kinematic_param);
58
59 UBlasMatrix EngineeringElastTensor_3D(double E, double nu);
60
61 //! Initialize operator GradientBasedElastTensor
62 UBlasMatrix InitializeGradientBasedElastTensor(int dimension);
63
64 //! Assign the type of force applied from the integer read in the data file
65 ElasticityNS::ForceType AssignForceType(int data_parameter);
66
67
68 class ErrorInvalidVolumicMass : public std::exception {
69 public:
70 //! Constructor
71 ErrorInvalidVolumicMass();
72
73 //! Destructor.
74 ~ErrorInvalidVolumicMass() noexcept override = default;
75
76 //! Copy constructor, to avoid warning due to user-declared destructor.
77 ErrorInvalidVolumicMass(const ErrorInvalidVolumicMass&) = default;
78
79 //! what() overload
80 const char* what() const noexcept override;
81
82 private:
83
84 //! Message to be displayed by what()
85 std::string m_message;
86 };
87
88 } // namespace anonymous
89
90 36 LinearProblemElasticityDynamic::LinearProblemElasticityDynamic(SpatialForce force)
91 : LinearProblem("Dynamic elasticity equation"),
92 36 m_feDisplacement(nullptr),
93
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 m_force(force),
94 36 transient_parameters_(nullptr),
95
6/12
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 36 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 36 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 36 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 36 times.
✗ Branch 20 not taken.
72 system_(ElasticityNS::static_)
96 {
97
98 36 }
99
100 /***********************************************************************************/
101 /***********************************************************************************/
102
103 96 LinearProblemElasticityDynamic::~LinearProblemElasticityDynamic()
104 = default;
105
106 /***********************************************************************************/
107 /***********************************************************************************/
108
109 36 void LinearProblemElasticityDynamic::initialize(std::vector<GeometricMeshRegion::Pointer>& mesh, FelisceTransient::Pointer fstransient, MPI_Comm& comm, bool doUseSNES)
110 {
111
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
36 FEL_ASSERT(doUseSNES && "Should be true!!!");
112
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 LinearProblem::initialize(mesh, comm, doUseSNES);
113
114 36 transient_parameters_ = fstransient;
115
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
36 m_typeOfForceApplied = AssignForceType(FelisceParam::instance().volumicOrSurfacicForce);
116
117
1/2
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 std::vector<PhysicalVariable> listVariable(1);
118
1/2
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
36 std::vector<std::size_t> listNumComp(1);
119 36 listVariable[0] = displacement;
120 36 listNumComp[0] = this->dimension();
121
122
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 m_listUnknown.push_back(displacement);
123
124
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 definePhysicalVariable(listVariable,listNumComp); // Must be called after m_listUnknown is initialized
125
126
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 setNumberOfMatrix(3);
127
128
2/4
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 36 times.
✗ Branch 7 not taken.
36 m_gradientBasedElastTensor = std::move(InitializeGradientBasedElastTensor(this->dimension()));
129
130
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 const double volumic_mass = FelisceParam::instance().volumic_mass;
131
132
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (volumic_mass < 0.)
133 throw ErrorInvalidVolumicMass();
134
135
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
36 FEL_ASSERT(fstransient->timeStep > 1.e-10);
136 36 }
137
138 /***********************************************************************************/
139 /***********************************************************************************/
140
141 37 void LinearProblemElasticityDynamic::initPerElementType(ElementType eltType, FlagMatrixRHS flagMatrixRHS)
142 {
143 IGNORE_UNUSED_ELT_TYPE;
144 IGNORE_UNUSED_FLAG_MATRIX_RHS;
145 37 m_iDisplacement = m_listVariable.getVariableIdList(displacement);
146 37 m_feDisplacement = m_listCurrentFiniteElement[m_iDisplacement];
147
148 37 m_elemField.initialize(QUAD_POINT_FIELD, *m_feDisplacement, this->dimension());
149 37 }
150
151 /***********************************************************************************/
152 /***********************************************************************************/
153
154 36 void LinearProblemElasticityDynamic::InitializeDerivedAttributes()
155 {
156 // Check here there are no Neumann or NeumannNormal boundary conditions in the case of the volumic force
157 // (it is not stricto sensu a limitation, so it could be lifted later, but at the moment it is a good way
158 // to make sure there is no mishap in the data parameter file, in which we could apply both volumic and
159 // surfacic force without being aware of it.)
160
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 4 times.
36 if (m_typeOfForceApplied == ElasticityNS::volumic) {
161
3/6
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 32 times.
32 if (m_boundaryConditionList.numNeumannBoundaryCondition() || m_boundaryConditionList.numNeumannNormalBoundaryCondition()) {
162 FEL_ERROR("Neumann condition found along with a volumic force; it is not allowed at the moment. "
163 "Check there is no mishap in your data file.");
164 }
165 }
166
167 36 current_displacement_.duplicateFrom(this->solution());
168 36 current_velocity_.duplicateFrom(this->solution());
169
170 36 current_velocity_.zeroEntries();
171 36 current_displacement_.zeroEntries();
172 36 }
173
174 /***********************************************************************************/
175 /***********************************************************************************/
176
177 4209 void LinearProblemElasticityDynamic::computeElementArray(const std::vector<Point*>& elemPoint,
178 const std::vector<felInt>& elemIdPoint,
179 int& iel, FlagMatrixRHS flagMatrixRHS) {
180 IGNORE_UNUSED_FLAG_MATRIX_RHS;
181 IGNORE_UNUSED_IEL;
182 IGNORE_UNUSED_ELEM_ID_POINT;
183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4209 times.
4209 FEL_ASSERT(m_feDisplacement);
184
185
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4209 times.
4209 FEL_ASSERT(this->numberOfMatrices() == 3);
186
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 4209 times.
4209 FEL_ASSERT(static_cast<std::size_t>(this->numberOfMatrices()) == m_elementMat.size());
187
188 4209 CurrentFiniteElement& feDisplacement = *m_feDisplacement; // alias
189
190 4209 feDisplacement.updateFirstDeriv(0, elemPoint);
191
192
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4209 times.
4209 FEL_ASSERT(transient_parameters_);
193 4209 const FelisceTransient& transient_param = *transient_parameters_;
194
195 // First iteration is static case.
196
2/3
✓ Branch 0 taken 4149 times.
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
4209 switch(system_) {
197 4149 case ElasticityNS::static_: {
198
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4149 times.
4149 FEL_ASSERT(transient_param.iteration >= 0);
199
1/2
✓ Branch 0 taken 4149 times.
✗ Branch 1 not taken.
4149 if (transient_param.iteration == 0) {
200 // Matrix operators.
201 4149 m_elementMat[0]->grad_phi_i_GradientBasedElastTensor_grad_phi_j(1.0, feDisplacement, m_gradientBasedElastTensor, 0, 0);
202
203 // Set the source in the case of a volumic force. Surfacic ones are handled differently (through Neumann boundary condition)
204
2/2
✓ Branch 0 taken 2149 times.
✓ Branch 1 taken 2000 times.
4149 if (m_typeOfForceApplied == ElasticityNS::volumic) {
205 // Vector operators.
206
2/2
✓ Branch 1 taken 4438 times.
✓ Branch 2 taken 2149 times.
6587 for (int iComp = 0; iComp < this->dimension(); ++iComp)
207 4438 m_elemField.setValueVec(m_force, feDisplacement, iComp);
208
209 2149 m_elementVector[0]->source(1., feDisplacement, m_elemField, 0, this->dimension());
210 }
211 }
212 4149 break;
213 }
214 60 case ElasticityNS::dynamic_: {
215 // Matrix operators.
216
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 60 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
60 FEL_ASSERT(m_elementMat[0]);
217 60 ElementMatrix& complete_matrix = *m_elementMat[0];
218
219
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 ElementMatrix mass_matrix;
220
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 ElementMatrix half_stiffness_matrix; // stiffness matrix multiplied by 0.5
221
222 // Calculate mass and stiffness element matrix
223 {
224
225
1/2
✓ Branch 3 taken 60 times.
✗ Branch 4 not taken.
60 mass_matrix.duplicateFrom(*m_elementMat[0]);
226
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 half_stiffness_matrix.duplicateFrom(mass_matrix);
227
228
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 half_stiffness_matrix.grad_phi_i_GradientBasedElastTensor_grad_phi_j(0.5, feDisplacement, m_gradientBasedElastTensor, 0, 0);
229
1/2
✓ Branch 2 taken 60 times.
✗ Branch 3 not taken.
60 mass_matrix.phi_i_phi_j(1., feDisplacement, 0, 0, this->dimension());
230 }
231
232 // Calculate coefficients used in Newmark scheme.
233
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
60 FEL_ASSERT(transient_param.timeStep > 1.e-10);
234 60 const double inv_time_step = 1. / transient_param.timeStep;
235
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 const double velocity_mass_coefficient = 2. * FelisceParam::instance().volumic_mass * inv_time_step;
236 60 const double displacement_mass_coefficient = velocity_mass_coefficient * inv_time_step;
237
238 // Build the system matrix
239
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 complete_matrix = mass_matrix;
240
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 complete_matrix *= displacement_mass_coefficient;
241
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 complete_matrix += half_stiffness_matrix;
242
243 // Now we must take into account the terms related to previous iteration.
244 // We must for that fill two other matrixes: one for the displacement from previous iteration and the other
245 // for the velocity. Once assembled, these matrixes will be multiplied by the vectors from previous iteration
246 // and the RHS will hence be evaluated.
247 60 ElementMatrix& current_displacement_matrix = *m_elementMat[ElasticityNS::current_displacement];
248
249
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 current_displacement_matrix = mass_matrix;
250
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 current_displacement_matrix *= displacement_mass_coefficient;
251
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 current_displacement_matrix -= half_stiffness_matrix;
252
253 60 ElementMatrix& current_velocity_matrix = *m_elementMat[ElasticityNS::current_velocity];
254
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 current_velocity_matrix = mass_matrix;
255
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 current_velocity_matrix *= velocity_mass_coefficient;
256 60 break;
257 60 }
258 } // switch
259 4209 }
260
261 /***********************************************************************************/
262 /***********************************************************************************/
263
264 120 void LinearProblemElasticityDynamic::ComputeRHS()
265 {
266
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 PetscVector buf;
267
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 buf.duplicateFrom(current_displacement_);
268
269
1/2
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
120 mult(matrix(ElasticityNS::current_displacement), current_displacement_, buf);
270
1/2
✓ Branch 3 taken 120 times.
✗ Branch 4 not taken.
120 multAdd(matrix(ElasticityNS::current_velocity), current_velocity_, buf, vector());
271 120 }
272
273 /***********************************************************************************/
274 /***********************************************************************************/
275
276 void LinearProblemElasticityDynamic::computeElementArrayBoundaryCondition(const std::vector<Point*>& elemPoint,
277 const std::vector<felInt>& elemIdPoint,
278 int& iel, FlagMatrixRHS flagMatrixRHS)
279 {
280 IGNORE_UNUSED_FLAG_MATRIX_RHS;
281 IGNORE_UNUSED_IEL;
282 IGNORE_UNUSED_ELEM_ID_POINT;
283
284 CurvilinearFiniteElement& feCurvDisplacement = *m_listCurvilinearFiniteElement[m_iDisplacement];
285 feCurvDisplacement.updateMeasNormal(0, elemPoint);
286
287 // Below: only when spatial function
288 const BoundaryCondition& neumann_condition = *m_boundaryConditionList.Neumann(0);
289
290 if (neumann_condition.typeValueBC() == FunctionS) {
291 const auto& comp_list = neumann_condition.getComp();
292
293 for (auto component_index : comp_list) { // more efficient.
294 m_elemFieldNeumann[0].setValueVec(m_force, feCurvDisplacement, component_index);
295 }
296 // Important: in my first approach I added the following line, to mimic what was done in volumic force case:
297 //m_elemVecBD->source(1., feCurvDisplacement, m_elemFieldNeumannNormal[0], block, Ncomponent);
298 // It was wrong: the source was added more properly in applyNaturalBoundaryCondition()
299 }
300 }
301
302 /***********************************************************************************/
303 /***********************************************************************************/
304
305 120 void LinearProblemElasticityDynamic::endIteration()
306 {
307 PetscInt size;
308
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 current_displacement_.getLocalSize(&size);
309
310
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 PetscInt NdofLocalPerUnknown = numDofLocalPerUnknown(displacement);
311
312
1/2
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
120 std::vector<PetscInt> local_indexing(NdofLocalPerUnknown); // std::vector that contains integers from 0 to local size - 1
313
314 // std::iota(local_indexing.begin(), local_indexing.end(), 0);
315
316
2/2
✓ Branch 0 taken 17010 times.
✓ Branch 1 taken 120 times.
17130 for (int i = 0; i < NdofLocalPerUnknown; ++i) // substitute that also works in C++ 98 (arguably more easy to understand anyway)
317 17010 local_indexing[i] = i;
318
319 120 double vel_min = 1.e20;
320 120 double vel_max = -1.e20;
321 120 double disp_current_min = 1.e20;
322 120 double disp_current_max = -1.e20;
323 120 double disp_new_min = 1.e20;
324 120 double disp_new_max = -1.e20;
325
326 {
327 PetscScalar * solution;
328
1/2
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
120 this->solution().getArray(&solution);
329
330 PetscScalar * displacement_prev;
331
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 current_displacement_.getArray(&displacement_prev);
332
333 PetscScalar * my_velocity;
334
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 current_velocity_.getArray(&my_velocity);
335
336
2/2
✓ Branch 0 taken 17010 times.
✓ Branch 1 taken 120 times.
17130 for (PetscInt i = 0; i < size; ++i) {
337 17010 my_velocity[i] *= -1.;
338 17010 my_velocity[i] += 2. / transient_parameters_->timeStep * (solution[i] - displacement_prev[i]);
339 17010 vel_min = std::min(vel_min, my_velocity[i]);
340 17010 vel_max = std::max(vel_max, my_velocity[i]);
341 17010 disp_current_min = std::min(disp_current_min, displacement_prev[i]);
342 17010 disp_current_max = std::max(disp_current_max, displacement_prev[i]);
343 }
344
345
1/2
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
120 this->solution().restoreArray(&solution);
346
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 current_displacement_.restoreArray(&displacement_prev);
347
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 current_velocity_.restoreArray(&my_velocity);
348 }
349
350
5/10
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 120 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 120 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 120 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 120 times.
✗ Branch 14 not taken.
120 std::cout << "Displ prev [min, max] = [" << disp_current_min << ", " << disp_current_max << "]\n";
351
5/10
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 120 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 120 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 120 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 120 times.
✗ Branch 14 not taken.
120 std::cout << "Velocities [min, max] = [" << vel_min << ", " << vel_max << "]\n";
352
353 // Make sure to do that after the velocity calculation!
354
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 UpdateCurrentDisplacement();
355
356 {
357 PetscScalar * displacement_new;
358
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 current_displacement_.getArray(&displacement_new);
359
360
2/2
✓ Branch 0 taken 17010 times.
✓ Branch 1 taken 120 times.
17130 for (PetscInt i = 0u; i < size; ++i) {
361 17010 disp_new_min = std::min(disp_new_min, displacement_new[i]);
362 17010 disp_new_max = std::max(disp_new_max, displacement_new[i]);
363 }
364
365
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 current_displacement_.restoreArray(&displacement_new);
366
367 }
368
369
5/10
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 120 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 120 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 120 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 120 times.
✗ Branch 14 not taken.
120 std::cout << "Displ new [min, max] = [" << disp_new_min << ", " << disp_new_max << "]\n";
370 120 }
371
372 /***********************************************************************************/
373 /***********************************************************************************/
374
375 156 void LinearProblemElasticityDynamic::UpdateCurrentDisplacement() {
376 156 current_displacement_.copyFrom(this->solution());
377 156 }
378
379 /***********************************************************************************/
380 /***********************************************************************************/
381
382 4 void LinearProblemElasticityDynamic::GoToDynamic() {
383 4 system_ = ElasticityNS::dynamic_;
384 4 }
385
386 /***********************************************************************************/
387 /***********************************************************************************/
388
389 namespace { // anonymous
390
391 template<>
392 20 UBlasMatrix Gradient2Strain<3>() {
393 20 UBlasMatrix ret(6, 9);
394
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ret.clear();
395
396
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ret(0, 0) = 1.;
397
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ret(1, 4) = 1.;
398
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ret(2, 8) = 1.;
399
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ret(3, 1) = 1.;
400
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ret(3, 3) = 1.;
401
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ret(4, 5) = 1.;
402
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ret(4, 7) = 1.;
403
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ret(5, 2) = 1.;
404
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ret(5, 6) = 1.;
405
406 20 return ret;
407 }
408
409 /***********************************************************************************/
410 /***********************************************************************************/
411
412 template<>
413 16 UBlasMatrix Gradient2Strain<2>() {
414 16 UBlasMatrix ret(3, 4);
415
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ret.clear();
416
417
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ret(0, 0) = 1.;
418
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ret(1, 3) = 1.;
419
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ret(2, 1) = 1.;
420
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ret(2, 2) = 1.;
421
422 16 return ret;
423 }
424
425 /***********************************************************************************/
426 /***********************************************************************************/
427
428 20 UBlasMatrix EngineeringElastTensor_3D(const double E, const double nu)
429 {
430
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 UBlasMatrix ret(6, 6);
431
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ret.clear();
432
433
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
20 ret(0, 0) = ret(1, 1) = ret(2, 2) = 1.;
434
435 20 const double inv = 1. / (1. - nu);
436
3/6
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 20 times.
✗ Branch 8 not taken.
20 ret(3, 3) = ret(4, 4) = ret(5, 5) = 0.5 * (1. - 2. * nu) * inv;
437
438 {
439 20 const double non_diag_value = nu * inv;
440
441
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 20 times.
80 for (std::size_t i = 0u; i < 3u; ++i) {
442
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 60 times.
120 for (std::size_t j = i + 1u; j < 3u; ++j)
443
2/4
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 60 times.
✗ Branch 5 not taken.
60 ret(i, j) = ret(j, i) = non_diag_value;
444 }
445 }
446
447 20 const double factor = E * (1. - nu) / ((1. + nu) * (1. - 2. * nu));
448
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ret *= factor;
449
450 40 return ret;
451 }
452
453 /***********************************************************************************/
454 /***********************************************************************************/
455
456 16 UBlasMatrix EngineeringElastTensor_2D(const double E, const double nu, const int kinematic_param)
457 {
458 16 UBlasMatrix ret(3, 3);
459
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ret.clear();
460
461
1/3
✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 switch(kinematic_param) {
462 case planeStress: {
463 ret(0, 0) = 1.;
464 ret(1, 1) = 1.;
465 ret(2, 2) = 0.5 * (1. - nu);
466 ret(0, 1) = nu;
467 ret(1, 0) = nu;
468
469 const double factor = E / (1. - std::pow(nu, 2));
470 ret *= factor;
471
472 return ret;
473 }
474 16 case planeStrain: {
475 16 const double inv = 1. / (1. - nu);
476
477
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ret(0, 0) = 1.;
478
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ret(1, 1) = 1.;
479
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ret(2, 2) = 0.5 * inv * (1. - 2. * nu);
480
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ret(0, 1) = nu * inv;
481
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ret(1, 0) = nu * inv;
482
483 16 const double factor = E * (1. - nu) / ((1. + nu) * (1. - 2 * nu));
484
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 ret *= factor;
485
486 16 return ret;
487 }
488 }
489
490 FEL_ERROR("SHOULD NEVER BE REACHED!!!");
491 return ret; // to avoid warning
492 }
493
494 /***********************************************************************************/
495 /***********************************************************************************/
496
497 36 UBlasMatrix InitializeGradientBasedElastTensor(const int dimension)
498 {
499
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
36 UBlasMatrix engineering_elast_tensor, gradient_2_strain;
500
501 // Use Poisson coefficient and Young modulus read in the input parameter file
502
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 const double nu = FelisceParam::instance().poisson;
503
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 const double E = FelisceParam::instance().young;
504
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 const int kinematic_parameter = FelisceParam::instance().planeStressStrain;
505
506
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
36 if (kinematic_parameter != planeStrain && kinematic_parameter != planeStress)
507 FEL_ERROR("Must be 1 (plane stress) or 2 (plane strain)");
508
509
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
36 FEL_ASSERT(std::fabs(nu -1.) > 1.e-10);
510
511
2/3
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
36 switch(dimension) {
512 16 case 2: {
513
2/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
16 engineering_elast_tensor = std::move(EngineeringElastTensor_2D(E, nu, kinematic_parameter));
514
2/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
16 gradient_2_strain = std::move(Gradient2Strain<2>());
515 16 break;
516 }
517 20 case 3: {
518
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
20 engineering_elast_tensor = std::move(EngineeringElastTensor_3D(E, nu));
519
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
20 gradient_2_strain = std::move(Gradient2Strain<3>());
520 20 break;
521 }
522 default: {
523 FEL_ERROR("Dimension must be 2 or 3");
524 exit(1);
525 }
526 }
527
528 // Intermediate step as Boost ublas gets a lousy syntax...
529
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
36 UBlasMatrix product1 = std::move(boost::numeric::ublas::prod(engineering_elast_tensor, gradient_2_strain));
530
531
3/6
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 36 times.
✗ Branch 10 not taken.
108 return std::move(prod(boost::numeric::ublas::trans(gradient_2_strain), std::move(product1)));
532 36 }
533
534 /***********************************************************************************/
535 /***********************************************************************************/
536
537 36 ElasticityNS::ForceType AssignForceType(const int data_parameter) {
538
539 // Check whether a surfacic or volumic force has been chosen
540
2/3
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
36 switch (data_parameter) {
541 4 case static_cast<int>(ElasticityNS::surfacic):
542 4 return ElasticityNS::surfacic;
543 32 case static_cast<int>(ElasticityNS::volumic):
544 32 return ElasticityNS::volumic;
545 default:
546 FEL_ERROR("Force applied should be either volumic or surfacic; make sure [solid] volumicOrSurfacicForce "
547 "is correctly filled in your data file and encompass an acceptable value");
548 }
549
550 FEL_ERROR("Should never be reached; if so bug to correct in the function!!!");
551 return ElasticityNS::volumic; // to avoid warning about missing warning
552 }
553
554 /***********************************************************************************/
555 /***********************************************************************************/
556
557 ErrorInvalidVolumicMass::ErrorInvalidVolumicMass() {
558 m_message = std::move("No volumic mass read in input parameter file.");
559 }
560
561 /***********************************************************************************/
562 /***********************************************************************************/
563
564 const char* ErrorInvalidVolumicMass::what() const noexcept {
565 return m_message.c_str();
566 }
567
568 } // namespace anonymous
569
570 } // namespace felisce
571