GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/test/solidmechanics/elastic/problem.hh
Date: 2025-04-12 19:19:20
Exec Total Coverage
Lines: 70 70 100.0%
Functions: 6 6 100.0%
Branches: 27 28 96.4%

Line Branch Exec Source
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 //
4 // SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7 /*!
8 * \file
9 * \ingroup GeomechanicsTests
10 * \brief Definition of a test problem for the linear elastic model.
11 */
12 #ifndef DUMUX_ELASTICPROBLEM_HH
13 #define DUMUX_ELASTICPROBLEM_HH
14
15 #include <dune/common/fmatrix.hh>
16
17 #include <dumux/common/math.hh>
18 #include <dumux/common/properties.hh>
19 #include <dumux/common/parameters.hh>
20 #include <dumux/common/boundarytypes.hh>
21 #include <dumux/common/numeqvector.hh>
22 #include <dumux/common/fvproblemwithspatialparams.hh>
23
24 namespace Dumux {
25
26 /*!
27 * \ingroup GeomechanicsTests
28 * \brief Problem definition for the deformation of an elastic body.
29 */
30 template<class TypeTag>
31 1 class ElasticProblem : public FVProblemWithSpatialParams<TypeTag>
32 {
33 using ParentType = FVProblemWithSpatialParams<TypeTag>;
34
35 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
36 using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
37 using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>;
38 using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
39 using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
40
41 using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
42 using ElementVolumeVariables = typename GridVariables::GridVolumeVariables::LocalView;
43 using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView;
44
45 using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
46 using FVElementGeometry = typename GridGeometry::LocalView;
47 using SubControlVolume = typename GridGeometry::SubControlVolume;
48 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
49
50 using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView;
51 using Element = typename GridView::template Codim<0>::Entity;
52 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
53
54 static constexpr Scalar pi = M_PI;
55 static constexpr int dim = GridView::dimension;
56 static constexpr int dimWorld = GridView::dimensionworld;
57 using GradU = Dune::FieldMatrix<Scalar, dim, dimWorld>;
58
59 public:
60 1 ElasticProblem(std::shared_ptr<const GridGeometry> gridGeometry)
61
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
3 : ParentType(gridGeometry) {}
62
63 //! Evaluates the initial value for a control volume.
64 121 PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const
65 242 { return PrimaryVariables(0.0); }
66
67 //! Evaluates the boundary conditions for a Dirichlet boundary segment.
68 152 PrimaryVariables dirichletAtPos(const GlobalPosition& globalPos) const
69 304 { return PrimaryVariables(0.0); }
70
71 /*!
72 * \brief Specifies which kind of boundary condition should be
73 * used for which equation on a given boundary segment.
74 *
75 * \param globalPos The global position
76 */
77 152 BoundaryTypes boundaryTypesAtPos(const GlobalPosition& globalPos) const
78 {
79
2/2
✓ Branch 0 taken 304 times.
✓ Branch 1 taken 152 times.
456 BoundaryTypes values;
80
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 112 times.
152 values.setAllDirichlet();
81
82
6/6
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 112 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 2 times.
152 if (globalPos[0] < eps_ && globalPos[1] > eps_ && globalPos[1] < 1.0 - eps_)
83 36 values.setNeumann(Indices::momentum(/*x-dir*/0));
84
6/6
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 112 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 36 times.
✓ Branch 5 taken 2 times.
152 if (globalPos[1] > 1.0 - eps_ && globalPos[0] > eps_ && globalPos[0] < 1.0 - eps_)
85 36 values.setNeumann(Indices::momentum(/*y-dir*/1));
86
87 152 return values;
88 }
89
90 //! Evaluates the boundary conditions for a Neumann boundary segment.
91 648 NumEqVector neumann(const Element& element,
92 const FVElementGeometry& fvGeometry,
93 const ElementVolumeVariables& elemVolvars,
94 const ElementFluxVariablesCache& elemFluxVarsCache,
95 const SubControlVolumeFace& scvf) const
96 {
97 648 GradU gradU = exactGradient(scvf.ipGlobal());
98
99 648 GradU epsilon;
100
2/2
✓ Branch 0 taken 1296 times.
✓ Branch 1 taken 648 times.
1944 for (int i = 0; i < dim; ++i)
101
2/2
✓ Branch 0 taken 2592 times.
✓ Branch 1 taken 1296 times.
3888 for (int j = 0; j < dimWorld; ++j)
102 2592 epsilon[i][j] = 0.5*(gradU[i][j] + gradU[j][i]);
103
104 648 const auto& lameParams = this->spatialParams().lameParamsAtPos(scvf.ipGlobal());
105
2/2
✓ Branch 0 taken 1296 times.
✓ Branch 1 taken 648 times.
2592 GradU sigma(0.0);
106 1944 const auto traceEpsilon = trace(epsilon);
107
2/2
✓ Branch 0 taken 1296 times.
✓ Branch 1 taken 648 times.
1944 for (int i = 0; i < dim; ++i)
108 {
109 1296 sigma[i][i] = lameParams.lambda()*traceEpsilon;
110
2/2
✓ Branch 0 taken 2592 times.
✓ Branch 1 taken 1296 times.
3888 for (int j = 0; j < dimWorld; ++j)
111 2592 sigma[i][j] += 2.0*lameParams.mu()*epsilon[i][j];
112 }
113
114 648 NumEqVector values;
115 648 sigma.mv(scvf.unitOuterNormal(), values);
116 648 return values;
117 }
118
119 /*!
120 * \brief Evaluates the source term for all phases within a given
121 * sub-control volume.
122 */
123 7200 NumEqVector source(const Element& element,
124 const FVElementGeometry& fvGeometry,
125 const ElementVolumeVariables& elemVolVars,
126 const SubControlVolume& scv) const
127 {
128 using std::sin;
129 using std::cos;
130
131 7200 const auto ipGlobal = scv.center();
132 7200 const auto x = ipGlobal[0];
133 7200 const auto y = ipGlobal[1];
134
135 // the lame parameters (we know they only depend on the position here)
136 7200 const auto& lameParams = this->spatialParams().lameParamsAtPos(scv.center());
137 7200 const auto lambda = lameParams.lambda();
138 7200 const auto mu = lameParams.mu();
139
140 // precalculated products
141 7200 const Scalar pi_2 = 2.0*pi;
142 7200 const Scalar pi_2_square = pi_2*pi_2;
143 7200 const Scalar cos_2pix = cos(pi_2*x);
144 7200 const Scalar sin_2pix = sin(pi_2*x);
145 7200 const Scalar cos_2piy = cos(pi_2*y);
146 7200 const Scalar sin_2piy = sin(pi_2*y);
147
148 7200 const Scalar dE11_dx = -2.0*sin_2piy;
149 7200 const Scalar dE22_dx = pi_2_square*cos_2pix*cos_2piy;
150 7200 const Scalar dE11_dy = pi_2*(1.0-2.0*x)*cos_2piy;
151 7200 const Scalar dE22_dy = -1.0*pi_2_square*sin_2pix*sin_2piy;
152 7200 const Scalar dE12_dy = 0.5*pi_2_square*(cos_2pix*cos_2piy - (x-x*x)*sin_2piy);
153 7200 const Scalar dE21_dx = 0.5*((1.0-2*x)*pi_2*cos_2piy - pi_2_square*sin_2pix*sin_2piy);
154
155 // compute exact divergence of sigma
156 7200 PrimaryVariables divSigma(0.0);
157 7200 divSigma[Indices::momentum(/*x-dir*/0)] = lambda*(dE11_dx + dE22_dx) + 2*mu*(dE11_dx + dE12_dy);
158 7200 divSigma[Indices::momentum(/*y-dir*/1)] = lambda*(dE11_dy + dE22_dy) + 2*mu*(dE21_dx + dE22_dy);
159 7200 return divSigma;
160 }
161
162 /*!
163 * \brief Evaluates the exact displacement to this problem at a given position.
164 */
165 121 PrimaryVariables exactSolution(const GlobalPosition& globalPos) const
166 {
167 using std::sin;
168
169 121 const auto x = globalPos[0];
170 121 const auto y = globalPos[1];
171
172 121 PrimaryVariables exact(0.0);
173 121 exact[Indices::momentum(/*x-dir*/0)] = (x-x*x)*sin(2*pi*y);
174 121 exact[Indices::momentum(/*y-dir*/1)] = sin(2*pi*x)*sin(2*pi*y);
175 121 return exact;
176 }
177
178 /*!
179 * \brief Evaluates the exact displacement gradient to this problem at a given position.
180 */
181 648 GradU exactGradient(const GlobalPosition& globalPos) const
182 {
183 using std::sin;
184 using std::cos;
185
186 648 const auto x = globalPos[0];
187 648 const auto y = globalPos[1];
188
189 static constexpr int xIdx = Indices::momentum(/*x-dir*/0);
190 static constexpr int yIdx = Indices::momentum(/*y-dir*/1);
191
192 648 GradU exactGrad(0.0);
193 648 exactGrad[xIdx][xIdx] = (1-2*x)*sin(2*pi*y);
194 648 exactGrad[xIdx][yIdx] = (x - x*x)*2*pi*cos(2*pi*y);
195 648 exactGrad[yIdx][xIdx] = 2*pi*cos(2*pi*x)*sin(2*pi*y);
196 648 exactGrad[yIdx][yIdx] = 2*pi*sin(2*pi*x)*cos(2*pi*y);
197 648 return exactGrad;
198 }
199
200 private:
201 static constexpr Scalar eps_ = 3e-6;
202 };
203
204 } // end namespace Dumux
205
206 #endif
207