156 std::vector<double>
const& local_x,
157 std::vector<double>
const& local_x_prev,
158 std::vector<double>& local_rhs_data,
159 std::vector<double>& local_Jac_data)
161 auto const local_matrix_dim = pressure_size + temperature_size;
162 assert(local_x.size() == local_matrix_dim);
164 auto const T = Eigen::Map<
typename ShapeMatricesType::template VectorType<
165 temperature_size>
const>(local_x.data() + temperature_index,
167 auto const p_L = Eigen::Map<
168 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
169 local_x.data() + pressure_index, pressure_size);
172 Eigen::Map<
typename ShapeMatricesType::template VectorType<
173 temperature_size>
const>(local_x_prev.data() + temperature_index,
175 auto const p_L_prev = Eigen::Map<
176 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
177 local_x_prev.data() + pressure_index, pressure_size);
180 typename ShapeMatricesType::template MatrixType<local_matrix_dim,
182 local_Jac_data, local_matrix_dim, local_matrix_dim);
185 typename ShapeMatricesType::template VectorType<local_matrix_dim>>(
186 local_rhs_data, local_matrix_dim);
189 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
192 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
195 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
198 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
201 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
204 ShapeMatricesType::NodalMatrixType::Zero(pressure_size,
207 ShapeMatricesType::NodalMatrixType::Zero(pressure_size, pressure_size);
209 ShapeMatricesType::NodalMatrixType::Zero(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;
228 unsigned const n_integration_points =
229 _integration_method.getNumberOfPoints();
230 for (
unsigned ip = 0; ip < n_integration_points; ip++)
232 auto const& w = _ip_data[ip].integration_weight;
234 auto const& N = _ip_data[ip].N;
235 auto const& dNdx = _ip_data[ip].dNdx;
238 std::nullopt, _element.getID(), ip,
249 double p_cap_prev_ip;
259 auto& S_L = _ip_data[ip].saturation;
260 auto const S_L_prev = _ip_data[ip].saturation_prev;
262 medium[MPL::PropertyType::biot_coefficient].template value<double>(
263 variables, x_position, t, dt);
265 auto& solid_elasticity = *_process_data.simplified_elasticity;
269 solid_elasticity.bulkCompressibilityFromYoungsModulus(
270 solid_phase, variables, x_position, t, dt);
271 auto const beta_SR = (1 - alpha) * beta_S;
275 liquid_phase[MPL::PropertyType::density].template value<double>(
276 variables, x_position, t, dt);
278 auto const& b = _process_data.specific_body_force;
280 double const drho_LR_dp =
281 liquid_phase[MPL::PropertyType::density].template dValue<double>(
282 variables, MPL::Variable::liquid_phase_pressure, x_position, t,
284 auto const beta_LR = drho_LR_dp / rho_LR;
286 S_L = medium[MPL::PropertyType::saturation].template value<double>(
287 variables, x_position, t, dt);
292 double const dS_L_dp_cap =
293 medium[MPL::PropertyType::saturation].template dValue<double>(
294 variables, MPL::Variable::capillary_pressure, x_position, t,
298 double const DeltaS_L_Deltap_cap =
299 (p_cap_ip == p_cap_prev_ip)
301 : (S_L - S_L_prev) / (p_cap_ip - p_cap_prev_ip);
304 auto chi_S_L_prev = S_L_prev;
305 auto dchi_dS_L = 1.0;
306 if (medium.hasProperty(MPL::PropertyType::bishops_effective_stress))
308 auto const chi = [&medium, x_position, t, dt](
double const S_L)
312 return medium[MPL::PropertyType::bishops_effective_stress]
313 .template value<double>(variables, x_position, t, dt);
316 chi_S_L_prev = chi(S_L_prev);
318 dchi_dS_L = medium[MPL::PropertyType::bishops_effective_stress]
319 .template dValue<double>(
320 variables, MPL::Variable::liquid_saturation,
331 auto& phi = _ip_data[ip].porosity;
334 variables_prev.
porosity = _ip_data[ip].porosity_prev;
335 phi = medium[MPL::PropertyType::porosity].template value<double>(
336 variables, variables_prev, x_position, t, dt);
343 "ThermoRichardsFlow: Biot-coefficient {} is smaller than "
344 "porosity {} in element/integration point {}/{}.",
345 alpha, phi, _element.getID(), ip);
349 medium[MPL::PropertyType::relative_permeability]
350 .template value<double>(variables, x_position, t, dt);
352 liquid_phase[MPL::PropertyType::viscosity].template value<double>(
353 variables, x_position, t, dt);
356 medium[MPL::PropertyType::permeability].value(variables, x_position,
362 auto const K_pT_thermal_osmosis =
363 (solid_phase.hasProperty(
367 [MPL::PropertyType::thermal_osmosis_coefficient]
368 .value(variables, x_position, t, dt))
369 : Eigen::MatrixXd::Zero(GlobalDim, GlobalDim));
374 Eigen::Matrix<double, 3, 3>
const
375 solid_linear_thermal_expansion_coefficient =
379 .value(variables, x_position, t, dt));
382 solid_phase[MPL::PropertyType::density].template value<double>(
383 variables, x_position, t, dt);
388 laplace_p.noalias() +=
389 dNdx.transpose() * k_rel * rho_Ki_over_mu * dNdx * w;
390 laplace_T.noalias() +=
391 dNdx.transpose() * rho_LR * K_pT_thermal_osmosis * dNdx * w;
392 const double alphaB_minus_phi = alpha - phi;
393 double const a0 = alphaB_minus_phi * beta_SR;
394 double const specific_storage_a_p =
395 S_L * (phi * beta_LR + S_L * a0 +
396 chi_S_L * alpha * alpha *
397 solid_elasticity.storageContribution(
398 solid_phase, variables, x_position, t, dt));
399 double const specific_storage_a_S = phi - p_cap_ip * S_L * a0;
401 double const dspecific_storage_a_p_dp_cap =
402 dS_L_dp_cap * (phi * beta_LR + 2 * S_L * a0 +
404 solid_elasticity.storageContribution(
405 solid_phase, variables, x_position, t, dt) *
406 (chi_S_L + dchi_dS_L * S_L));
407 double const dspecific_storage_a_S_dp_cap =
408 -a0 * (S_L + p_cap_ip * dS_L_dp_cap);
410 storage_p_a_p.noalias() +=
411 N.transpose() * rho_LR * specific_storage_a_p * N * w;
413 storage_p_a_S.noalias() -= N.transpose() * rho_LR *
414 specific_storage_a_S * DeltaS_L_Deltap_cap *
418 .template block<pressure_size, pressure_size>(pressure_index,
420 .noalias() += N.transpose() * (p_cap_ip - p_cap_prev_ip) / dt *
421 rho_LR * dspecific_storage_a_p_dp_cap * N * w;
423 storage_p_a_S_Jpp.noalias() -=
424 N.transpose() * rho_LR *
425 ((S_L - S_L_prev) * dspecific_storage_a_S_dp_cap +
426 specific_storage_a_S * dS_L_dp_cap) /
429 double const dk_rel_dS_L =
430 medium[MPL::PropertyType::relative_permeability]
431 .template dValue<double>(variables,
432 MPL::Variable::liquid_saturation,
436 .template block<pressure_size, pressure_size>(pressure_index,
438 .noalias() += dNdx.transpose() * rho_Ki_over_mu * grad_p_cap *
439 dk_rel_dS_L * dS_L_dp_cap * N * w;
442 .template block<pressure_size, pressure_size>(pressure_index,
444 .noalias() += dNdx.transpose() * rho_LR * rho_Ki_over_mu * b *
445 dk_rel_dS_L * dS_L_dp_cap * N * w;
447 local_rhs.template segment<pressure_size>(pressure_index).noalias() +=
448 dNdx.transpose() * rho_LR * k_rel * rho_Ki_over_mu * b * w;
453 double const fluid_volumetric_thermal_expansion_coefficient =
456 const double eff_thermal_expansion =
457 S_L * (alphaB_minus_phi *
458 solid_linear_thermal_expansion_coefficient.trace() +
459 phi * fluid_volumetric_thermal_expansion_coefficient +
460 alpha * solid_elasticity.thermalExpansivityContribution(
461 solid_linear_thermal_expansion_coefficient,
462 solid_phase, variables, x_position, t, dt));
464 N.transpose() * rho_LR * eff_thermal_expansion * N * w;
470 auto const specific_heat_capacity_fluid =
472 .template value<double>(variables, x_position, t, dt);
474 auto const specific_heat_capacity_solid =
477 .template value<double>(variables, x_position, t, dt);
481 (rho_SR * specific_heat_capacity_solid * (1 - phi) +
482 (S_L * rho_LR * specific_heat_capacity_fluid) * phi) *
485 auto const thermal_conductivity =
488 thermal_conductivity]
489 .value(variables, x_position, t, dt));
492 -Ki_over_mu * k_rel * (dNdx * p_L - rho_LR * b) -
493 K_pT_thermal_osmosis * dNdx * T);
495 K_TT.noalias() += (dNdx.transpose() * thermal_conductivity * dNdx +
496 N.transpose() * velocity_L.transpose() * dNdx *
497 rho_LR * specific_heat_capacity_fluid) *
504 dNdx.transpose() * T_ip * K_pT_thermal_osmosis * dNdx * w;
505 dK_TT_dp.noalias() -= rho_LR * specific_heat_capacity_fluid *
506 N.transpose() * (dNdx * T).transpose() *
507 k_rel * Ki_over_mu * dNdx * w;
509 dK_TT_dp.noalias() -= rho_LR * specific_heat_capacity_fluid *
510 N.transpose() * velocity_L.dot(dNdx * T) /
511 k_rel * dk_rel_dS_L * dS_L_dp_cap * N * w;
513 if (gas_phase && S_L < 1.0)
517 double const rho_wv =
518 gas_phase->
property(MPL::PropertyType::density)
519 .template value<double>(variables, x_position, t, dt);
521 double const drho_wv_dT =
522 gas_phase->
property(MPL::PropertyType::density)
523 .template dValue<double>(variables,
524 MPL::Variable::temperature,
526 double const drho_wv_dp =
527 gas_phase->
property(MPL::PropertyType::density)
528 .template dValue<double>(
529 variables, MPL::Variable::liquid_phase_pressure,
534 MPL::PropertyType::thermal_diffusion_enhancement_factor)
535 .template value<double>(variables, x_position, t, dt);
538 auto const tortuosity =
539 medium.property(MPL::PropertyType::tortuosity)
540 .template value<double>(variables, x_position, t, dt);
542 phi * (1.0 - S_L) * tortuosity *
543 gas_phase->
property(MPL::PropertyType::diffusion)
544 .template value<double>(variables, x_position, t, dt);
546 double const f_Tv_D_Tv = f_Tv * D_v * drho_wv_dT;
547 double const D_pv = D_v * drho_wv_dp;
551 -(f_Tv_D_Tv * grad_T - D_pv * grad_p_cap);
552 double const specific_heat_capacity_vapour =
554 .template value<double>(variables, x_position, t, dt);
557 w * (rho_wv * specific_heat_capacity_vapour * (1 - S_L) * phi) *
560 K_TT.noalias() += N.transpose() * vapour_flux.transpose() * dNdx *
561 specific_heat_capacity_vapour * w;
563 double const storage_coefficient_by_water_vapor =
564 phi * (rho_wv * dS_L_dp_cap + (1 - S_L) * drho_wv_dp);
566 storage_p_a_p.noalias() +=
567 N.transpose() * storage_coefficient_by_water_vapor * N * w;
569 double const vapor_expansion_factor = phi * (1 - S_L) * drho_wv_dT;
570 M_pT.noalias() += N.transpose() * vapor_expansion_factor * N * w;
573 .template block<pressure_size, temperature_size>(
574 pressure_index, temperature_index)
575 .noalias() += dNdx.transpose() * f_Tv_D_Tv * dNdx * w;
577 local_rhs.template segment<pressure_size>(pressure_index)
578 .noalias() -= f_Tv_D_Tv * dNdx.transpose() * (dNdx * T) * w;
580 laplace_p.noalias() += dNdx.transpose() * D_pv * dNdx * w;
585 if (gas_phase->
hasProperty(MPL::PropertyType::specific_latent_heat))
587 double const factor = phi * (1 - S_L) / rho_LR;
590 gas_phase->
property(MPL::PropertyType::specific_latent_heat)
591 .template value<double>(variables, x_position, t, dt) *
594 double const drho_LR_dT =
595 liquid_phase.property(MPL::PropertyType::density)
596 .template dValue<double>(variables,
597 MPL::Variable::temperature,
600 double const rho_wv_over_rho_L = rho_wv / rho_LR;
603 (drho_wv_dT - rho_wv_over_rho_L * drho_LR_dT) *
604 N.transpose() * N * w;
608 (drho_wv_dp - rho_wv_over_rho_L * drho_LR_dp) +
609 L0 * phi * rho_wv_over_rho_L * dS_L_dp_cap) *
610 N.transpose() * N * w;
614 L0 * f_Tv_D_Tv * dNdx.transpose() * dNdx * w / rho_LR;
617 L0 * D_pv * dNdx.transpose() * dNdx * w / rho_LR;
622 if (_process_data.apply_mass_lumping)
624 storage_p_a_p = storage_p_a_p.colwise().sum().eval().asDiagonal();
625 storage_p_a_S = storage_p_a_S.colwise().sum().eval().asDiagonal();
627 storage_p_a_S_Jpp.colwise().sum().eval().asDiagonal();
635 .template block<temperature_size, temperature_size>(temperature_index,
637 .noalias() += M_TT / dt + K_TT;
640 .template block<temperature_size, pressure_size>(temperature_index,
642 .noalias() += K_Tp + dK_TT_dp;
646 .template block<pressure_size, pressure_size>(pressure_index,
648 .noalias() += laplace_p + storage_p_a_p / dt + storage_p_a_S_Jpp;
652 .template block<pressure_size, temperature_size>(pressure_index,
654 .noalias() += M_pT / dt + laplace_T;
660 local_rhs.template segment<temperature_size>(temperature_index).noalias() -=
661 M_TT * (T - T_prev) / dt + K_TT * T;
662 local_rhs.template segment<temperature_size>(temperature_index).noalias() -=
666 local_rhs.template segment<pressure_size>(pressure_index).noalias() -=
667 laplace_p * p_L + laplace_T * T +
668 (storage_p_a_p + storage_p_a_S) * (p_L - p_L_prev) / dt +
669 M_pT * (T - T_prev) / dt;
672 if (gas_phase->
hasProperty(MPL::PropertyType::specific_latent_heat))
676 .template block<temperature_size, pressure_size>(
677 temperature_index, pressure_index)
678 .noalias() += M_Tp / dt;
680 local_rhs.template segment<temperature_size>(temperature_index)
681 .noalias() -= M_Tp * (p_L - p_L_prev) / dt;
688 double const t,
double const dt, std::vector<double>
const& local_x,
689 std::vector<double>
const& local_x_prev, std::vector<double>& local_M_data,
690 std::vector<double>& local_K_data, std::vector<double>& local_rhs_data)
692 auto const local_matrix_dim = pressure_size + temperature_size;
693 assert(local_x.size() == local_matrix_dim);
695 auto const T = Eigen::Map<
typename ShapeMatricesType::template VectorType<
696 temperature_size>
const>(local_x.data() + temperature_index,
698 auto const p_L = Eigen::Map<
699 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
700 local_x.data() + pressure_index, pressure_size);
702 auto const p_L_prev = Eigen::Map<
703 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
704 local_x_prev.data() + pressure_index, pressure_size);
707 typename ShapeMatricesType::template MatrixType<local_matrix_dim,
709 local_K_data, local_matrix_dim, local_matrix_dim);
712 typename ShapeMatricesType::template MatrixType<local_matrix_dim,
714 local_M_data, local_matrix_dim, local_matrix_dim);
717 typename ShapeMatricesType::template VectorType<local_matrix_dim>>(
718 local_rhs_data, local_matrix_dim);
720 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
721 auto const& liquid_phase = medium.phase(
"AqueousLiquid");
722 auto const& solid_phase = medium.phase(
"Solid");
724 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++)
732 auto const& w = _ip_data[ip].integration_weight;
734 auto const& N = _ip_data[ip].N;
735 auto const& dNdx = _ip_data[ip].dNdx;
738 std::nullopt, _element.getID(), ip,
749 double p_cap_prev_ip;
759 auto& S_L = _ip_data[ip].saturation;
760 auto const S_L_prev = _ip_data[ip].saturation_prev;
762 medium[MPL::PropertyType::biot_coefficient].template value<double>(
763 variables, x_position, t, dt);
765 auto& solid_elasticity = *_process_data.simplified_elasticity;
769 solid_elasticity.bulkCompressibilityFromYoungsModulus(
770 solid_phase, variables, x_position, t, dt);
771 auto const beta_SR = (1 - alpha) * beta_S;
775 liquid_phase[MPL::PropertyType::density].template value<double>(
776 variables, x_position, t, dt);
777 auto const& b = _process_data.specific_body_force;
779 double const drho_LR_dp =
780 liquid_phase[MPL::PropertyType::density].template dValue<double>(
781 variables, MPL::Variable::liquid_phase_pressure, x_position, t,
783 auto const beta_LR = drho_LR_dp / rho_LR;
785 S_L = medium[MPL::PropertyType::saturation].template value<double>(
786 variables, x_position, t, dt);
791 double const dS_L_dp_cap =
792 medium[MPL::PropertyType::saturation].template dValue<double>(
793 variables, MPL::Variable::capillary_pressure, x_position, t,
797 double const DeltaS_L_Deltap_cap =
798 (p_cap_ip == p_cap_prev_ip)
800 : (S_L - S_L_prev) / (p_cap_ip - p_cap_prev_ip);
803 auto chi_S_L_prev = S_L_prev;
804 if (medium.hasProperty(MPL::PropertyType::bishops_effective_stress))
806 auto const chi = [&medium, x_position, t, dt](
double const S_L)
810 return medium[MPL::PropertyType::bishops_effective_stress]
811 .template value<double>(variables, x_position, t, dt);
814 chi_S_L_prev = chi(S_L_prev);
824 auto& phi = _ip_data[ip].porosity;
827 variables_prev.
porosity = _ip_data[ip].porosity_prev;
828 phi = medium[MPL::PropertyType::porosity].template value<double>(
829 variables, variables_prev, x_position, t, dt);
836 "ThermoRichardsFlow: Biot-coefficient {} is smaller than "
837 "porosity {} in element/integration point {}/{}.",
838 alpha, phi, _element.getID(), ip);
841 auto const K_pT_thermal_osmosis =
842 (solid_phase.hasProperty(
846 [MPL::PropertyType::thermal_osmosis_coefficient]
847 .value(variables, x_position, t, dt))
848 : Eigen::MatrixXd::Zero(GlobalDim, GlobalDim));
851 medium[MPL::PropertyType::relative_permeability]
852 .template value<double>(variables, x_position, t, dt);
854 liquid_phase[MPL::PropertyType::viscosity].template value<double>(
855 variables, x_position, t, dt);
858 medium[MPL::PropertyType::permeability].value(variables, x_position,
867 Eigen::Matrix<double, 3, 3>
const
868 solid_linear_thermal_expansion_coefficient =
872 .value(variables, x_position, t, dt));
875 solid_phase[MPL::PropertyType::density].template value<double>(
876 variables, x_position, t, dt);
882 .template block<pressure_size, pressure_size>(pressure_index,
884 .noalias() += dNdx.transpose() * k_rel * rho_Ki_over_mu * dNdx * w;
886 const double alphaB_minus_phi = alpha - phi;
887 double const a0 = alphaB_minus_phi * beta_SR;
888 double const specific_storage_a_p =
889 S_L * (phi * beta_LR + S_L * a0 +
890 chi_S_L * alpha * alpha *
891 solid_elasticity.storageContribution(
892 solid_phase, variables, x_position, t, dt));
893 double const specific_storage_a_S = phi - p_cap_ip * S_L * a0;
896 .template block<pressure_size, pressure_size>(pressure_index,
898 .noalias() += N.transpose() * rho_LR *
899 (specific_storage_a_p -
900 specific_storage_a_S * DeltaS_L_Deltap_cap) *
903 local_rhs.template segment<pressure_size>(pressure_index).noalias() +=
904 dNdx.transpose() * rho_LR * k_rel * rho_Ki_over_mu * b * w;
909 double const fluid_volumetric_thermal_expansion_coefficient =
912 const double eff_thermal_expansion =
913 S_L * (alphaB_minus_phi *
914 solid_linear_thermal_expansion_coefficient.trace() +
915 phi * fluid_volumetric_thermal_expansion_coefficient +
916 alpha * solid_elasticity.thermalExpansivityContribution(
917 solid_linear_thermal_expansion_coefficient,
918 solid_phase, variables, x_position, t, dt));
921 .template block<pressure_size, temperature_size>(pressure_index,
924 dNdx.transpose() * rho_LR * K_pT_thermal_osmosis * dNdx * w;
927 .template block<pressure_size, temperature_size>(pressure_index,
930 N.transpose() * rho_LR * eff_thermal_expansion * N * w;
936 auto const specific_heat_capacity_fluid =
938 .template value<double>(variables, x_position, t, dt);
940 auto const specific_heat_capacity_solid =
943 .template value<double>(variables, x_position, t, dt);
946 .template block<temperature_size, temperature_size>(
947 temperature_index, temperature_index)
950 (rho_SR * specific_heat_capacity_solid * (1 - phi) +
951 (S_L * rho_LR * specific_heat_capacity_fluid) * phi) *
954 auto const thermal_conductivity =
957 thermal_conductivity]
958 .value(variables, x_position, t, dt));
961 -Ki_over_mu * k_rel * (dNdx * p_L - rho_LR * b) -
962 K_pT_thermal_osmosis * dNdx * T);
965 .template block<temperature_size, temperature_size>(
966 temperature_index, temperature_index)
967 .noalias() += (dNdx.transpose() * thermal_conductivity * dNdx +
968 N.transpose() * velocity_L.transpose() * dNdx *
969 rho_LR * specific_heat_capacity_fluid) *
972 .template block<temperature_size, pressure_size>(
973 temperature_index, pressure_index)
975 dNdx.transpose() * T_ip * K_pT_thermal_osmosis * dNdx * w;
977 if (gas_phase && S_L < 1.0)
981 double const rho_wv =
983 .template value<double>(variables, x_position, t, dt);
985 double const drho_wv_dT =
987 .template dValue<double>(variables,
988 MPL::Variable::temperature,
990 double const drho_wv_dp =
992 .template dValue<double>(
993 variables, MPL::Variable::liquid_phase_pressure,
998 MPL::PropertyType::thermal_diffusion_enhancement_factor)
999 .template value<double>(variables, x_position, t, dt);
1002 auto const tortuosity =
1003 medium.property(MPL::PropertyType::tortuosity)
1004 .template value<double>(variables, x_position, t, dt);
1006 phi * (1.0 - S_L) * tortuosity *
1007 gas_phase->
property(MPL::PropertyType::diffusion)
1008 .template value<double>(variables, x_position, t, dt);
1010 double const f_Tv_D_Tv = f_Tv * D_v * drho_wv_dT;
1011 double const D_pv = D_v * drho_wv_dp;
1016 -(f_Tv_D_Tv * grad_T - D_pv * grad_p_cap);
1017 double const specific_heat_capacity_vapour =
1019 .template value<double>(variables, x_position, t, dt);
1022 .template block<temperature_size, temperature_size>(
1023 temperature_index, temperature_index)
1025 w * (rho_wv * specific_heat_capacity_vapour * (1 - S_L) * phi) *
1029 .template block<temperature_size, temperature_size>(
1030 temperature_index, temperature_index)
1031 .noalias() += N.transpose() * vapour_flux.transpose() * dNdx *
1032 specific_heat_capacity_vapour * w;
1034 double const storage_coefficient_by_water_vapor =
1035 phi * (rho_wv * dS_L_dp_cap + (1 - S_L) * drho_wv_dp);
1037 .template block<pressure_size, pressure_size>(pressure_index,
1040 N.transpose() * storage_coefficient_by_water_vapor * N * w;
1042 double const vapor_expansion_factor = phi * (1 - S_L) * drho_wv_dT;
1044 .template block<pressure_size, temperature_size>(
1045 pressure_index, temperature_index)
1046 .noalias() += N.transpose() * vapor_expansion_factor * N * w;
1048 local_rhs.template segment<pressure_size>(pressure_index)
1049 .noalias() -= f_Tv_D_Tv * dNdx.transpose() * (dNdx * T) * w;
1052 .template block<pressure_size, pressure_size>(pressure_index,
1054 .noalias() += dNdx.transpose() * D_pv * dNdx * w;
1059 if (gas_phase->
hasProperty(MPL::PropertyType::specific_latent_heat))
1061 double const factor = phi * (1 - S_L) / rho_LR;
1064 gas_phase->
property(MPL::PropertyType::specific_latent_heat)
1065 .template value<double>(variables, x_position, t, dt) *
1068 double const drho_LR_dT =
1069 liquid_phase.property(MPL::PropertyType::density)
1070 .template dValue<double>(variables,
1071 MPL::Variable::temperature,
1074 double const rho_wv_over_rho_L = rho_wv / rho_LR;
1076 .template block<temperature_size, temperature_size>(
1077 temperature_index, temperature_index)
1080 (drho_wv_dT - rho_wv_over_rho_L * drho_LR_dT) *
1081 N.transpose() * N * w;
1084 .template block<temperature_size, pressure_size>(
1085 temperature_index, pressure_index)
1088 (drho_wv_dp - rho_wv_over_rho_L * drho_LR_dp) +
1089 L0 * phi * rho_wv_over_rho_L * dS_L_dp_cap) *
1090 N.transpose() * N * w;
1094 .template block<temperature_size, temperature_size>(
1095 temperature_index, temperature_index)
1097 L0 * f_Tv_D_Tv * dNdx.transpose() * dNdx * w / rho_LR;
1100 .template block<temperature_size, pressure_size>(
1101 temperature_index, pressure_index)
1103 L0 * D_pv * dNdx.transpose() * dNdx * w / rho_LR;
1108 if (_process_data.apply_mass_lumping)
1110 auto Mpp = local_M.template block<pressure_size, pressure_size>(
1111 pressure_index, pressure_index);
1112 Mpp = Mpp.colwise().sum().eval().asDiagonal();
1199 Eigen::VectorXd
const& local_x,
1200 Eigen::VectorXd
const& local_x_prev)
1203 local_x.template segment<temperature_size>(temperature_index);
1205 auto const p_L = local_x.template segment<pressure_size>(pressure_index);
1208 local_x_prev.template segment<pressure_size>(pressure_index);
1210 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
1211 auto const& liquid_phase = medium.phase(
"AqueousLiquid");
1212 auto const& solid_phase = medium.phase(
"Solid");
1216 unsigned const n_integration_points =
1217 _integration_method.getNumberOfPoints();
1219 double saturation_avg = 0;
1220 double porosity_avg = 0;
1222 for (
unsigned ip = 0; ip < n_integration_points; ip++)
1224 auto const& N = _ip_data[ip].N;
1227 std::nullopt, _element.getID(), ip,
1238 double p_cap_prev_ip;
1249 auto& S_L = _ip_data[ip].saturation;
1250 auto const S_L_prev = _ip_data[ip].saturation_prev;
1251 S_L = medium[MPL::PropertyType::saturation].template value<double>(
1252 variables, x_position, t, dt);
1257 auto chi_S_L_prev = S_L_prev;
1258 if (medium.hasProperty(MPL::PropertyType::bishops_effective_stress))
1260 auto const chi = [&medium, x_position, t, dt](
double const S_L)
1264 return medium[MPL::PropertyType::bishops_effective_stress]
1265 .template value<double>(variables, x_position, t, dt);
1268 chi_S_L_prev = chi(S_L_prev);
1274 medium[MPL::PropertyType::biot_coefficient].template value<double>(
1275 variables, x_position, t, dt);
1277 auto& solid_elasticity = *_process_data.simplified_elasticity;
1279 solid_elasticity.bulkCompressibilityFromYoungsModulus(
1280 solid_phase, variables, x_position, t, dt);
1281 auto const beta_SR = (1 - alpha) * beta_S;
1284 auto& phi = _ip_data[ip].porosity;
1286 variables_prev.
porosity = _ip_data[ip].porosity_prev;
1287 phi = medium[MPL::PropertyType::porosity].template value<double>(
1288 variables, variables_prev, x_position, t, dt);
1293 liquid_phase[MPL::PropertyType::viscosity].template value<double>(
1294 variables, x_position, t, dt);
1296 liquid_phase[MPL::PropertyType::density].template value<double>(
1297 variables, x_position, t, dt);
1300 medium[MPL::PropertyType::permeability].value(variables, x_position,
1303 double const k_rel =
1304 medium[MPL::PropertyType::relative_permeability]
1305 .template value<double>(variables, x_position, t, dt);
1310 solid_phase[MPL::PropertyType::density].template value<double>(
1311 variables, x_position, t, dt);
1312 _ip_data[ip].dry_density_solid = (1 - phi) * rho_SR;
1314 auto const& b = _process_data.specific_body_force;
1316 auto const K_pT_thermal_osmosis =
1317 (solid_phase.hasProperty(
1321 [MPL::PropertyType::thermal_osmosis_coefficient]
1322 .value(variables, x_position, t, dt))
1323 : Eigen::MatrixXd::Zero(GlobalDim, GlobalDim));
1326 auto const& dNdx = _ip_data[ip].dNdx;
1327 _ip_data[ip].v_darcy.noalias() = -K_over_mu * dNdx * p_L -
1328 K_pT_thermal_osmosis * dNdx * T +
1329 rho_LR * K_over_mu * b;
1331 saturation_avg += S_L;
1332 porosity_avg += phi;
1334 saturation_avg /= n_integration_points;
1335 porosity_avg /= n_integration_points;
1337 (*_process_data.element_saturation)[_element.getID()] = saturation_avg;
1338 (*_process_data.element_porosity)[_element.getID()] = porosity_avg;