28 namespace ThermoRichardsMechanics
30 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
31 typename IntegrationMethod,
int DisplacementDim>
32 ThermoRichardsMechanicsLocalAssembler<ShapeFunctionDisplacement, ShapeFunction,
33 IntegrationMethod, DisplacementDim>::
34 ThermoRichardsMechanicsLocalAssembler(
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 =
59 DisplacementDim>(e, is_axially_symmetric,
62 auto const& solid_material =
71 for (
unsigned ip = 0; ip < n_integration_points; ip++)
74 ip_data_.emplace_back(solid_material);
76 auto const& sm_u = shape_matrices_u[ip];
79 sm_u.integralMeasure * sm_u.detJ;
81 ip_data.N_u_op = ShapeMatricesTypeDisplacement::template MatrixType<
84 for (
int i = 0; i < DisplacementDim; ++i)
93 ip_data.dNdx_u = sm_u.dNdx;
96 ip_data.N_p = shape_matrices[ip].N;
97 ip_data.dNdx_p = shape_matrices[ip].dNdx;
102 .template initialValue<double>(
105 double>::quiet_NaN() );
107 ip_data.transport_porosity = ip_data.porosity;
110 ip_data.transport_porosity =
112 .template initialValue<double>(
115 double>::quiet_NaN() );
122 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
123 typename IntegrationMethod,
int DisplacementDim>
125 ShapeFunctionDisplacement, ShapeFunction, IntegrationMethod,
126 DisplacementDim>::setIPDataInitialConditions(std::string
const&
name,
127 double const* values,
128 int const integration_order)
130 if (integration_order !=
131 static_cast<int>(integration_method_.getIntegrationOrder()))
134 "Setting integration point initial conditions; The integration "
135 "order of the local assembler for element {:d} is different "
136 "from the integration order in the initial condition.",
140 if (
name ==
"sigma_ip")
142 if (process_data_.initial_stress !=
nullptr)
145 "Setting initial conditions for stress from integration "
146 "point data and from a parameter '{:s}' is not possible "
148 process_data_.initial_stress->name);
150 return ProcessLib::setIntegrationPointKelvinVectorData<DisplacementDim>(
151 values, ip_data_, &IpData::sigma_eff);
154 if (
name ==
"saturation_ip")
159 if (
name ==
"porosity_ip")
164 if (
name ==
"transport_porosity_ip")
169 if (
name ==
"swelling_stress_ip")
171 return ProcessLib::setIntegrationPointKelvinVectorData<DisplacementDim>(
172 values, ip_data_, &IpData::sigma_sw);
174 if (
name ==
"epsilon_ip")
176 return ProcessLib::setIntegrationPointKelvinVectorData<DisplacementDim>(
177 values, ip_data_, &IpData::eps);
182 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
183 typename IntegrationMethod,
int DisplacementDim>
185 ShapeFunction, IntegrationMethod,
187 setInitialConditionsConcrete(std::vector<double>
const& local_x,
192 assert(local_x.size() ==
193 temperature_size + pressure_size + displacement_size);
195 auto const p_L = Eigen::Map<
196 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
197 local_x.data() + pressure_index, pressure_size);
199 auto const T = Eigen::Map<
typename ShapeMatricesType::template VectorType<
200 temperature_size>
const>(local_x.data() + temperature_index,
203 constexpr
double dt = std::numeric_limits<double>::quiet_NaN();
204 auto const& medium = process_data_.media_map->getMedium(element_.getID());
210 auto const& solid_phase = medium->phase(
"Solid");
212 unsigned const n_integration_points =
213 integration_method_.getNumberOfPoints();
214 for (
unsigned ip = 0; ip < n_integration_points; ip++)
219 auto const& N = ip_data_[ip].N_p;
226 variables[
static_cast<int>(MPL::Variable::phase_pressure)] = -p_cap_ip;
232 ip_data_[ip].saturation_prev =
234 .template value<double>(variables, x_position, t, dt);
238 auto const C_el = ip_data_[ip].computeElasticTangentStiffness(
239 t, x_position, dt, T_ip, T_ip);
240 auto& eps = ip_data_[ip].eps;
241 auto& sigma_sw = ip_data_[ip].sigma_sw;
242 ip_data_[ip].eps_m_prev.noalias() =
244 ? eps + C_el.inverse() * sigma_sw
249 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
250 typename IntegrationMethod,
int DisplacementDim>
252 ShapeFunction, IntegrationMethod,
254 assembleWithJacobian(
double const t,
double const dt,
255 std::vector<double>
const& local_x,
256 std::vector<double>
const& local_xdot,
257 const double ,
const double ,
258 std::vector<double>& ,
259 std::vector<double>& ,
260 std::vector<double>& local_rhs_data,
261 std::vector<double>& local_Jac_data)
263 auto const local_matrix_dim =
264 displacement_size + pressure_size + temperature_size;
265 assert(local_x.size() == local_matrix_dim);
267 auto const T = Eigen::Map<
typename ShapeMatricesType::template VectorType<
268 temperature_size>
const>(local_x.data() + temperature_index,
270 auto const p_L = Eigen::Map<
271 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
272 local_x.data() + pressure_index, pressure_size);
275 Eigen::Map<
typename ShapeMatricesTypeDisplacement::template VectorType<
276 displacement_size>
const>(local_x.data() + displacement_index,
280 Eigen::Map<
typename ShapeMatricesType::template VectorType<
281 temperature_size>
const>(local_xdot.data() + temperature_index,
283 auto const p_L_dot = Eigen::Map<
284 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
285 local_xdot.data() + pressure_index, pressure_size);
287 Eigen::Map<
typename ShapeMatricesTypeDisplacement::template VectorType<
288 displacement_size>
const>(local_xdot.data() + displacement_index,
292 typename ShapeMatricesTypeDisplacement::template MatrixType<
293 local_matrix_dim, local_matrix_dim>>(
294 local_Jac_data, local_matrix_dim, local_matrix_dim);
298 template VectorType<local_matrix_dim>>(
299 local_rhs_data, local_matrix_dim);
303 DisplacementDim)>::identity2;
306 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
309 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
312 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
315 ShapeMatricesType::NodalMatrixType::Zero(pressure_size,
318 ShapeMatricesType::NodalMatrixType::Zero(pressure_size, pressure_size);
321 ShapeMatricesType::NodalMatrixType::Zero(pressure_size, pressure_size);
324 ShapeMatricesType::NodalMatrixType::Zero(pressure_size, pressure_size);
327 ShapeMatricesType::NodalMatrixType::Zero(pressure_size, pressure_size);
329 typename ShapeMatricesTypeDisplacement::template MatrixType<
330 pressure_size, displacement_size>
331 Kpu = ShapeMatricesTypeDisplacement::template MatrixType<
332 pressure_size, displacement_size>::Zero(pressure_size,
335 auto const& medium = process_data_.media_map->getMedium(element_.getID());
336 auto const& liquid_phase = medium->phase(
"AqueousLiquid");
337 auto const& solid_phase = medium->phase(
"Solid");
344 unsigned const n_integration_points =
345 integration_method_.getNumberOfPoints();
346 for (
unsigned ip = 0; ip < n_integration_points; ip++)
349 auto& ip_data = ip_data_[ip];
350 auto const& w = ip_data.integration_weight;
352 auto const& N_u_op = ip_data.N_u_op;
354 auto const& N_u = ip_data.N_u;
355 auto const& dNdx_u = ip_data.dNdx_u;
358 auto const& N = ip_data.N_p;
359 auto const& dNdx = ip_data.dNdx_p;
367 ShapeFunctionDisplacement::NPOINTS,
369 dNdx_u, N_u, x_coord, is_axially_symmetric_);
375 double const dT = T_dot_ip * dt;
385 variables[
static_cast<int>(MPL::Variable::phase_pressure)] = -p_cap_ip;
388 auto& eps = ip_data.eps;
389 auto& eps_m = ip_data.eps_m;
390 eps.noalias() = B * u;
391 auto const& sigma_eff = ip_data.sigma_eff;
392 auto& S_L = ip_data.saturation;
393 auto const S_L_prev = ip_data.saturation_prev;
396 .template value<double>(variables, x_position, t, dt);
398 double const T_ip_prev = T_ip - dT;
399 auto const C_el = ip_data.computeElasticTangentStiffness(
400 t, x_position, dt, T_ip_prev, T_ip);
404 ip_data.solid_material.getBulkModulus(t, x_position, &C_el);
405 variables[
static_cast<int>(MPL::Variable::grain_compressibility)] =
410 .template value<double>(variables, x_position, t, dt);
411 auto const& b = process_data_.specific_body_force;
414 .template value<double>(variables, x_position, t, dt);
415 variables[
static_cast<int>(MPL::Variable::liquid_saturation)] = S_L;
416 variables_prev[
static_cast<int>(MPL::Variable::liquid_saturation)] =
420 double const dS_L_dp_cap =
422 .template dValue<double>(variables,
427 double const DeltaS_L_Deltap_cap =
428 (p_cap_dot_ip == 0) ? dS_L_dp_cap
429 : (S_L - S_L_prev) / (dt * p_cap_dot_ip);
431 auto const chi = [medium, x_position, t, dt](
double const S_L)
434 vs[
static_cast<int>(MPL::Variable::liquid_saturation)] = S_L;
436 .template value<double>(vs, x_position, t, dt);
438 double const chi_S_L = chi(S_L);
439 double const chi_S_L_prev = chi(S_L_prev);
441 variables[
static_cast<int>(MPL::Variable::effective_pore_pressure)] =
443 variables_prev[
static_cast<int>(
444 MPL::Variable::effective_pore_pressure)] =
445 -chi_S_L_prev * (p_cap_ip - p_cap_dot_ip * dt);
448 variables[
static_cast<int>(MPL::Variable::volumetric_strain)]
449 .emplace<double>(Invariants::trace(eps));
450 variables_prev[
static_cast<int>(MPL::Variable::volumetric_strain)]
451 .emplace<double>(Invariants::trace(B * (u - u_dot * dt)));
453 auto& phi = ip_data.porosity;
457 ip_data.porosity_prev;
459 .template value<double>(variables, variables_prev,
467 "ThermoRichardsMechanics: Biot-coefficient {} is smaller than "
468 "porosity {} in element/integration point {}/{}.",
469 alpha, phi, element_.getID(), ip);
475 auto& sigma_sw = ip_data.sigma_sw;
476 auto const& sigma_sw_prev = ip_data.sigma_sw_prev;
480 sigma_sw = sigma_sw_prev;
482 using DimMatrix = Eigen::Matrix<double, 3, 3>;
483 auto const sigma_sw_dot =
484 MathLib::KelvinVector::tensorToKelvin<DisplacementDim>(
487 .
template value<DimMatrix>(variables, variables_prev,
489 sigma_sw += sigma_sw_dot * dt;
493 std::get<double>(variables[
static_cast<int>(
494 MPL::Variable::volumetric_strain)]) +=
495 identity2.transpose() * C_el.inverse() * sigma_sw;
496 std::get<double>(variables_prev[
static_cast<int>(
497 MPL::Variable::volumetric_strain)]) +=
498 identity2.transpose() * C_el.inverse() * sigma_sw_prev;
503 variables_prev[
static_cast<int>(
505 ip_data.transport_porosity_prev;
507 ip_data.transport_porosity =
509 .template value<double>(variables, variables_prev,
512 ip_data.transport_porosity;
526 DisplacementDim>
const solid_linear_thermal_expansivity_vector =
527 MPL::formKelvinVectorFromThermalExpansivity<DisplacementDim>(
531 .value(variables, x_position, t, dt));
534 dthermal_strain = solid_linear_thermal_expansivity_vector * dT;
536 auto& eps_prev = ip_data.eps_prev;
537 auto& eps_m_prev = ip_data.eps_m_prev;
538 eps_m.noalias() = eps_m_prev + eps - eps_prev - dthermal_strain;
543 C_el.inverse() * (ip_data.sigma_sw - ip_data.sigma_sw_prev);
546 variables[
static_cast<int>(
551 auto C = ip_data.updateConstitutiveRelation(variables, t, x_position,
555 .template block<displacement_size, displacement_size>(
556 displacement_index, displacement_index)
557 .noalias() += B.transpose() * C * B * w;
559 double const p_FR = -chi_S_L * p_cap_ip;
561 variables[
static_cast<int>(MPL::Variable::solid_grain_pressure)] =
562 p_FR - Invariants::trace(sigma_eff) / (3 * (1 - phi));
565 .template value<double>(variables, x_position, t, dt);
567 double const rho = rho_SR * (1 - phi) + S_L * phi * rho_LR;
569 auto const sigma_total =
570 (sigma_eff +
alpha * chi_S_L * identity2 * p_cap_ip).eval();
572 local_rhs.template segment<displacement_size>(displacement_index)
574 (B.transpose() * sigma_total - N_u_op.transpose() * rho * b) * w;
579 auto const dchi_dS_L =
581 .template dValue<double>(variables,
582 MPL::Variable::liquid_saturation,
585 .template block<displacement_size, pressure_size>(
586 displacement_index, pressure_index)
587 .noalias() -= B.transpose() *
alpha *
588 (chi_S_L + dchi_dS_L * p_cap_ip * dS_L_dp_cap) *
592 .template block<displacement_size, pressure_size>(
593 displacement_index, pressure_index)
595 N_u_op.transpose() * phi * rho_LR * dS_L_dp_cap * b * N * w;
599 using DimMatrix = Eigen::Matrix<double, 3, 3>;
600 auto const dsigma_sw_dS_L =
601 MathLib::KelvinVector::tensorToKelvin<DisplacementDim>(
604 .
template dValue<DimMatrix>(
605 variables, variables_prev,
606 MPL::Variable::liquid_saturation, x_position, t,
609 .template block<displacement_size, pressure_size>(
610 displacement_index, pressure_index)
612 B.transpose() * dsigma_sw_dS_L * dS_L_dp_cap * N * w;
618 Kpu.noalias() += N.transpose() * S_L * rho_LR *
alpha *
619 identity2.transpose() * B * w;
626 .template value<double>(variables, x_position, t, dt);
629 .template value<double>(variables, x_position, t, dt);
635 variables[
static_cast<int>(MPL::Variable::total_stress)]
636 .emplace<SymmetricTensor>(
640 variables[
static_cast<int>(
642 ip_data.material_state_variables->getEquivalentPlasticStrain();
644 auto const K_intrinsic = MPL::formEigenTensor<DisplacementDim>(
646 .value(variables, x_position, t, dt));
651 laplace_p.noalias() +=
652 dNdx.transpose() * k_rel * rho_Ki_over_mu * dNdx * w;
654 auto const beta_LR = 1 / rho_LR *
656 .template dValue<double>(
657 variables, MPL::Variable::phase_pressure,
660 const double alphaB_minus_phi =
alpha - phi;
661 double const a0 = alphaB_minus_phi * beta_SR;
662 double const specific_storage_a_p = S_L * (phi * beta_LR + S_L * a0);
663 double const specific_storage_a_S = phi - p_cap_ip * S_L * a0;
666 double const dspecific_storage_a_p_dp_cap =
667 dS_L_dp_cap * (phi * beta_LR + 2 * S_L * a0);
668 double const dspecific_storage_a_S_dp_cap =
669 -a0 * (S_L + p_cap_ip * dS_L_dp_cap);
671 storage_p_a_p.noalias() +=
672 N.transpose() * rho_LR * specific_storage_a_p * N * w;
674 storage_p_a_S.noalias() -= N.transpose() * rho_LR *
675 specific_storage_a_S * DeltaS_L_Deltap_cap *
679 .template block<pressure_size, pressure_size>(pressure_index,
681 .noalias() += N.transpose() * p_cap_dot_ip * rho_LR *
682 dspecific_storage_a_p_dp_cap * N * w;
684 storage_p_a_S_Jpp.noalias() -=
685 N.transpose() * rho_LR *
686 ((S_L - S_L_prev) * dspecific_storage_a_S_dp_cap +
687 specific_storage_a_S * dS_L_dp_cap) /
691 .template block<pressure_size, pressure_size>(pressure_index,
693 .noalias() -= N.transpose() * rho_LR * dS_L_dp_cap *
alpha *
694 identity2.transpose() * B * u_dot * N * w;
696 double const dk_rel_dS_L =
698 .template dValue<double>(variables,
699 MPL::Variable::liquid_saturation,
703 .template block<pressure_size, pressure_size>(pressure_index,
705 .noalias() += dNdx.transpose() * rho_Ki_over_mu * grad_p_cap *
706 dk_rel_dS_L * dS_L_dp_cap * N * w;
709 .template block<pressure_size, pressure_size>(pressure_index,
711 .noalias() += dNdx.transpose() * rho_LR * rho_Ki_over_mu * b *
712 dk_rel_dS_L * dS_L_dp_cap * N * w;
714 local_rhs.template segment<pressure_size>(pressure_index).noalias() +=
715 dNdx.transpose() * rho_LR * k_rel * rho_Ki_over_mu * b * w;
721 double const fluid_volumetric_thermal_expansion =
723 liquid_phase, variables, rho_LR, x_position, t, dt);
725 const double eff_thermal_expansion =
727 Invariants::trace(solid_linear_thermal_expansivity_vector) +
728 fluid_volumetric_thermal_expansion;
731 N.transpose() * S_L * rho_LR * eff_thermal_expansion * N * w;
738 auto const specific_heat_capacity_fluid =
741 .template value<double>(variables, x_position, t, dt);
743 auto const specific_heat_capacity_solid =
747 .template value<double>(variables, x_position, t, dt);
751 (rho_SR * specific_heat_capacity_solid * (1 - phi) +
752 (S_L * rho_LR * specific_heat_capacity_fluid) * phi) *
756 MaterialPropertyLib::formEigenTensor<DisplacementDim>(
760 .value(variables, x_position, t, dt));
763 -Ki_over_mu * k_rel * (dNdx * p_L - rho_LR * b));
766 N.transpose() * velocity_L.transpose() * dNdx *
767 rho_LR * specific_heat_capacity_fluid) *
773 K_Tp.noalias() -= rho_LR * specific_heat_capacity_fluid *
774 N.transpose() * (dNdx * T).transpose() * k_rel *
775 Ki_over_mu * dNdx * w;
776 K_Tp.noalias() -= rho_LR * specific_heat_capacity_fluid *
777 N.transpose() * velocity_L.dot(dNdx * T) / k_rel *
778 dk_rel_dS_L * dS_L_dp_cap * N * w;
782 if (process_data_.apply_mass_lumping)
784 storage_p_a_p = storage_p_a_p.colwise().sum().eval().asDiagonal();
785 storage_p_a_S = storage_p_a_S.colwise().sum().eval().asDiagonal();
787 storage_p_a_S_Jpp.colwise().sum().eval().asDiagonal();
795 .template block<temperature_size, temperature_size>(temperature_index,
797 .noalias() += M_TT / dt + K_TT;
800 .template block<temperature_size, pressure_size>(temperature_index,
806 .template block<pressure_size, pressure_size>(pressure_index,
808 .noalias() += laplace_p + storage_p_a_p / dt + storage_p_a_S_Jpp;
812 .template block<pressure_size, temperature_size>(pressure_index,
814 .noalias() += M_pT / dt;
818 .template block<pressure_size, displacement_size>(pressure_index,
820 .noalias() = Kpu / dt;
826 local_rhs.template segment<temperature_size>(temperature_index).noalias() -=
827 M_TT * T_dot + K_TT * T;
830 local_rhs.template segment<pressure_size>(pressure_index).noalias() -=
831 laplace_p * p_L + (storage_p_a_p + storage_p_a_S) * p_L_dot +
832 Kpu * u_dot + M_pT * T_dot;
835 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
836 typename IntegrationMethod,
int DisplacementDim>
838 ShapeFunctionDisplacement, ShapeFunction, IntegrationMethod,
839 DisplacementDim>::getSigma()
const
841 constexpr
int kelvin_vector_size =
844 return transposeInPlace<kelvin_vector_size>(
845 [
this](std::vector<double>& values)
846 {
return getIntPtSigma(0, {}, {}, values); });
849 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
850 typename IntegrationMethod,
int DisplacementDim>
851 std::vector<double>
const&
853 IntegrationMethod, DisplacementDim>::
856 std::vector<GlobalVector*>
const& ,
857 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& ,
858 std::vector<double>& cache)
const
860 return ProcessLib::getIntegrationPointKelvinVectorData<DisplacementDim>(
861 ip_data_, &IpData::sigma_eff, cache);
864 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
865 typename IntegrationMethod,
int DisplacementDim>
867 ShapeFunctionDisplacement, ShapeFunction, IntegrationMethod,
868 DisplacementDim>::getSwellingStress()
const
870 constexpr
int kelvin_vector_size =
873 return transposeInPlace<kelvin_vector_size>(
874 [
this](std::vector<double>& values)
875 {
return getIntPtSwellingStress(0, {}, {}, values); });
878 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
879 typename IntegrationMethod,
int DisplacementDim>
880 std::vector<double>
const&
882 IntegrationMethod, DisplacementDim>::
883 getIntPtSwellingStress(
885 std::vector<GlobalVector*>
const& ,
886 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& ,
887 std::vector<double>& cache)
const
889 constexpr
int kelvin_vector_size =
891 auto const n_integration_points = ip_data_.size();
895 double, kelvin_vector_size, Eigen::Dynamic, Eigen::RowMajor>>(
896 cache, kelvin_vector_size, n_integration_points);
898 for (
unsigned ip = 0; ip < n_integration_points; ++ip)
900 auto const& sigma_sw = ip_data_[ip].sigma_sw;
908 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
909 typename IntegrationMethod,
int DisplacementDim>
911 ShapeFunctionDisplacement, ShapeFunction, IntegrationMethod,
912 DisplacementDim>::getEpsilon()
const
914 constexpr
int kelvin_vector_size =
917 return transposeInPlace<kelvin_vector_size>(
918 [
this](std::vector<double>& values)
919 {
return getIntPtEpsilon(0, {}, {}, values); });
922 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
923 typename IntegrationMethod,
int DisplacementDim>
924 std::vector<double>
const&
926 IntegrationMethod, DisplacementDim>::
929 std::vector<GlobalVector*>
const& ,
930 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& ,
931 std::vector<double>& cache)
const
933 return ProcessLib::getIntegrationPointKelvinVectorData<DisplacementDim>(
934 ip_data_, &IpData::eps, cache);
937 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
938 typename IntegrationMethod,
int DisplacementDim>
939 std::vector<double>
const&
941 IntegrationMethod, DisplacementDim>::
942 getIntPtDarcyVelocity(
944 std::vector<GlobalVector*>
const& ,
945 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& ,
946 std::vector<double>& cache)
const
948 unsigned const n_integration_points =
949 integration_method_.getNumberOfPoints();
953 double, DisplacementDim, Eigen::Dynamic, Eigen::RowMajor>>(
954 cache, DisplacementDim, n_integration_points);
956 for (
unsigned ip = 0; ip < n_integration_points; ip++)
958 cache_matrix.col(ip).noalias() = ip_data_[ip].v_darcy;
964 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
965 typename IntegrationMethod,
int DisplacementDim>
967 ShapeFunctionDisplacement, ShapeFunction, IntegrationMethod,
968 DisplacementDim>::getSaturation()
const
970 std::vector<double> result;
971 getIntPtSaturation(0, {}, {}, result);
975 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
976 typename IntegrationMethod,
int DisplacementDim>
977 std::vector<double>
const&
979 IntegrationMethod, DisplacementDim>::
982 std::vector<GlobalVector*>
const& ,
983 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& ,
984 std::vector<double>& cache)
const
990 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
991 typename IntegrationMethod,
int DisplacementDim>
993 ShapeFunctionDisplacement, ShapeFunction, IntegrationMethod,
994 DisplacementDim>::getPorosity()
const
996 std::vector<double> result;
997 getIntPtPorosity(0, {}, {}, result);
1001 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
1002 typename IntegrationMethod,
int DisplacementDim>
1003 std::vector<double>
const&
1005 IntegrationMethod, DisplacementDim>::
1008 std::vector<GlobalVector*>
const& ,
1009 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& ,
1010 std::vector<double>& cache)
const
1016 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
1017 typename IntegrationMethod,
int DisplacementDim>
1019 ShapeFunctionDisplacement, ShapeFunction, IntegrationMethod,
1020 DisplacementDim>::getTransportPorosity()
const
1022 std::vector<double> result;
1023 getIntPtTransportPorosity(0, {}, {}, result);
1027 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
1028 typename IntegrationMethod,
int DisplacementDim>
1029 std::vector<double>
const&
1031 IntegrationMethod, DisplacementDim>::
1032 getIntPtTransportPorosity(
1034 std::vector<GlobalVector*>
const& ,
1035 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& ,
1036 std::vector<double>& cache)
const
1042 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
1043 typename IntegrationMethod,
int DisplacementDim>
1044 std::vector<double>
const&
1046 IntegrationMethod, DisplacementDim>::
1047 getIntPtDryDensitySolid(
1049 std::vector<GlobalVector*>
const& ,
1050 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& ,
1051 std::vector<double>& cache)
const
1054 ip_data_, &IpData::dry_density_solid, cache);
1057 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
1058 typename IntegrationMethod,
int DisplacementDim>
1060 ShapeFunction, IntegrationMethod,
1062 computeSecondaryVariableConcrete(
double const t,
double const dt,
1063 Eigen::VectorXd
const& local_x,
1064 Eigen::VectorXd
const& local_x_dot)
1067 local_x.template segment<temperature_size>(temperature_index);
1068 auto const p_L = local_x.template segment<pressure_size>(pressure_index);
1070 local_x.template segment<displacement_size>(displacement_index);
1073 local_x_dot.template segment<temperature_size>(temperature_index);
1074 auto const p_L_dot =
1075 local_x_dot.template segment<pressure_size>(pressure_index);
1077 local_x_dot.template segment<displacement_size>(displacement_index);
1081 DisplacementDim)>::identity2;
1083 auto const& medium = process_data_.media_map->getMedium(element_.getID());
1084 auto const& liquid_phase = medium->phase(
"AqueousLiquid");
1085 auto const& solid_phase = medium->phase(
"Solid");
1092 unsigned const n_integration_points =
1093 integration_method_.getNumberOfPoints();
1095 double saturation_avg = 0;
1096 double porosity_avg = 0;
1099 KV sigma_avg = KV::Zero();
1101 for (
unsigned ip = 0; ip < n_integration_points; ip++)
1105 auto& ip_data = ip_data_[ip];
1107 auto const& N = ip_data.N_p;
1108 auto const& N_u = ip_data.N_u;
1109 auto const& dNdx_u = ip_data.dNdx_u;
1111 auto const x_coord =
1117 ShapeFunctionDisplacement::NPOINTS,
1119 dNdx_u, N_u, x_coord, is_axially_symmetric_);
1125 double const dT = T_dot_ip * dt;
1130 double p_cap_dot_ip;
1135 variables[
static_cast<int>(MPL::Variable::phase_pressure)] = -p_cap_ip;
1139 auto& eps = ip_data.eps;
1140 eps.noalias() = B * u;
1141 auto& eps_m = ip_data.eps_m;
1142 auto& S_L = ip_data.saturation;
1143 auto const S_L_prev = ip_data.saturation_prev;
1145 .template value<double>(variables, x_position, t, dt);
1146 variables[
static_cast<int>(MPL::Variable::liquid_saturation)] = S_L;
1147 variables_prev[
static_cast<int>(MPL::Variable::liquid_saturation)] =
1150 auto const chi = [medium, x_position, t, dt](
double const S_L)
1153 vs.fill(std::numeric_limits<double>::quiet_NaN());
1154 vs[
static_cast<int>(MPL::Variable::liquid_saturation)] = S_L;
1156 .template value<double>(vs, x_position, t, dt);
1158 double const chi_S_L = chi(S_L);
1159 double const chi_S_L_prev = chi(S_L_prev);
1163 .template value<double>(variables, x_position, t, dt);
1165 double const T_ip_prev = T_ip - dT;
1166 auto const C_el = ip_data.computeElasticTangentStiffness(
1167 t, x_position, dt, T_ip_prev, T_ip);
1169 auto const beta_SR =
1171 ip_data.solid_material.getBulkModulus(t, x_position, &C_el);
1172 variables[
static_cast<int>(MPL::Variable::grain_compressibility)] =
1175 variables[
static_cast<int>(MPL::Variable::effective_pore_pressure)] =
1176 -chi_S_L * p_cap_ip;
1177 variables_prev[
static_cast<int>(
1178 MPL::Variable::effective_pore_pressure)] =
1179 -chi_S_L_prev * (p_cap_ip - p_cap_dot_ip * dt);
1182 variables[
static_cast<int>(MPL::Variable::volumetric_strain)]
1183 .emplace<double>(Invariants::trace(eps));
1184 variables_prev[
static_cast<int>(MPL::Variable::volumetric_strain)]
1185 .emplace<double>(Invariants::trace(B * (u - u_dot * dt)));
1187 auto& phi = ip_data.porosity;
1190 ip_data.porosity_prev;
1192 .template value<double>(variables, variables_prev,
1200 auto& sigma_sw = ip_data.sigma_sw;
1201 auto const& sigma_sw_prev = ip_data.sigma_sw_prev;
1205 sigma_sw = sigma_sw_prev;
1207 using DimMatrix = Eigen::Matrix<double, 3, 3>;
1208 auto const sigma_sw_dot =
1209 MathLib::KelvinVector::tensorToKelvin<DisplacementDim>(
1212 .
template value<DimMatrix>(variables, variables_prev,
1213 x_position, t, dt));
1214 sigma_sw += sigma_sw_dot * dt;
1218 std::get<double>(variables[
static_cast<int>(
1219 MPL::Variable::volumetric_strain)]) +=
1220 identity2.transpose() * C_el.inverse() * sigma_sw;
1221 std::get<double>(variables_prev[
static_cast<int>(
1222 MPL::Variable::volumetric_strain)]) +=
1223 identity2.transpose() * C_el.inverse() * sigma_sw_prev;
1228 variables_prev[
static_cast<int>(
1230 ip_data.transport_porosity_prev;
1232 ip_data.transport_porosity =
1234 .template value<double>(variables, variables_prev,
1237 ip_data.transport_porosity;
1247 .template value<double>(variables, x_position, t, dt);
1250 .template value<double>(variables, x_position, t, dt);
1255 auto const sigma_total =
1256 (ip_data.sigma_eff +
alpha * chi_S_L * identity2 * p_cap_ip)
1259 variables[
static_cast<int>(MPL::Variable::total_stress)]
1260 .emplace<SymmetricTensor>(
1265 variables[
static_cast<int>(
1267 ip_data.material_state_variables->getEquivalentPlasticStrain();
1268 auto const K_intrinsic = MPL::formEigenTensor<DisplacementDim>(
1270 .value(variables, x_position, t, dt));
1272 double const k_rel =
1274 .template value<double>(variables, x_position, t, dt);
1278 auto const& sigma_eff = ip_data.sigma_eff;
1279 double const p_FR = -chi_S_L * p_cap_ip;
1281 variables[
static_cast<int>(MPL::Variable::solid_grain_pressure)] =
1282 p_FR - Invariants::trace(sigma_eff) / (3 * (1 - phi));
1285 .template value<double>(variables, x_position, t, dt);
1286 ip_data.dry_density_solid = (1 - phi) * rho_SR;
1289 DisplacementDim>
const solid_linear_thermal_expansivity_vector =
1290 MPL::formKelvinVectorFromThermalExpansivity<DisplacementDim>(
1294 .value(variables, x_position, t, dt));
1297 dthermal_strain = solid_linear_thermal_expansivity_vector * dT;
1299 auto& eps_prev = ip_data.eps_prev;
1300 auto& eps_m_prev = ip_data.eps_m_prev;
1301 eps_m.noalias() = eps_m_prev + eps - eps_prev - dthermal_strain;
1306 -C_el.inverse() * (ip_data.sigma_sw - ip_data.sigma_sw_prev);
1309 variables[
static_cast<int>(
1314 ip_data.updateConstitutiveRelation(variables, t, x_position, dt,
1317 auto const& b = process_data_.specific_body_force;
1320 auto const& dNdx = ip_data.dNdx_p;
1321 ip_data.v_darcy.noalias() =
1322 -K_over_mu * dNdx * p_L + rho_LR * K_over_mu * b;
1324 saturation_avg += S_L;
1325 porosity_avg += phi;
1326 sigma_avg += sigma_eff;
1328 saturation_avg /= n_integration_points;
1329 porosity_avg /= n_integration_points;
1330 sigma_avg /= n_integration_points;
1332 (*process_data_.element_saturation)[element_.getID()] = saturation_avg;
1333 (*process_data_.element_porosity)[element_.getID()] = porosity_avg;
1335 Eigen::Map<KV>(&(*process_data_.element_stresses)[element_.getID() *
1336 KV::RowsAtCompileTime]) =
1340 ShapeFunction,
typename ShapeFunctionDisplacement::MeshElement,
1341 DisplacementDim>(element_, is_axially_symmetric_, p_L,
1342 *process_data_.pressure_interpolated);
1344 ShapeFunction,
typename ShapeFunctionDisplacement::MeshElement,
1345 DisplacementDim>(element_, is_axially_symmetric_, T,
1346 *process_data_.temperature_interpolated);
1349 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
1350 typename IntegrationMethod,
int DisplacementDim>
1352 ShapeFunctionDisplacement, ShapeFunction, IntegrationMethod,
1353 DisplacementDim>::getNumberOfIntegrationPoints()
const
1355 return integration_method_.getNumberOfPoints();
1358 template <
typename ShapeFunctionDisplacement,
typename ShapeFunction,
1359 typename IntegrationMethod,
int DisplacementDim>
1361 DisplacementDim>::MaterialStateVariables
const&
1363 IntegrationMethod, DisplacementDim>::
1364 getMaterialStateVariablesAt(
unsigned integration_point)
const
1366 return *ip_data_[integration_point].material_state_variables;
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
ShapeMatrixPolicyType< ShapeFunctionDisplacement, DisplacementDim > ShapeMatricesTypeDisplacement
MeshLib::Element const & element_
ThermoRichardsMechanicsProcessData< DisplacementDim > & process_data_
typename ShapeMatricesType::GlobalDimVectorType GlobalDimVectorType
SecondaryData< typename ShapeMatricesTypeDisplacement::ShapeMatrices::ShapeType > secondary_data_
static const int displacement_size
typename ShapeMatricesType::GlobalDimMatrixType GlobalDimMatrixType
std::vector< IpData, Eigen::aligned_allocator< IpData > > ip_data_
IntegrationMethod integration_method_
ShapeMatrixPolicyType< ShapeFunction, DisplacementDim > ShapeMatricesType
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
@ bishops_effective_stress
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
constexpr int kelvin_vector_dimensions(int const displacement_dim)
Kelvin vector dimensions for given displacement dimension.
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 shapeFunctionInterpolate(const NodalValues &nodal_values, const ShapeMatrix &shape_matrix_N, double &interpolated_value, ScalarTypes &... interpolated_values)
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< 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.
std::vector< double > const & getIntegrationPointScalarData(std::vector< IntegrationPointData, Eigen::aligned_allocator< IntegrationPointData >> const &ip_data, MemberType member, std::vector< double > &cache)
std::size_t setIntegrationPointScalarData(double const *values, std::vector< IntegrationPointData, Eigen::aligned_allocator< IntegrationPointData >> &ip_data, MemberType member)
MatrixType< ShapeFunction::NPOINTS, ShapeFunction::NPOINTS > NodalMatrixType
std::vector< ShapeMatrixType, Eigen::aligned_allocator< ShapeMatrixType > > N_u