31 namespace ThermoRichardsFlow
33 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
38 bool const is_axially_symmetric,
39 unsigned const integration_order,
41 : _process_data(process_data),
42 _integration_method(integration_order),
44 _is_axially_symmetric(is_axially_symmetric)
46 unsigned const n_integration_points =
49 _ip_data.reserve(n_integration_points);
51 auto const shape_matrices =
52 NumLib::initShapeMatrices<ShapeFunction, ShapeMatricesType, GlobalDim>(
59 for (
unsigned ip = 0; ip < n_integration_points; ip++)
61 auto const& sm = shape_matrices[ip];
67 sm.integralMeasure * sm.detJ;
70 ip_data.dNdx = sm.dNdx;
73 ip_data.porosity = medium[
MPL::porosity].template initialValue<double>(
75 std::numeric_limits<double>::quiet_NaN() );
79 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
81 ShapeFunction, IntegrationMethod,
82 GlobalDim>::setIPDataInitialConditions(std::string
const&
name,
84 int const integration_order)
86 if (integration_order !=
87 static_cast<int>(_integration_method.getIntegrationOrder()))
90 "Setting integration point initial conditions; The integration "
91 "order of the local assembler for element {:d} is different "
92 "from the integration order in the initial condition.",
96 if (
name ==
"saturation_ip")
101 if (
name ==
"porosity_ip")
109 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
112 setInitialConditionsConcrete(std::vector<double>
const& local_x,
117 assert(local_x.size() == temperature_size + pressure_size);
119 auto p_L = Eigen::Map<
120 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
121 local_x.data() + pressure_index, pressure_size);
123 auto const& medium = *_process_data.media_map->getMedium(_element.getID());
129 unsigned const n_integration_points =
130 _integration_method.getNumberOfPoints();
131 for (
unsigned ip = 0; ip < n_integration_points; ip++)
135 auto const& N = _ip_data[ip].N;
142 variables[
static_cast<int>(MPL::Variable::phase_pressure)] = -p_cap_ip;
146 _ip_data[ip].saturation_prev =
148 variables, x_position, t,
149 std::numeric_limits<double>::quiet_NaN());
153 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
155 ShapeFunction, IntegrationMethod,
156 GlobalDim>::assembleWithJacobian(
double const t,
double const dt,
157 std::vector<double>
const& local_x,
158 std::vector<double>
const& local_xdot,
161 std::vector<double>& ,
162 std::vector<double>& ,
163 std::vector<double>& local_rhs_data,
164 std::vector<double>& local_Jac_data)
166 auto const local_matrix_dim = pressure_size + temperature_size;
167 assert(local_x.size() == local_matrix_dim);
169 auto const T = Eigen::Map<
typename ShapeMatricesType::template VectorType<
170 temperature_size>
const>(local_x.data() + temperature_index,
172 auto const p_L = Eigen::Map<
173 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
174 local_x.data() + pressure_index, pressure_size);
177 Eigen::Map<
typename ShapeMatricesType::template VectorType<
178 temperature_size>
const>(local_xdot.data() + temperature_index,
180 auto const p_L_dot = Eigen::Map<
181 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
182 local_xdot.data() + pressure_index, pressure_size);
185 typename ShapeMatricesType::template MatrixType<local_matrix_dim,
187 local_Jac_data, local_matrix_dim, local_matrix_dim);
190 typename ShapeMatricesType::template VectorType<local_matrix_dim>>(
191 local_rhs_data, local_matrix_dim);
194 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
197 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
200 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
203 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
206 ShapeMatricesType::NodalMatrixType::Zero(pressure_size,
209 ShapeMatricesType::NodalMatrixType::Zero(pressure_size, pressure_size);
212 ShapeMatricesType::NodalMatrixType::Zero(pressure_size, pressure_size);
215 ShapeMatricesType::NodalMatrixType::Zero(pressure_size, pressure_size);
218 ShapeMatricesType::NodalMatrixType::Zero(pressure_size, pressure_size);
220 auto const& medium = *_process_data.media_map->getMedium(_element.getID());
221 auto const& liquid_phase = medium.phase(
"AqueousLiquid");
222 auto const& solid_phase = medium.phase(
"Solid");
224 medium.hasPhase(
"Gas") ? &medium.phase(
"Gas") :
nullptr;
231 unsigned const n_integration_points =
232 _integration_method.getNumberOfPoints();
233 for (
unsigned ip = 0; ip < n_integration_points; ip++)
236 auto const& w = _ip_data[ip].integration_weight;
238 auto const& N = _ip_data[ip].N;
239 auto const& dNdx = _ip_data[ip].dNdx;
254 variables[
static_cast<int>(MPL::Variable::phase_pressure)] = -p_cap_ip;
257 auto& S_L = _ip_data[ip].saturation;
258 auto const S_L_prev = _ip_data[ip].saturation_prev;
261 variables, x_position, t, dt);
263 auto& solid_elasticity = *_process_data.simplified_elasticity;
267 solid_elasticity.bulkCompressibilityFromYoungsModulus(
268 solid_phase, variables, x_position, t, dt);
269 auto const beta_SR = (1 -
alpha) * beta_S;
270 variables[
static_cast<int>(MPL::Variable::grain_compressibility)] =
275 variables, x_position, t, dt);
276 auto const& b = _process_data.specific_body_force;
278 double const drho_LR_dp =
280 variables, MPL::Variable::phase_pressure, x_position, t, dt);
281 auto const beta_LR = drho_LR_dp / rho_LR;
284 variables, x_position, t, dt);
285 variables[
static_cast<int>(MPL::Variable::liquid_saturation)] = S_L;
286 variables_prev[
static_cast<int>(MPL::Variable::liquid_saturation)] =
290 double const dS_L_dp_cap =
296 double const DeltaS_L_Deltap_cap =
297 (p_cap_dot_ip == 0) ? dS_L_dp_cap
298 : (S_L - S_L_prev) / (dt * p_cap_dot_ip);
301 auto chi_S_L_prev = S_L_prev;
302 auto dchi_dS_L = 1.0;
305 auto const chi = [&medium, x_position, t, dt](
double const S_L)
308 variables[
static_cast<int>(MPL::Variable::liquid_saturation)] =
311 .template value<double>(variables, x_position, t, dt);
314 chi_S_L_prev = chi(S_L_prev);
317 .template dValue<double>(
318 variables, MPL::Variable::liquid_saturation,
327 variables[
static_cast<int>(MPL::Variable::effective_pore_pressure)] =
329 variables_prev[
static_cast<int>(
330 MPL::Variable::effective_pore_pressure)] =
331 -chi_S_L_prev * (p_cap_ip - p_cap_dot_ip * dt);
333 auto& phi = _ip_data[ip].porosity;
337 _ip_data[ip].porosity_prev;
339 variables, variables_prev, x_position, t, dt);
346 "ThermoRichardsFlow: Biot-coefficient {} is smaller than "
347 "porosity {} in element/integration point {}/{}.",
348 alpha, phi, _element.getID(), ip);
353 .template value<double>(variables, x_position, t, dt);
356 variables, x_position, t, dt);
358 auto const K_intrinsic = MPL::formEigenTensor<GlobalDim>(
368 Eigen::Matrix<double, 3, 3>
const
369 solid_linear_thermal_expansion_coefficient =
373 .value(variables, x_position, t, dt));
377 variables, x_position, t, dt);
382 laplace_p.noalias() +=
383 dNdx.transpose() * k_rel * rho_Ki_over_mu * dNdx * w;
385 const double alphaB_minus_phi =
alpha - phi;
386 double const a0 = alphaB_minus_phi * beta_SR;
387 double const specific_storage_a_p =
388 S_L * (phi * beta_LR + S_L * a0 +
390 solid_elasticity.storageContribution(
391 solid_phase, variables, x_position, t, dt));
392 double const specific_storage_a_S = phi - p_cap_ip * S_L * a0;
394 double const dspecific_storage_a_p_dp_cap =
395 dS_L_dp_cap * (phi * beta_LR + 2 * S_L * a0 +
397 solid_elasticity.storageContribution(
398 solid_phase, variables, x_position, t, dt) *
399 (chi_S_L + dchi_dS_L * S_L));
400 double const dspecific_storage_a_S_dp_cap =
401 -a0 * (S_L + p_cap_ip * dS_L_dp_cap);
403 storage_p_a_p.noalias() +=
404 N.transpose() * rho_LR * specific_storage_a_p * N * w;
406 storage_p_a_S.noalias() -= N.transpose() * rho_LR *
407 specific_storage_a_S * DeltaS_L_Deltap_cap *
411 .template block<pressure_size, pressure_size>(pressure_index,
413 .noalias() += N.transpose() * p_cap_dot_ip * rho_LR *
414 dspecific_storage_a_p_dp_cap * N * w;
416 storage_p_a_S_Jpp.noalias() -=
417 N.transpose() * rho_LR *
418 ((S_L - S_L_prev) * dspecific_storage_a_S_dp_cap +
419 specific_storage_a_S * dS_L_dp_cap) /
422 double const dk_rel_dS_L =
424 .template dValue<double>(variables,
425 MPL::Variable::liquid_saturation,
429 .template block<pressure_size, pressure_size>(pressure_index,
431 .noalias() += dNdx.transpose() * rho_Ki_over_mu * grad_p_cap *
432 dk_rel_dS_L * dS_L_dp_cap * N * w;
435 .template block<pressure_size, pressure_size>(pressure_index,
437 .noalias() += dNdx.transpose() * rho_LR * rho_Ki_over_mu * b *
438 dk_rel_dS_L * dS_L_dp_cap * N * w;
440 local_rhs.template segment<pressure_size>(pressure_index).noalias() +=
441 dNdx.transpose() * rho_LR * k_rel * rho_Ki_over_mu * b * w;
446 double const fluid_volumetric_thermal_expansion_coefficient =
449 const double eff_thermal_expansion =
450 S_L * (alphaB_minus_phi *
451 solid_linear_thermal_expansion_coefficient.trace() +
452 phi * fluid_volumetric_thermal_expansion_coefficient +
453 alpha * solid_elasticity.thermalExpansivityContribution(
454 solid_linear_thermal_expansion_coefficient,
455 solid_phase, variables, x_position, t, dt));
457 N.transpose() * rho_LR * eff_thermal_expansion * N * w;
463 auto const specific_heat_capacity_fluid =
465 .template value<double>(variables, x_position, t, dt);
467 auto const specific_heat_capacity_solid =
470 .template value<double>(variables, x_position, t, dt);
474 (rho_SR * specific_heat_capacity_solid * (1 - phi) +
475 (S_L * rho_LR * specific_heat_capacity_fluid) * phi) *
479 MaterialPropertyLib::formEigenTensor<GlobalDim>(
482 .value(variables, x_position, t, dt));
485 -Ki_over_mu * k_rel * (dNdx * p_L - rho_LR * b));
488 N.transpose() * velocity_L.transpose() * dNdx *
489 rho_LR * specific_heat_capacity_fluid) *
495 K_Tp.noalias() -= rho_LR * specific_heat_capacity_fluid *
496 N.transpose() * (dNdx * T).transpose() * k_rel *
497 Ki_over_mu * dNdx * w;
499 K_Tp.noalias() -= rho_LR * specific_heat_capacity_fluid *
500 N.transpose() * velocity_L.dot(dNdx * T) / k_rel *
501 dk_rel_dS_L * dS_L_dp_cap * N * w;
508 double const rho_wv =
510 .template value<double>(variables, x_position, t, dt);
512 double const drho_wv_dT =
514 .template dValue<double>(variables,
517 double const drho_wv_dp =
519 .template dValue<double>(variables,
520 MPL::Variable::phase_pressure,
525 .template value<double>(variables, x_position, t, dt);
530 .template value<double>(variables, x_position, t, dt);
532 double const f_Tv_D_Tv = f_Tv * D_v * drho_wv_dT;
533 double const D_pv = D_v * drho_wv_dp;
541 -(f_Tv_D_Tv * grad_T - D_pv * grad_p_cap) / rho_LR;
542 double const specific_heat_capacity_vapour =
546 .template value<double>(variables, x_position, t, dt);
550 (rho_wv * specific_heat_capacity_vapour * (1 - S_L) * phi) *
553 K_TT.noalias() += N.transpose() * q_v.transpose() * dNdx *
554 rho_wv * specific_heat_capacity_vapour * w;
557 double const storage_coefficient_by_water_vapor =
558 phi * (rho_wv * dS_L_dp_cap + (1 - S_L) * drho_wv_dp);
560 storage_p_a_p.noalias() +=
561 N.transpose() * storage_coefficient_by_water_vapor * N * w;
563 double const vapor_expansion_factor = phi * (1 - S_L) * drho_wv_dT;
564 M_pT.noalias() += N.transpose() * vapor_expansion_factor * N * w;
567 .template block<pressure_size, temperature_size>(
568 pressure_index, temperature_index)
569 .noalias() += dNdx.transpose() * f_Tv_D_Tv * dNdx * w;
571 local_rhs.template segment<pressure_size>(pressure_index)
572 .noalias() -= f_Tv_D_Tv * dNdx.transpose() * (dNdx * T) * w;
574 laplace_p.noalias() += dNdx.transpose() * D_pv * dNdx * w;
581 double const factor = phi * (1 - S_L) / rho_LR;
585 .template value<double>(variables, x_position, t, dt) *
588 double const drho_LR_dT =
590 .template dValue<double>(variables,
594 double const rho_wv_over_rho_L = rho_wv / rho_LR;
597 (drho_wv_dT - rho_wv_over_rho_L * drho_LR_dT) *
598 N.transpose() * N * w;
602 (drho_wv_dp - rho_wv_over_rho_L * drho_LR_dp) +
603 L0 * phi * rho_wv_over_rho_L * dS_L_dp_cap) *
604 N.transpose() * N * w;
608 L0 * f_Tv_D_Tv * dNdx.transpose() * dNdx * w / rho_LR;
611 L0 * D_pv * dNdx.transpose() * dNdx * w / rho_LR;
616 if (_process_data.apply_mass_lumping)
618 storage_p_a_p = storage_p_a_p.colwise().sum().eval().asDiagonal();
619 storage_p_a_S = storage_p_a_S.colwise().sum().eval().asDiagonal();
621 storage_p_a_S_Jpp.colwise().sum().eval().asDiagonal();
629 .template block<temperature_size, temperature_size>(temperature_index,
631 .noalias() += M_TT / dt + K_TT;
634 .template block<temperature_size, pressure_size>(temperature_index,
640 .template block<pressure_size, pressure_size>(pressure_index,
642 .noalias() += laplace_p + storage_p_a_p / dt + storage_p_a_S_Jpp;
646 .template block<pressure_size, temperature_size>(pressure_index,
648 .noalias() += M_pT / dt;
654 local_rhs.template segment<temperature_size>(temperature_index).noalias() -=
655 M_TT * T_dot + K_TT * T;
658 local_rhs.template segment<pressure_size>(pressure_index).noalias() -=
659 laplace_p * p_L + (storage_p_a_p + storage_p_a_S) * p_L_dot +
666 .template block<temperature_size, pressure_size>(temperature_index,
668 .noalias() += M_Tp / dt;
670 local_rhs.template segment<temperature_size>(temperature_index)
671 .noalias() -= M_Tp * p_L_dot;
675 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
677 ShapeFunction, IntegrationMethod,
678 GlobalDim>::assemble(
double const t,
double const dt,
679 std::vector<double>
const& local_x,
680 std::vector<double>
const& local_xdot,
681 std::vector<double>& local_M_data,
682 std::vector<double>& local_K_data,
683 std::vector<double>& local_rhs_data)
685 auto const local_matrix_dim = pressure_size + temperature_size;
686 assert(local_x.size() == local_matrix_dim);
688 auto const T = Eigen::Map<
typename ShapeMatricesType::template VectorType<
689 temperature_size>
const>(local_x.data() + temperature_index,
691 auto const p_L = Eigen::Map<
692 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
693 local_x.data() + pressure_index, pressure_size);
696 Eigen::Map<
typename ShapeMatricesType::template VectorType<
697 temperature_size>
const>(local_xdot.data() + temperature_index,
699 auto const p_L_dot = Eigen::Map<
700 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
701 local_xdot.data() + pressure_index, pressure_size);
704 typename ShapeMatricesType::template MatrixType<local_matrix_dim,
706 local_K_data, local_matrix_dim, local_matrix_dim);
709 typename ShapeMatricesType::template MatrixType<local_matrix_dim,
711 local_M_data, local_matrix_dim, local_matrix_dim);
714 typename ShapeMatricesType::template VectorType<local_matrix_dim>>(
715 local_rhs_data, local_matrix_dim);
717 auto const& medium = *_process_data.media_map->getMedium(_element.getID());
718 auto const& liquid_phase = medium.phase(
"AqueousLiquid");
719 auto const& solid_phase = medium.phase(
"Solid");
721 medium.hasPhase(
"Gas") ? &medium.phase(
"Gas") :
nullptr;
728 unsigned const n_integration_points =
729 _integration_method.getNumberOfPoints();
730 for (
unsigned ip = 0; ip < n_integration_points; ip++)
733 auto const& w = _ip_data[ip].integration_weight;
735 auto const& N = _ip_data[ip].N;
736 auto const& dNdx = _ip_data[ip].dNdx;
751 variables[
static_cast<int>(MPL::Variable::phase_pressure)] = -p_cap_ip;
754 auto& S_L = _ip_data[ip].saturation;
755 auto const S_L_prev = _ip_data[ip].saturation_prev;
758 variables, x_position, t, dt);
760 auto& solid_elasticity = *_process_data.simplified_elasticity;
764 solid_elasticity.bulkCompressibilityFromYoungsModulus(
765 solid_phase, variables, x_position, t, dt);
766 auto const beta_SR = (1 -
alpha) * beta_S;
767 variables[
static_cast<int>(MPL::Variable::grain_compressibility)] =
772 variables, x_position, t, dt);
773 auto const& b = _process_data.specific_body_force;
775 double const drho_LR_dp =
777 variables, MPL::Variable::phase_pressure, x_position, t, dt);
778 auto const beta_LR = drho_LR_dp / rho_LR;
781 variables, x_position, t, dt);
782 variables[
static_cast<int>(MPL::Variable::liquid_saturation)] = S_L;
783 variables_prev[
static_cast<int>(MPL::Variable::liquid_saturation)] =
787 double const dS_L_dp_cap =
793 double const DeltaS_L_Deltap_cap =
794 (p_cap_dot_ip == 0) ? dS_L_dp_cap
795 : (S_L - S_L_prev) / (dt * p_cap_dot_ip);
798 auto chi_S_L_prev = S_L_prev;
801 auto const chi = [&medium, x_position, t, dt](
double const S_L)
804 variables[
static_cast<int>(MPL::Variable::liquid_saturation)] =
807 .template value<double>(variables, x_position, t, dt);
810 chi_S_L_prev = chi(S_L_prev);
818 variables[
static_cast<int>(MPL::Variable::effective_pore_pressure)] =
820 variables_prev[
static_cast<int>(
821 MPL::Variable::effective_pore_pressure)] =
822 -chi_S_L_prev * (p_cap_ip - p_cap_dot_ip * dt);
824 auto& phi = _ip_data[ip].porosity;
828 _ip_data[ip].porosity_prev;
830 variables, variables_prev, x_position, t, dt);
837 "ThermoRichardsFlow: Biot-coefficient {} is smaller than "
838 "porosity {} in element/integration point {}/{}.",
839 alpha, phi, _element.getID(), ip);
844 .template value<double>(variables, x_position, t, dt);
847 variables, x_position, t, dt);
849 auto const K_intrinsic = MPL::formEigenTensor<GlobalDim>(
859 Eigen::Matrix<double, 3, 3>
const
860 solid_linear_thermal_expansion_coefficient =
864 .value(variables, x_position, t, dt));
868 variables, x_position, t, dt);
874 .template block<pressure_size, pressure_size>(pressure_index,
876 .noalias() += dNdx.transpose() * k_rel * rho_Ki_over_mu * dNdx * w;
878 const double alphaB_minus_phi =
alpha - phi;
879 double const a0 = alphaB_minus_phi * beta_SR;
880 double const specific_storage_a_p =
881 S_L * (phi * beta_LR + S_L * a0 +
883 solid_elasticity.storageContribution(
884 solid_phase, variables, x_position, t, dt));
885 double const specific_storage_a_S = phi - p_cap_ip * S_L * a0;
888 .template block<pressure_size, pressure_size>(pressure_index,
890 .noalias() += N.transpose() * rho_LR *
891 (specific_storage_a_p -
892 specific_storage_a_S * DeltaS_L_Deltap_cap) *
895 local_rhs.template segment<pressure_size>(pressure_index).noalias() +=
896 dNdx.transpose() * rho_LR * k_rel * rho_Ki_over_mu * b * w;
901 double const fluid_volumetric_thermal_expansion_coefficient =
904 const double eff_thermal_expansion =
905 S_L * (alphaB_minus_phi *
906 solid_linear_thermal_expansion_coefficient.trace() +
907 phi * fluid_volumetric_thermal_expansion_coefficient +
908 alpha * solid_elasticity.thermalExpansivityContribution(
909 solid_linear_thermal_expansion_coefficient,
910 solid_phase, variables, x_position, t, dt));
913 .template block<pressure_size, temperature_size>(pressure_index,
916 N.transpose() * rho_LR * eff_thermal_expansion * N * w;
922 auto const specific_heat_capacity_fluid =
924 .template value<double>(variables, x_position, t, dt);
926 auto const specific_heat_capacity_solid =
929 .template value<double>(variables, x_position, t, dt);
932 .template block<temperature_size, temperature_size>(
933 temperature_index, temperature_index)
936 (rho_SR * specific_heat_capacity_solid * (1 - phi) +
937 (S_L * rho_LR * specific_heat_capacity_fluid) * phi) *
941 MaterialPropertyLib::formEigenTensor<GlobalDim>(
944 .value(variables, x_position, t, dt));
947 -Ki_over_mu * k_rel * (dNdx * p_L - rho_LR * b));
950 .template block<temperature_size, temperature_size>(
951 temperature_index, temperature_index)
953 N.transpose() * velocity_L.transpose() * dNdx *
954 rho_LR * specific_heat_capacity_fluid) *
962 double const rho_wv =
964 .template value<double>(variables, x_position, t, dt);
966 double const drho_wv_dT =
968 .template dValue<double>(variables,
971 double const drho_wv_dp =
973 .template dValue<double>(variables,
974 MPL::Variable::phase_pressure,
979 .template value<double>(variables, x_position, t, dt);
984 .template value<double>(variables, x_position, t, dt);
986 double const f_Tv_D_Tv = f_Tv * D_v * drho_wv_dT;
987 double const D_pv = D_v * drho_wv_dp;
996 -(f_Tv_D_Tv * grad_T - D_pv * grad_p_cap) / rho_LR;
997 double const specific_heat_capacity_vapour =
1001 .template value<double>(variables, x_position, t, dt);
1004 .template block<temperature_size, temperature_size>(
1005 temperature_index, temperature_index)
1008 (rho_wv * specific_heat_capacity_vapour * (1 - S_L) * phi) *
1012 .template block<temperature_size, temperature_size>(
1013 temperature_index, temperature_index)
1014 .noalias() += N.transpose() * q_v.transpose() * dNdx *
1015 rho_wv * specific_heat_capacity_vapour * w;
1018 double const storage_coefficient_by_water_vapor =
1019 phi * (rho_wv * dS_L_dp_cap + (1 - S_L) * drho_wv_dp);
1021 .template block<pressure_size, pressure_size>(pressure_index,
1024 N.transpose() * storage_coefficient_by_water_vapor * N * w;
1026 double const vapor_expansion_factor = phi * (1 - S_L) * drho_wv_dT;
1028 .template block<pressure_size, temperature_size>(
1029 pressure_index, temperature_index)
1030 .noalias() += N.transpose() * vapor_expansion_factor * N * w;
1032 local_rhs.template segment<pressure_size>(pressure_index)
1033 .noalias() -= f_Tv_D_Tv * dNdx.transpose() * (dNdx * T) * w;
1036 .template block<pressure_size, pressure_size>(pressure_index,
1038 .noalias() += dNdx.transpose() * D_pv * dNdx * w;
1045 double const factor = phi * (1 - S_L) / rho_LR;
1049 .template value<double>(variables, x_position, t, dt) *
1052 double const drho_LR_dT =
1054 .template dValue<double>(variables,
1058 double const rho_wv_over_rho_L = rho_wv / rho_LR;
1060 .template block<temperature_size, temperature_size>(
1061 temperature_index, temperature_index)
1064 (drho_wv_dT - rho_wv_over_rho_L * drho_LR_dT) *
1065 N.transpose() * N * w;
1068 .template block<temperature_size, pressure_size>(
1069 temperature_index, pressure_index)
1072 (drho_wv_dp - rho_wv_over_rho_L * drho_LR_dp) +
1073 L0 * phi * rho_wv_over_rho_L * dS_L_dp_cap) *
1074 N.transpose() * N * w;
1078 .template block<temperature_size, temperature_size>(
1079 temperature_index, temperature_index)
1081 L0 * f_Tv_D_Tv * dNdx.transpose() * dNdx * w / rho_LR;
1084 .template block<temperature_size, pressure_size>(
1085 temperature_index, pressure_index)
1087 L0 * D_pv * dNdx.transpose() * dNdx * w / rho_LR;
1092 if (_process_data.apply_mass_lumping)
1094 auto Mpp = local_M.template block<pressure_size, pressure_size>(
1095 pressure_index, pressure_index);
1096 Mpp = Mpp.colwise().sum().eval().asDiagonal();
1100 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
1101 std::vector<double>
const&
1105 std::vector<GlobalVector*>
const& ,
1106 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& ,
1107 std::vector<double>& cache)
const
1109 unsigned const n_integration_points =
1110 _integration_method.getNumberOfPoints();
1114 Eigen::Matrix<double, GlobalDim, Eigen::Dynamic, Eigen::RowMajor>>(
1115 cache, GlobalDim, n_integration_points);
1117 for (
unsigned ip = 0; ip < n_integration_points; ip++)
1119 cache_matrix.col(ip).noalias() = _ip_data[ip].v_darcy;
1125 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
1127 ShapeFunction, IntegrationMethod, GlobalDim>::getSaturation()
const
1129 std::vector<double> result;
1130 getIntPtSaturation(0, {}, {}, result);
1134 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
1135 std::vector<double>
const&
1139 std::vector<GlobalVector*>
const& ,
1140 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& ,
1141 std::vector<double>& cache)
const
1147 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
1149 ShapeFunction, IntegrationMethod, GlobalDim>::getPorosity()
const
1151 std::vector<double> result;
1152 getIntPtPorosity(0, {}, {}, result);
1156 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
1157 std::vector<double>
const&
1161 std::vector<GlobalVector*>
const& ,
1162 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& ,
1163 std::vector<double>& cache)
const
1169 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
1170 std::vector<double>
const&
1174 std::vector<GlobalVector*>
const& ,
1175 std::vector<NumLib::LocalToGlobalIndexMap const*>
const& ,
1176 std::vector<double>& cache)
const
1179 _ip_data, &IpData::dry_density_solid, cache);
1182 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
1185 computeSecondaryVariableConcrete(
double const t,
double const dt,
1186 Eigen::VectorXd
const& local_x,
1187 Eigen::VectorXd
const& local_x_dot)
1190 local_x.template segment<temperature_size>(temperature_index);
1193 local_x_dot.template segment<temperature_size>(temperature_index);
1195 auto const p_L = local_x.template segment<pressure_size>(pressure_index);
1197 auto p_L_dot = local_x_dot.template segment<pressure_size>(pressure_index);
1199 auto const& medium = *_process_data.media_map->getMedium(_element.getID());
1200 auto const& liquid_phase = medium.phase(
"AqueousLiquid");
1201 auto const& solid_phase = medium.phase(
"Solid");
1208 unsigned const n_integration_points =
1209 _integration_method.getNumberOfPoints();
1211 double saturation_avg = 0;
1212 double porosity_avg = 0;
1214 for (
unsigned ip = 0; ip < n_integration_points; ip++)
1217 auto const& N = _ip_data[ip].N;
1227 double p_cap_dot_ip;
1232 variables[
static_cast<int>(MPL::Variable::phase_pressure)] = -p_cap_ip;
1236 auto& S_L = _ip_data[ip].saturation;
1237 auto const S_L_prev = _ip_data[ip].saturation_prev;
1239 variables, x_position, t, dt);
1240 variables[
static_cast<int>(MPL::Variable::liquid_saturation)] = S_L;
1241 variables_prev[
static_cast<int>(MPL::Variable::liquid_saturation)] =
1245 auto chi_S_L_prev = S_L_prev;
1248 auto const chi = [&medium, x_position, t, dt](
double const S_L)
1251 variables[
static_cast<int>(MPL::Variable::liquid_saturation)] =
1254 .template value<double>(variables, x_position, t, dt);
1257 chi_S_L_prev = chi(S_L_prev);
1259 variables[
static_cast<int>(MPL::Variable::effective_pore_pressure)] =
1260 -chi_S_L * p_cap_ip;
1261 variables_prev[
static_cast<int>(
1262 MPL::Variable::effective_pore_pressure)] =
1263 -chi_S_L_prev * (p_cap_ip - p_cap_dot_ip * dt);
1267 variables, x_position, t, dt);
1269 auto& solid_elasticity = *_process_data.simplified_elasticity;
1271 solid_elasticity.bulkCompressibilityFromYoungsModulus(
1272 solid_phase, variables, x_position, t, dt);
1273 auto const beta_SR = (1 -
alpha) * beta_S;
1274 variables[
static_cast<int>(MPL::Variable::grain_compressibility)] =
1277 auto& phi = _ip_data[ip].porosity;
1280 _ip_data[ip].porosity_prev;
1282 variables, variables_prev, x_position, t, dt);
1288 variables, x_position, t, dt);
1291 variables, x_position, t, dt);
1293 auto const K_intrinsic = MPL::formEigenTensor<GlobalDim>(
1297 double const k_rel =
1299 .template value<double>(variables, x_position, t, dt);
1305 variables, x_position, t, dt);
1306 _ip_data[ip].dry_density_solid = (1 - phi) * rho_SR;
1308 auto const& b = _process_data.specific_body_force;
1311 auto const& dNdx = _ip_data[ip].dNdx;
1312 _ip_data[ip].v_darcy.noalias() =
1313 -K_over_mu * dNdx * p_L + rho_LR * K_over_mu * b;
1315 saturation_avg += S_L;
1316 porosity_avg += phi;
1318 saturation_avg /= n_integration_points;
1319 porosity_avg /= n_integration_points;
1321 (*_process_data.element_saturation)[_element.getID()] = saturation_avg;
1322 (*_process_data.element_porosity)[_element.getID()] = porosity_avg;
1325 template <
typename ShapeFunction,
typename IntegrationMethod,
int GlobalDim>
1327 ShapeFunction, IntegrationMethod, GlobalDim>::getNumberOfIntegrationPoints()
1330 return _integration_method.getNumberOfPoints();
Property const & property(PropertyType const &p) const
bool hasProperty(PropertyType const &p) const
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)
ThermoRichardsFlowLocalAssembler(ThermoRichardsFlowLocalAssembler const &)=delete
std::vector< IpData, Eigen::aligned_allocator< IpData > > _ip_data
ThermoRichardsFlowProcessData & _process_data
MeshLib::Element const & _element
std::vector< double > const & getIntPtSaturation(const double t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_table, std::vector< double > &cache) const override
IntegrationMethod _integration_method
typename ShapeMatricesType::GlobalDimVectorType GlobalDimVectorType
std::vector< double > const & getIntPtDarcyVelocity(const double t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_table, std::vector< double > &cache) const override
std::vector< double > const & getIntPtPorosity(const double t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_table, std::vector< double > &cache) const override
std::vector< double > const & getIntPtDryDensitySolid(const double t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_table, std::vector< double > &cache) const override
typename ShapeMatricesType::GlobalDimMatrixType GlobalDimMatrixType
double getLiquidThermalExpansivity(Phase const &phase, VariableArray const &vars, const double density, ParameterLib::SpatialPosition const &pos, double const t, double const dt)
template Eigen::Matrix< double, 3, 3 > formEigenTensor< 3 >(MaterialPropertyLib::PropertyDataType const &values)
std::array< VariableType, static_cast< int >(Variable::number_of_variables)> VariableArray
@ thermal_diffusion_enhancement_factor
Thermal diffusion enhancement factor for water vapor flow.
@ bishops_effective_stress
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)
void shapeFunctionInterpolate(const NodalValues &nodal_values, const ShapeMatrix &shape_matrix_N, double &interpolated_value, ScalarTypes &... interpolated_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::unique_ptr< MaterialPropertyLib::MaterialSpatialDistributionMap > media_map