27 namespace ThermoHydroMechanics
29 template <
typename ShapeFunctionDisplacement,
typename ShapeFunctionPressure,
30 typename IntegrationMethod,
int DisplacementDim>
31 ThermoHydroMechanicsLocalAssembler<ShapeFunctionDisplacement,
32 ShapeFunctionPressure, IntegrationMethod,
34 ThermoHydroMechanicsLocalAssembler(
37 bool const is_axially_symmetric,
38 unsigned const integration_order,
40 : _process_data(process_data),
41 _integration_method(integration_order),
43 _is_axially_symmetric(is_axially_symmetric)
45 unsigned const n_integration_points =
48 _ip_data.reserve(n_integration_points);
51 auto const shape_matrices_u =
54 DisplacementDim>(e, is_axially_symmetric,
57 auto const shape_matrices_p =
62 auto const& solid_material =
67 for (
unsigned ip = 0; ip < n_integration_points; ip++)
69 _ip_data.emplace_back(solid_material);
71 auto const& sm_u = shape_matrices_u[ip];
72 ip_data.integration_weight =
74 sm_u.integralMeasure * sm_u.detJ;
76 ip_data.N_u_op = ShapeMatricesTypeDisplacement::template MatrixType<
79 for (
int i = 0; i < DisplacementDim; ++i)
81 .template block<1, displacement_size / DisplacementDim>(
86 ip_data.dNdx_u = sm_u.dNdx;
88 ip_data.N_p = shape_matrices_p[ip].N;
89 ip_data.dNdx_p = shape_matrices_p[ip].dNdx;
95 template <
typename ShapeFunctionDisplacement,
typename ShapeFunctionPressure,
96 typename IntegrationMethod,
int DisplacementDim>
98 ShapeFunctionDisplacement, ShapeFunctionPressure, IntegrationMethod,
99 DisplacementDim>::setIPDataInitialConditions(std::string
const&
name,
100 double const* values,
101 int const integration_order)
103 if (integration_order !=
104 static_cast<int>(_integration_method.getIntegrationOrder()))
107 "Setting integration point initial conditions; The integration "
108 "order of the local assembler for element {:d} is different from "
109 "the integration order in the initial condition.",
113 if (
name ==
"sigma_ip")
115 if (_process_data.initial_stress !=
nullptr)
118 "Setting initial conditions for stress from integration "
119 "point data and from a parameter '{:s}' is not possible "
121 _process_data.initial_stress->name);
124 return ProcessLib::setIntegrationPointKelvinVectorData<DisplacementDim>(
125 values, _ip_data, &IpData::sigma_eff);
127 if (
name ==
"epsilon_ip")
129 return ProcessLib::setIntegrationPointKelvinVectorData<DisplacementDim>(
130 values, _ip_data, &IpData::eps);
138 template <
typename ShapeFunctionDisplacement,
typename ShapeFunctionPressure,
139 typename IntegrationMethod,
int DisplacementDim>
141 ShapeFunctionPressure,
142 IntegrationMethod, DisplacementDim>::
143 assembleWithJacobian(
double const t,
double const dt,
144 std::vector<double>
const& local_x,
145 std::vector<double>
const& local_xdot,
146 const double ,
const double ,
147 std::vector<double>& ,
148 std::vector<double>& ,
149 std::vector<double>& local_rhs_data,
150 std::vector<double>& local_Jac_data)
152 assert(local_x.size() ==
153 pressure_size + displacement_size + temperature_size);
155 auto T = Eigen::Map<
typename ShapeMatricesTypePressure::template VectorType<
156 temperature_size>
const>(local_x.data() + temperature_index,
159 auto p = Eigen::Map<
typename ShapeMatricesTypePressure::template VectorType<
160 pressure_size>
const>(local_x.data() + pressure_index, pressure_size);
163 Eigen::Map<
typename ShapeMatricesTypeDisplacement::template VectorType<
164 displacement_size>
const>(local_x.data() + displacement_index,
168 Eigen::Map<
typename ShapeMatricesTypePressure::template VectorType<
169 temperature_size>
const>(local_xdot.data() + temperature_index,
173 Eigen::Map<
typename ShapeMatricesTypePressure::template VectorType<
174 pressure_size>
const>(local_xdot.data() + pressure_index,
177 Eigen::Map<
typename ShapeMatricesTypeDisplacement::template VectorType<
178 displacement_size>
const>(local_xdot.data() + displacement_index,
182 typename ShapeMatricesTypeDisplacement::template MatrixType<
183 temperature_size + displacement_size + pressure_size,
184 temperature_size + displacement_size + pressure_size>>(
185 local_Jac_data, displacement_size + pressure_size + temperature_size,
186 displacement_size + pressure_size + temperature_size);
189 typename ShapeMatricesTypeDisplacement::template VectorType<
190 displacement_size + pressure_size + temperature_size>>(
191 local_rhs_data, displacement_size + pressure_size + temperature_size);
194 MTT.setZero(temperature_size, temperature_size);
196 typename ShapeMatricesTypeDisplacement::template MatrixType<
197 temperature_size, displacement_size>
199 MTu.setZero(temperature_size, displacement_size);
202 KTT.setZero(temperature_size, temperature_size);
205 KTp.setZero(temperature_size, pressure_size);
208 laplace_p.setZero(pressure_size, pressure_size);
211 laplace_T.setZero(pressure_size, temperature_size);
214 storage_p.setZero(pressure_size, pressure_size);
217 storage_T.setZero(pressure_size, temperature_size);
219 typename ShapeMatricesTypeDisplacement::template MatrixType<
220 displacement_size, pressure_size>
222 Kup.setZero(displacement_size, pressure_size);
223 typename ShapeMatricesTypeDisplacement::template MatrixType<
224 displacement_size, temperature_size>
226 KuT.setZero(displacement_size, temperature_size);
229 *_process_data.solid_materials[0];
234 auto const& medium = _process_data.media_map->getMedium(_element.getID());
235 auto const& liquid_phase = medium->phase(
"AqueousLiquid");
236 auto const& solid_phase = medium->phase(
"Solid");
239 auto const& identity2 = Invariants::identity2;
241 unsigned const n_integration_points =
242 _integration_method.getNumberOfPoints();
243 for (
unsigned ip = 0; ip < n_integration_points; ip++)
246 auto const& w = _ip_data[ip].integration_weight;
248 auto const& N_u_op = _ip_data[ip].N_u_op;
250 auto const& N_u = _ip_data[ip].N_u;
251 auto const& dNdx_u = _ip_data[ip].dNdx_u;
253 auto const& N_p = _ip_data[ip].N_p;
254 auto const& dNdx_p = _ip_data[ip].dNdx_p;
258 auto const& N_T = N_p;
259 auto const& dNdx_T = dNdx_p;
260 auto const T_int_pt = N_T.dot(T);
261 double const dT_int_pt = N_T.dot(T_dot) * dt;
269 ShapeFunctionDisplacement::NPOINTS,
271 dNdx_u, N_u, x_coord, _is_axially_symmetric);
273 auto& eps = _ip_data[ip].eps;
274 eps.noalias() = B * u;
275 auto const& sigma_eff = _ip_data[ip].sigma_eff;
279 double const p_int_pt = N_p.dot(p);
283 vars[
static_cast<int>(
286 auto const solid_density =
288 .template value<double>(vars, x_position, t, dt);
290 auto const porosity =
292 .template value<double>(vars, x_position, t, dt);
299 .template value<double>(vars, x_position, t, dt);
301 auto const solid_skeleton_compressibility =
304 auto const beta_SR = (1 -
alpha) * solid_skeleton_compressibility;
309 auto const sigma_total =
310 (_ip_data[ip].sigma_eff -
alpha * p_int_pt * identity2).eval();
312 .emplace<SymmetricTensor>(
317 vars[
static_cast<int>(
319 Invariants::trace(_ip_data[ip].eps);
320 vars[
static_cast<int>(
322 _ip_data[ip].material_state_variables->getEquivalentPlasticStrain();
324 auto const intrinsic_permeability =
325 MaterialPropertyLib::formEigenTensor<DisplacementDim>(
328 .value(vars, x_position, t, dt));
332 .template value<double>(vars, x_position, t, dt);
336 .template dValue<double>(
340 auto const fluid_compressibility = 1 /
fluid_density * drho_dp;
342 double const fluid_volumetric_thermal_expansion_coefficient =
349 .template value<double>(vars, x_position, t, dt);
352 auto const& b = _process_data.specific_body_force;
356 DisplacementDim>
const solid_linear_thermal_expansion_coefficient =
357 MPL::formKelvinVectorFromThermalExpansivity<DisplacementDim>(
361 .value(vars, x_position, t, dt));
365 solid_linear_thermal_expansion_coefficient * dT_int_pt;
367 auto const K_pT_thermal_osmosis =
368 (solid_phase.hasProperty(
370 ? MaterialPropertyLib::formEigenTensor<DisplacementDim>(
374 .value(vars, x_position, t, dt))
375 : Eigen::MatrixXd::Zero(DisplacementDim, DisplacementDim));
378 (-K_over_mu * dNdx_p * p - K_pT_thermal_osmosis * dNdx_T * T)
385 auto& eps_prev = _ip_data[ip].eps_prev;
386 auto& eps_m = _ip_data[ip].eps_m;
387 auto& eps_m_prev = _ip_data[ip].eps_m_prev;
388 eps_m.noalias() = eps_m_prev + eps - eps_prev - dthermal_strain;
393 auto C = _ip_data[ip].updateConstitutiveRelation(
394 vars, t, x_position, dt, T_int_pt - dT_int_pt);
397 .template block<displacement_size, displacement_size>(
398 displacement_index, displacement_index)
399 .noalias() += B.transpose() * C * B * w;
403 local_rhs.template segment<displacement_size>(displacement_index)
405 (B.transpose() * sigma_eff - N_u_op.transpose() * rho * b) * w;
411 Kup.noalias() += B.transpose() *
alpha * identity2 * N_p * w;
416 laplace_p.noalias() += dNdx_p.transpose() * K_over_mu * dNdx_p * w;
418 storage_p.noalias() +=
420 (porosity * fluid_compressibility + (
alpha - porosity) * beta_SR) *
423 laplace_T.noalias() +=
424 dNdx_p.transpose() * K_pT_thermal_osmosis * dNdx_T * w;
428 local_rhs.template segment<pressure_size>(pressure_index).noalias() +=
434 porosity * fluid_volumetric_thermal_expansion_coefficient +
436 Invariants::trace(solid_linear_thermal_expansion_coefficient);
437 storage_T.noalias() += N_T.transpose() *
beta * N_T * w;
451 .template value<double>(vars, x_position, t, dt);
452 auto const effective_thermal_conductivity =
453 MaterialPropertyLib::formEigenTensor<DisplacementDim>(
457 .value(vars, x_position, t, dt));
460 (dNdx_T.transpose() * effective_thermal_conductivity * dNdx_T +
461 N_T.transpose() * velocity.transpose() * dNdx_T *
fluid_density *
464 fluid_density * c_f * N_T.transpose() * (dNdx_T * T).transpose() *
465 K_pT_thermal_osmosis * dNdx_T * w;
467 auto const effective_volumetric_heat_capacity =
469 (1.0 - porosity) * solid_density *
473 .template value<double>(vars, x_position, t, dt);
476 N_T.transpose() * effective_volumetric_heat_capacity * N_T * w;
482 fluid_density * c_f * N_T.transpose() * (dNdx_T * T).transpose() *
483 K_over_mu * dNdx_p * w -
484 dNdx_T.transpose() * T_int_pt * K_pT_thermal_osmosis * dNdx_p * w;
487 if (fluid_compressibility != 0)
489 local_rhs.template segment<temperature_size>(temperature_index)
492 (-T_int_pt * fluid_volumetric_thermal_expansion_coefficient /
493 fluid_compressibility) *
498 Invariants::trace(solid_linear_thermal_expansion_coefficient) /
499 solid_skeleton_compressibility) *
500 N_T.transpose() * identity2.transpose() * B * w;
504 (-T_int_pt * fluid_volumetric_thermal_expansion_coefficient *
505 K_pT_thermal_osmosis / fluid_compressibility) *
510 (T_int_pt * fluid_volumetric_thermal_expansion_coefficient *
511 K_over_mu / fluid_compressibility) *
517 .template block<temperature_size, temperature_size>(temperature_index,
519 .noalias() += KTT + MTT / dt;
523 .template block<temperature_size, pressure_size>(temperature_index,
529 .template block<temperature_size, displacement_size>(temperature_index,
531 .noalias() += MTu / dt;
535 .template block<displacement_size, temperature_size>(displacement_index,
541 .template block<displacement_size, pressure_size>(displacement_index,
547 .template block<pressure_size, temperature_size>(pressure_index,
549 .noalias() -= storage_T / dt - laplace_T;
553 .template block<pressure_size, pressure_size>(pressure_index,
555 .noalias() += laplace_p + storage_p / dt;
559 .template block<pressure_size, displacement_size>(pressure_index,
561 .noalias() += Kup.transpose() / dt;
564 local_rhs.template segment<pressure_size>(pressure_index).noalias() -=
565 laplace_p * p + laplace_T * T + storage_p * p_dot - storage_T * T_dot +
566 Kup.transpose() * u_dot;
569 local_rhs.template segment<displacement_size>(displacement_index)
570 .noalias() += Kup * p;
573 local_rhs.template segment<temperature_size>(temperature_index).noalias() -=
574 KTT * T + MTT * T_dot;
577 template <
typename ShapeFunctionDisplacement,
typename ShapeFunctionPressure,
578 typename IntegrationMethod,
int DisplacementDim>
580 ShapeFunctionDisplacement, ShapeFunctionPressure, IntegrationMethod,
582 getIntPtDarcyVelocity(
584 std::vector<GlobalVector*>
const& x,
585 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& dof_table,
586 std::vector<double>& cache)
const
588 unsigned const n_integration_points =
589 _integration_method.getNumberOfPoints();
591 constexpr
int process_id = 0;
594 assert(!indices.empty());
595 auto const local_x = x[process_id]->get(indices);
599 double, DisplacementDim, Eigen::Dynamic, Eigen::RowMajor>>(
600 cache, DisplacementDim, n_integration_points);
602 auto p = Eigen::Map<
typename ShapeMatricesTypePressure::template VectorType<
603 pressure_size>
const>(local_x.data() + pressure_index, pressure_size);
604 auto T = Eigen::Map<
typename ShapeMatricesTypePressure::template VectorType<
605 temperature_size>
const>(local_x.data() + temperature_index,
611 auto const& medium = _process_data.media_map->getMedium(_element.getID());
612 auto const& liquid_phase = medium->phase(
"AqueousLiquid");
613 auto const& solid_phase = medium->phase(
"Solid");
616 auto const& identity2 = Invariants::identity2;
618 for (
unsigned ip = 0; ip < n_integration_points; ip++)
620 x_position.setIntegrationPoint(ip);
622 auto const& N_p = _ip_data[ip].N_p;
626 double const p_int_pt = N_p.dot(p);
632 double const dt = std::numeric_limits<double>::quiet_NaN();
635 .template value<double>(vars, x_position, t, dt);
640 .template value<double>(vars, x_position, t, dt);
645 auto const sigma_total =
646 (_ip_data[ip].sigma_eff -
alpha * p_int_pt * identity2).eval();
648 .emplace<SymmetricTensor>(
653 vars[
static_cast<int>(
655 Invariants::trace(_ip_data[ip].eps);
656 vars[
static_cast<int>(
658 _ip_data[ip].material_state_variables->getEquivalentPlasticStrain();
661 MaterialPropertyLib::formEigenTensor<DisplacementDim>(
664 .value(vars, x_position, t, dt)) /
669 .template value<double>(vars, x_position, t, dt);
670 auto const& b = _process_data.specific_body_force;
672 auto const K_pT_thermal_osmosis =
673 (solid_phase.hasProperty(
675 ? MaterialPropertyLib::formEigenTensor<DisplacementDim>(
679 .value(vars, x_position, t, dt))
680 : Eigen::MatrixXd::Zero(DisplacementDim, DisplacementDim));
683 auto const& dNdx_p = _ip_data[ip].dNdx_p;
684 cache_matrix.col(ip).noalias() = -K_over_mu * dNdx_p * p -
685 K_pT_thermal_osmosis * dNdx_p * T +
692 template <
typename ShapeFunctionDisplacement,
typename ShapeFunctionPressure,
693 typename IntegrationMethod,
int DisplacementDim>
695 ShapeFunctionPressure,
696 IntegrationMethod, DisplacementDim>::
697 postNonLinearSolverConcrete(std::vector<double>
const& local_x,
698 std::vector<double>
const& local_xdot,
699 double const t,
double const dt,
700 bool const use_monolithic_scheme,
703 const int displacement_offset =
704 use_monolithic_scheme ? displacement_index : 0;
707 Eigen::Map<
typename ShapeMatricesTypeDisplacement::template VectorType<
708 displacement_size>
const>(local_x.data() + displacement_offset,
711 auto T = Eigen::Map<
typename ShapeMatricesTypePressure::template VectorType<
712 temperature_size>
const>(local_x.data() + temperature_index,
714 auto p = Eigen::Map<
typename ShapeMatricesTypePressure::template VectorType<
715 pressure_size>
const>(local_x.data() + pressure_index, pressure_size);
718 Eigen::Map<
typename ShapeMatricesTypePressure::template VectorType<
719 temperature_size>
const>(local_xdot.data() + temperature_index,
724 auto const& medium = _process_data.media_map->getMedium(_element.getID());
725 auto const& solid_phase = medium->phase(
"Solid");
728 int const n_integration_points = _integration_method.getNumberOfPoints();
729 for (
int ip = 0; ip < n_integration_points; ip++)
731 x_position.setIntegrationPoint(ip);
732 auto const& N_u = _ip_data[ip].N_u;
733 auto const& N_T = _ip_data[ip].N_p;
734 auto const& dNdx_u = _ip_data[ip].dNdx_u;
742 ShapeFunctionDisplacement::NPOINTS,
744 dNdx_u, N_u, x_coord, _is_axially_symmetric);
746 double const T_int_pt = N_T.dot(T);
754 DisplacementDim>
const solid_linear_thermal_expansion_coefficient =
755 MPL::formKelvinVectorFromThermalExpansivity<DisplacementDim>(
759 .value(vars, x_position, t, dt));
761 double const dT_int_pt = N_T.dot(T_dot) * dt;
764 solid_linear_thermal_expansion_coefficient * dT_int_pt;
766 auto& eps = _ip_data[ip].eps;
767 eps.noalias() = B * u;
769 auto& eps_prev = _ip_data[ip].eps_prev;
770 auto& eps_m = _ip_data[ip].eps_m;
771 auto& eps_m_prev = _ip_data[ip].eps_m_prev;
772 eps_m.noalias() = eps_m_prev + eps - eps_prev - dthermal_strain;
777 _ip_data[ip].updateConstitutiveRelation(vars, t, x_position, dt,
778 T_int_pt - dT_int_pt);
782 template <
typename ShapeFunctionDisplacement,
typename ShapeFunctionPressure,
783 typename IntegrationMethod,
int DisplacementDim>
785 ShapeFunctionPressure,
786 IntegrationMethod, DisplacementDim>::
787 computeSecondaryVariableConcrete(
double const ,
double const ,
788 Eigen::VectorXd
const& local_x,
789 Eigen::VectorXd
const& )
791 auto const p = local_x.template segment<pressure_size>(pressure_index);
794 ShapeFunctionPressure,
typename ShapeFunctionDisplacement::MeshElement,
795 DisplacementDim>(_element, _is_axially_symmetric, p,
796 *_process_data.pressure_interpolated);
798 auto T = local_x.template segment<temperature_size>(temperature_index);
801 ShapeFunctionPressure,
typename ShapeFunctionDisplacement::MeshElement,
802 DisplacementDim>(_element, _is_axially_symmetric, T,
803 *_process_data.temperature_interpolated);
virtual std::size_t getID() const final
Returns the ID of the element.
void setElementID(std::size_t element_id)
void setIntegrationPoint(unsigned integration_point)
MatrixType< _kelvin_vector_size, _number_of_dof > BMatrixType
typename ShapeMatricesTypePressure::GlobalDimMatrixType GlobalDimMatrixType
ShapeMatrixPolicyType< ShapeFunctionDisplacement, DisplacementDim > ShapeMatricesTypeDisplacement
std::vector< IpData, Eigen::aligned_allocator< IpData > > _ip_data
ThermoHydroMechanicsProcessData< DisplacementDim > & _process_data
static const int displacement_size
ShapeMatrixPolicyType< ShapeFunctionPressure, DisplacementDim > ShapeMatricesTypePressure
SecondaryData< typename ShapeMatricesTypeDisplacement::ShapeMatrices::ShapeType > _secondary_data
IntegrationMethod _integration_method
MechanicsBase< DisplacementDim > & selectSolidConstitutiveRelation(std::map< int, std::unique_ptr< MechanicsBase< DisplacementDim >>> const &constitutive_relations, MeshLib::PropertyVector< int > const *const material_ids, std::size_t const element_id)
@ equivalent_plastic_strain
double getLiquidThermalExpansivity(Phase const &phase, VariableArray const &vars, const double density, ParameterLib::SpatialPosition const &pos, double const t, double const dt)
std::array< VariableType, static_cast< int >(Variable::number_of_variables)> VariableArray
@ thermal_osmosis_coefficient
Eigen::Matrix< double, 4, 1 > kelvinVectorToSymmetricTensor(Eigen::Matrix< double, 4, 1, Eigen::ColMajor, 4, 1 > const &v)
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), 1, Eigen::ColMajor > KelvinVectorType
Eigen::Map< Matrix > createZeroedMatrix(std::vector< double > &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
Eigen::Map< Vector > createZeroedVector(std::vector< double > &data, Eigen::VectorXd::Index size)
double interpolateXCoordinate(MeshLib::Element const &e, typename ShapeMatricesType::ShapeMatrices::ShapeType const &N)
void interpolateToHigherOrderNodes(MeshLib::Element const &element, bool const is_axially_symmetric, Eigen::MatrixBase< EigenMatrixType > const &node_values, MeshLib::PropertyVector< double > &interpolated_values_global_vector)
std::vector< GlobalIndexType > getIndices(std::size_t const mesh_item_id, NumLib::LocalToGlobalIndexMap const &dof_table)
std::vector< typename ShapeMatricesType::ShapeMatrices, Eigen::aligned_allocator< typename ShapeMatricesType::ShapeMatrices > > initShapeMatrices(MeshLib::Element const &e, bool const is_axially_symmetric, IntegrationMethod const &integration_method)
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.
double fluid_density(const double p, const double T, const double x)
MatrixType< ShapeFunction::NPOINTS, ShapeFunction::NPOINTS > NodalMatrixType
virtual double getBulkModulus(double const, ParameterLib::SpatialPosition const &, KelvinMatrix const *const =nullptr) const
std::vector< ShapeMatrixType, Eigen::aligned_allocator< ShapeMatrixType > > N_u