OGS
LinearElasticTransverseIsotropic.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
5
6#include <Eigen/LU>
7
9
10namespace MPL = MaterialPropertyLib;
11
12namespace MaterialLib
13{
14namespace Solids
15{
16template <int DisplacementDim>
17std::optional<std::tuple<typename MechanicsBase<DisplacementDim>::KelvinVector,
18 std::unique_ptr<typename MechanicsBase<
19 DisplacementDim>::MaterialStateVariables>,
22 MaterialPropertyLib::VariableArray const& variable_array_prev,
23 MaterialPropertyLib::VariableArray const& variable_array, double const t,
24 ParameterLib::SpatialPosition const& x, double const /*dt*/,
26 MaterialStateVariables const& /*material_state_variables*/) const
27{
28 auto const& eps_m = std::get<MPL::SymmetricTensor<DisplacementDim>>(
29 variable_array.mechanical_strain);
30 auto const& eps_m_prev = std::get<MPL::SymmetricTensor<DisplacementDim>>(
31 variable_array_prev.mechanical_strain);
32 auto const& sigma_prev = std::get<MPL::SymmetricTensor<DisplacementDim>>(
33 variable_array_prev.stress);
34 auto const& T = variable_array_prev.temperature;
35
36 KelvinMatrix C = getElasticTensor(t, x, T);
37
38 KelvinVector sigma = sigma_prev + C * (eps_m - eps_m_prev);
39
40 return {std::make_tuple(
41 sigma,
42 std::make_unique<
44 C)};
45}
46
47template <int DisplacementDim>
51 ParameterLib::SpatialPosition const& x) const
52{
53 using namespace MathLib::KelvinVector;
54 double const E_i = E_i_p_(t, x)[0];
55 double const E_a = E_a_p_(t, x)[0];
56 double const nu_i = nu_ii_p_(t, x)[0];
57 double const nu_ia = nu_ia_p_(t, x)[0];
58
59 double const nu_ai = nu_ia * (E_a / E_i);
60
61 double const nu_ia_p_nu_ai = nu_ia * nu_ai;
62 double const nu_i_p2 = nu_i * nu_i;
63 double const E_i_p2 = E_i * E_i;
64 // 1/D
65 double const one_over_D =
66 (E_i_p2 * E_a) / (1.0 - nu_i_p2 - 2.0 * (1.0 + nu_i) * nu_ia_p_nu_ai);
67
68 double const fac1 = one_over_D / (E_i * E_a);
69 double const fac2 = one_over_D / E_i_p2;
70 double const a_ii = (1.0 - nu_ia_p_nu_ai) * fac1;
71 double const a_ai = (1.0 - nu_i_p2) * fac2;
72 double const b_ii = (nu_i + nu_ia_p_nu_ai) * fac1;
73 double const b_ai = (nu_ia * (1.0 + nu_i)) * fac2;
74
77
78 if (DisplacementDim == 2)
79 {
80 // The following data are set based on the condition that the direction
81 // of anisotropy is parallel to the second base (base2) of the 2D local
82 // coordinate system.
83 C_ortho.template topLeftCorner<3, 3>() << a_ii, b_ai, b_ii, b_ai, a_ai,
84 b_ai, b_ii, b_ai, a_ii;
85
86 return C_ortho;
87 }
88 C_ortho.template topLeftCorner<3, 3>() << a_ii, b_ii, b_ai, b_ii, a_ii,
89 b_ai, b_ai, b_ai, a_ai;
90
91 return C_ortho;
92}
93
94template <>
97 double const t, ParameterLib::SpatialPosition const& x,
98 double const /*T*/) const
99{
100 using namespace MathLib::KelvinVector;
101
102 double const G_a = G_ia_p_(t, x)[0];
103 double const c_ai = G_a;
104
106
107 C_ortho.template bottomRightCorner<1, 1>().diagonal() << 2 * c_ai;
108
109 auto const Q = [this, &x]() -> KelvinMatrixType<2>
110 {
112 {
114 }
115
116 Eigen::Matrix<double, 2, 2> R = Eigen::Matrix<double, 2, 2>::Identity();
117 R.template topLeftCorner<2, 2>().noalias() =
118 local_coordinate_system_->transformation<2>(x);
120 }();
121
122 // Rotate the forth-order tenser in Kelvin mapping with Q*C_ortho*Q^T and
123 // return the top left corner block of size 4x4 for two-dimensional case.
124 return Q * C_ortho * Q.transpose();
125}
126
127template <>
130 double const t, ParameterLib::SpatialPosition const& x,
131 double const /*T*/) const
132{
133 using namespace MathLib::KelvinVector;
134
135 double const E_i = E_i_p_(t, x)[0];
136 double const nu_i = nu_ii_p_(t, x)[0];
137 double const G_a = G_ia_p_(t, x)[0];
138
139 double const c_ii = E_i / (2.0 * (1 + nu_i));
140 double const c_ai = G_a;
141
143
144 C_ortho.template bottomRightCorner<3, 3>().diagonal() << 2.0 * c_ii,
145 2 * c_ai, 2 * c_ai;
146
147 auto const Q = [this, &x]() -> KelvinMatrixType<3>
148 {
150 {
152 }
153 Eigen::Matrix3d R = Eigen::Matrix3d::Identity();
154 R.template topLeftCorner<3, 3>().noalias() =
155 local_coordinate_system_->transformation<3>(x);
157 }();
158
159 // Rotate the forth-order tenser in Kelvin mapping with Q*C_ortho*Q^T and
160 // return the 6x6 matrix for in the three-dimensional case.
161 return Q * C_ortho * Q.transpose();
162}
163
166
167} // namespace Solids
168} // namespace MaterialLib
P const & nu_ii_p_
It is the in-plane Poisson’s ratio, .
MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > KelvinMatrix
KelvinMatrix getElasticTensorLeftTopCorner(double const t, ParameterLib::SpatialPosition const &x) const
MathLib::KelvinVector::KelvinVectorType< DisplacementDim > KelvinVector
P const & E_i_p_
It is the in-plane Young’s modulus, .
std::optional< ParameterLib::CoordinateSystem > const & local_coordinate_system_
KelvinMatrix getElasticTensor(double const t, ParameterLib::SpatialPosition const &x, double const T) const
std::optional< std::tuple< typename MechanicsBase< DisplacementDim >::KelvinVector, std::unique_ptr< typename MechanicsBase< DisplacementDim >::MaterialStateVariables >, typename MechanicsBase< DisplacementDim >::KelvinMatrix > > integrateStress(MaterialPropertyLib::VariableArray const &variable_array_prev, MaterialPropertyLib::VariableArray const &variable_array, double const t, ParameterLib::SpatialPosition const &x, double const dt, typename MechanicsBase< DisplacementDim >::MaterialStateVariables const &material_state_variables) const override
KelvinMatrixType< DisplacementDim > fourthOrderRotationMatrix(Eigen::Matrix< double, DisplacementDim, DisplacementDim, Eigen::ColMajor, DisplacementDim, DisplacementDim > const &transformation)
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), kelvin_vector_dimensions(DisplacementDim), Eigen::RowMajor > KelvinMatrixType
static const double t
MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > KelvinMatrix