OGS
ThermoMechanicalPhaseFieldFEM-impl.h
Go to the documentation of this file.
1
11#pragma once
12
15
16namespace ProcessLib
17{
18namespace ThermoMechanicalPhaseField
19{
20template <typename ShapeFunction, int DisplacementDim>
22 assembleWithJacobianForStaggeredScheme(double const t, double const dt,
23 Eigen::VectorXd const& local_x,
24 Eigen::VectorXd const& local_x_prev,
25 int const process_id,
26 std::vector<double>& local_b_data,
27 std::vector<double>& local_Jac_data)
28{
29 if (process_id == _phase_field_process_id)
30 {
31 assembleWithJacobianForPhaseFieldEquations(t, local_x, local_b_data,
32 local_Jac_data);
33 return;
34 }
35
36 if (process_id == _heat_conduction_process_id)
37 {
38 assembleWithJacobianForHeatConductionEquations(
39 t, dt, local_x, local_x_prev, local_b_data, local_Jac_data);
40 return;
41 }
42
43 // For the equations with deformation
44 assembleWithJacobianForDeformationEquations(t, dt, local_x, local_b_data,
45 local_Jac_data);
46}
47
48template <typename ShapeFunction, int DisplacementDim>
51 double const t, double const dt, Eigen::VectorXd const& local_x,
52 std::vector<double>& local_b_data, std::vector<double>& local_Jac_data)
53{
54 assert(local_x.size() ==
55 phasefield_size + displacement_size + temperature_size);
56
57 auto const d = local_x.template segment<phasefield_size>(phasefield_index);
58 auto const u =
59 local_x.template segment<displacement_size>(displacement_index);
60 auto const T =
61 local_x.template segment<temperature_size>(temperature_index);
62
63 auto local_Jac = MathLib::createZeroedMatrix<
64 typename ShapeMatricesType::template MatrixType<displacement_size,
65 displacement_size>>(
66 local_Jac_data, displacement_size, displacement_size);
67
68 auto local_rhs = MathLib::createZeroedVector<
69 typename ShapeMatricesType::template VectorType<displacement_size>>(
70 local_b_data, displacement_size);
71
73 x_position.setElementID(_element.getID());
74
75 int const n_integration_points = _integration_method.getNumberOfPoints();
76 for (int ip = 0; ip < n_integration_points; ip++)
77 {
78 x_position.setIntegrationPoint(ip);
79 auto const& w = _ip_data[ip].integration_weight;
80 auto const& N = _ip_data[ip].N;
81 auto const& dNdx = _ip_data[ip].dNdx;
82
83 auto const x_coord =
85 _element, N);
86 auto const& B =
87 LinearBMatrix::computeBMatrix<DisplacementDim,
88 ShapeFunction::NPOINTS,
90 dNdx, N, x_coord, _is_axially_symmetric);
91
92 auto& eps = _ip_data[ip].eps;
93
94 auto const& D = _ip_data[ip].D;
95 auto const& sigma = _ip_data[ip].sigma;
96
97 auto const k = _process_data.residual_stiffness(t, x_position)[0];
98 auto rho_sr = _process_data.solid_density(t, x_position)[0];
99 auto const alpha = _process_data.linear_thermal_expansion_coefficient(
100 t, x_position)[0];
101 double const T0 = _process_data.reference_temperature;
102 auto const& b = _process_data.specific_body_force;
103
104 double const T_ip = N.dot(T);
105 double const delta_T = T_ip - T0;
106 // calculate real density
107 double const rho_s = rho_sr / (1 + 3 * alpha * delta_T);
108
109 double const d_ip = N.dot(d);
110 double const degradation = d_ip * d_ip * (1 - k) + k;
111
112 eps.noalias() = B * u;
113 _ip_data[ip].updateConstitutiveRelation(t, x_position, dt, u, alpha,
114 delta_T, degradation);
115
116 typename ShapeMatricesType::template MatrixType<DisplacementDim,
117 displacement_size>
118 N_u = ShapeMatricesType::template MatrixType<
119 DisplacementDim, displacement_size>::Zero(DisplacementDim,
120 displacement_size);
121
122 for (int i = 0; i < DisplacementDim; ++i)
123 {
124 N_u.template block<1, displacement_size / DisplacementDim>(
125 i, i * displacement_size / DisplacementDim)
126 .noalias() = N;
127 }
128
129 local_Jac.noalias() += B.transpose() * D * B * w;
130
131 local_rhs.noalias() -=
132 (B.transpose() * sigma - N_u.transpose() * rho_s * b) * w;
133 }
134}
135
136template <typename ShapeFunction, int DisplacementDim>
139 double const t, double const dt, Eigen::VectorXd const& local_x,
140 Eigen::VectorXd const& local_x_prev, std::vector<double>& local_b_data,
141 std::vector<double>& local_Jac_data)
142{
143 assert(local_x.size() ==
144 phasefield_size + displacement_size + temperature_size);
145
146 auto const d = local_x.template segment<phasefield_size>(phasefield_index);
147 auto const T =
148 local_x.template segment<temperature_size>(temperature_index);
149 auto const T_prev =
150 local_x_prev.template segment<temperature_size>(temperature_index);
151 auto local_Jac = MathLib::createZeroedMatrix<
152 typename ShapeMatricesType::template MatrixType<temperature_size,
153 temperature_size>>(
154 local_Jac_data, temperature_size, temperature_size);
155
156 auto local_rhs = MathLib::createZeroedVector<
157 typename ShapeMatricesType::template VectorType<temperature_size>>(
158 local_b_data, temperature_size);
159
161 x_position.setElementID(_element.getID());
162
163 int const n_integration_points = _integration_method.getNumberOfPoints();
164 for (int ip = 0; ip < n_integration_points; ip++)
165 {
166 x_position.setIntegrationPoint(ip);
167 auto const& w = _ip_data[ip].integration_weight;
168 auto const& N = _ip_data[ip].N;
169 auto const& dNdx = _ip_data[ip].dNdx;
170
171 auto& eps_m = _ip_data[ip].eps_m;
172 auto& heatflux = _ip_data[ip].heatflux;
173
174 auto rho_sr = _process_data.solid_density(t, x_position)[0];
175 auto const alpha = _process_data.linear_thermal_expansion_coefficient(
176 t, x_position)[0];
177 double const c = _process_data.specific_heat_capacity(t, x_position)[0];
178 auto const lambda =
179 _process_data.thermal_conductivity(t, x_position)[0];
180 auto const lambda_res =
181 _process_data.residual_thermal_conductivity(t, x_position)[0];
182 double const T0 = _process_data.reference_temperature;
183
184 double const d_ip = N.dot(d);
185 double const T_ip = N.dot(T);
186 double const T_dot_ip = (T_ip - N.dot(T_prev)) / dt;
187 double const delta_T = T_ip - T0;
188 // calculate real density
189 double const rho_s = rho_sr / (1 + 3 * alpha * delta_T);
190 // calculate effective thermal conductivity
191 auto const lambda_eff =
192 d_ip * d_ip * lambda + (1 - d_ip) * (1 - d_ip) * lambda_res;
193
194 using Invariants = MathLib::KelvinVector::Invariants<
196
197 double const eps_m_trace = Invariants::trace(eps_m);
198 if (eps_m_trace >= 0)
199 {
200 local_Jac.noalias() += (dNdx.transpose() * lambda_eff * dNdx +
201 N.transpose() * rho_s * c * N / dt) *
202 w;
203
204 local_rhs.noalias() -= (N.transpose() * rho_s * c * T_dot_ip +
205 dNdx.transpose() * lambda_eff * dNdx * T) *
206 w;
207
208 heatflux.noalias() = -(lambda_eff * dNdx * T) * w;
209 }
210 else
211 {
212 local_Jac.noalias() += (dNdx.transpose() * lambda * dNdx +
213 N.transpose() * rho_s * c * N / dt) *
214 w;
215
216 local_rhs.noalias() -= (N.transpose() * rho_s * c * T_dot_ip +
217 dNdx.transpose() * lambda * dNdx * T) *
218 w;
219
220 heatflux.noalias() = -(lambda * dNdx * T) * w;
221 }
222 }
223}
224
225template <typename ShapeFunction, int DisplacementDim>
228 double const t, Eigen::VectorXd const& local_x,
229 std::vector<double>& local_b_data, std::vector<double>& local_Jac_data)
230{
231 assert(local_x.size() ==
232 phasefield_size + displacement_size + temperature_size);
233
234 auto const d = local_x.template segment<phasefield_size>(phasefield_index);
235
236 auto local_Jac = MathLib::createZeroedMatrix<
237 typename ShapeMatricesType::template MatrixType<phasefield_size,
238 phasefield_size>>(
239 local_Jac_data, phasefield_size, phasefield_size);
240
241 auto local_rhs = MathLib::createZeroedVector<
242 typename ShapeMatricesType::template VectorType<phasefield_size>>(
243 local_b_data, phasefield_size);
244
246 x_position.setElementID(_element.getID());
247
248 int const n_integration_points = _integration_method.getNumberOfPoints();
249 for (int ip = 0; ip < n_integration_points; ip++)
250 {
251 x_position.setIntegrationPoint(ip);
252 auto const& w = _ip_data[ip].integration_weight;
253 auto const& N = _ip_data[ip].N;
254 auto const& dNdx = _ip_data[ip].dNdx;
255
256 auto const& strain_energy_tensile = _ip_data[ip].strain_energy_tensile;
257
258 auto const gc = _process_data.crack_resistance(t, x_position)[0];
259 auto const ls = _process_data.crack_length_scale(t, x_position)[0];
260
261 double const d_ip = N.dot(d);
262
263 local_Jac.noalias() += (dNdx.transpose() * gc * ls * dNdx +
264 N.transpose() * 2 * strain_energy_tensile * N +
265 N.transpose() * gc / ls * N) *
266 w;
267
268 local_rhs.noalias() -=
269 (dNdx.transpose() * gc * ls * dNdx * d +
270 N.transpose() * d_ip * 2 * strain_energy_tensile -
271 N.transpose() * gc / ls * (1 - d_ip)) *
272 w;
273 }
274}
275
276} // namespace ThermoMechanicalPhaseField
277} // namespace ProcessLib
void setElementID(std::size_t element_id)
MatrixType< _kelvin_vector_size, _number_of_dof > BMatrixType
void assembleWithJacobianForDeformationEquations(double const t, double const dt, Eigen::VectorXd const &local_x, std::vector< double > &local_b_data, std::vector< double > &local_Jac_data)
void assembleWithJacobianForHeatConductionEquations(double const t, double const dt, Eigen::VectorXd const &local_x, Eigen::VectorXd const &local_x_prev, std::vector< double > &local_b_data, std::vector< double > &local_Jac_data)
void assembleWithJacobianForStaggeredScheme(double const t, double const dt, Eigen::VectorXd const &local_x, Eigen::VectorXd const &local_x_prev, int const process_id, std::vector< double > &local_b_data, std::vector< double > &local_Jac_data) override
void assembleWithJacobianForPhaseFieldEquations(double const t, Eigen::VectorXd const &local_x, std::vector< double > &local_b_data, std::vector< double > &local_Jac_data)
constexpr int kelvin_vector_dimensions(int const displacement_dim)
Kelvin vector dimensions for given displacement dimension.
Eigen::Map< Vector > createZeroedVector(std::vector< double > &data, Eigen::VectorXd::Index size)
Eigen::Map< Matrix > createZeroedMatrix(std::vector< double > &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
double interpolateXCoordinate(MeshLib::Element const &e, typename ShapeMatricesType::ShapeMatrices::ShapeType const &N)
BMatrixType computeBMatrix(DNDX_Type const &dNdx, N_Type const &N, const double radius, const bool is_axially_symmetric)
Fills a B-matrix based on given shape function dN/dx values.