152 std::vector<double>
const& local_x,
153 std::vector<double>
const& local_x_prev,
154 std::vector<double>& local_rhs_data,
155 std::vector<double>& local_Jac_data)
158 assert(local_x.size() == local_matrix_dim);
160 auto const T = Eigen::Map<
typename ShapeMatricesType::template VectorType<
163 auto const p_L = Eigen::Map<
164 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
168 Eigen::Map<
typename ShapeMatricesType::template VectorType<
171 auto const p_L_prev = Eigen::Map<
172 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
176 typename ShapeMatricesType::template MatrixType<local_matrix_dim,
178 local_Jac_data, local_matrix_dim, local_matrix_dim);
181 typename ShapeMatricesType::template VectorType<local_matrix_dim>>(
182 local_rhs_data, local_matrix_dim);
217 auto const& liquid_phase =
219 auto const& solid_phase =
226 unsigned const n_integration_points =
228 for (
unsigned ip = 0; ip < n_integration_points; ip++)
230 auto const& w =
_ip_data[ip].integration_weight;
233 auto const& dNdx =
_ip_data[ip].dNdx;
247 double p_cap_prev_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;
274 variables, x_position, t, dt);
278 double const drho_LR_dp =
282 auto const beta_LR = drho_LR_dp / rho_LR;
285 variables, x_position, t, dt);
290 double const dS_L_dp_cap =
296 double const DeltaS_L_Deltap_cap =
297 (p_cap_ip == p_cap_prev_ip)
299 : (S_L - S_L_prev) / (p_cap_ip - p_cap_prev_ip);
302 auto chi_S_L_prev = S_L_prev;
303 auto dchi_dS_L = 1.0;
306 auto const chi = [&medium, x_position, t, dt](
double const S_L)
311 .template value<double>(variables, x_position, t, dt);
314 chi_S_L_prev = chi(S_L_prev);
317 .template dValue<double>(
334 variables, variables_prev, x_position, t, dt);
341 "ThermoRichardsFlow: Biot-coefficient {} is smaller than "
342 "porosity {} in element/integration point {}/{}.",
348 .template value<double>(variables, x_position, t, dt);
351 variables, x_position, t, dt);
362 medium, variables, x_position, t, dt, K_intrinsic, mu);
367 Eigen::Matrix<double, 3, 3>
const
368 solid_linear_thermal_expansion_coefficient =
372 .value(variables, x_position, t, dt));
376 variables, x_position, t, dt);
381 laplace_p.noalias() +=
382 dNdx.transpose() * k_rel * rho_Ki_over_mu * dNdx * w;
383 laplace_T.noalias() +=
384 dNdx.transpose() * rho_LR * K_pT_thermal_osmosis * 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 +
389 chi_S_L * alpha * alpha *
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 *
413 .noalias() += N.transpose() * (p_cap_ip - p_cap_prev_ip) / dt *
414 rho_LR * 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,
431 .noalias() += dNdx.transpose() * rho_Ki_over_mu * grad_p_cap *
432 dk_rel_dS_L * dS_L_dp_cap * N * w;
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) *
478 auto const thermal_conductivity =
481 thermal_conductivity]
482 .value(variables, x_position, t, dt));
485 -Ki_over_mu * k_rel * (dNdx * p_L - rho_LR * b) -
486 K_pT_thermal_osmosis * dNdx * T);
488 K_TT.noalias() += (dNdx.transpose() * thermal_conductivity * dNdx +
489 N.transpose() * velocity_L.transpose() * dNdx *
490 rho_LR * specific_heat_capacity_fluid) *
497 dNdx.transpose() * T_ip * K_pT_thermal_osmosis * dNdx * w;
498 dK_TT_dp.noalias() -= rho_LR * specific_heat_capacity_fluid *
499 N.transpose() * (dNdx * T).transpose() *
500 k_rel * Ki_over_mu * dNdx * w;
502 dK_TT_dp.noalias() -= rho_LR * specific_heat_capacity_fluid *
503 N.transpose() * velocity_L.dot(dNdx * T) /
504 k_rel * dk_rel_dS_L * dS_L_dp_cap * N * w;
506 if (gas_phase && S_L < 1.0)
510 double const rho_wv =
512 .template value<double>(variables, x_position, t, dt);
514 double const drho_wv_dT =
516 .template dValue<double>(variables,
519 double const drho_wv_dp =
521 .template dValue<double>(
528 .template value<double>(variables, x_position, t, dt);
531 auto const tortuosity =
533 .template value<double>(variables, x_position, t, dt);
535 phi * (1.0 - S_L) * tortuosity *
537 .template value<double>(variables, x_position, t, dt);
539 double const f_Tv_D_Tv = f_Tv * D_v * drho_wv_dT;
540 double const D_pv = D_v * drho_wv_dp;
544 -(f_Tv_D_Tv * grad_T - D_pv * grad_p_cap);
545 double const specific_heat_capacity_vapour =
547 .template value<double>(variables, x_position, t, dt);
550 w * (rho_wv * specific_heat_capacity_vapour * (1 - S_L) * phi) *
553 K_TT.noalias() += N.transpose() * vapour_flux.transpose() * dNdx *
554 specific_heat_capacity_vapour * w;
556 double const storage_coefficient_by_water_vapor =
557 phi * (rho_wv * dS_L_dp_cap + (1 - S_L) * drho_wv_dp);
559 storage_p_a_p.noalias() +=
560 N.transpose() * storage_coefficient_by_water_vapor * N * w;
562 double const vapor_expansion_factor = phi * (1 - S_L) * drho_wv_dT;
563 M_pT.noalias() += N.transpose() * vapor_expansion_factor * N * w;
566 .template block<pressure_size, temperature_size>(
568 .noalias() += dNdx.transpose() * f_Tv_D_Tv * dNdx * w;
571 .noalias() -= f_Tv_D_Tv * dNdx.transpose() * (dNdx * T) * w;
573 laplace_p.noalias() += dNdx.transpose() * D_pv * dNdx * w;
580 double const factor = phi * (1 - S_L) / rho_LR;
584 .template value<double>(variables, x_position, t, dt) *
587 double const drho_LR_dT =
589 .template dValue<double>(variables,
593 double const rho_wv_over_rho_L = rho_wv / rho_LR;
596 (drho_wv_dT - rho_wv_over_rho_L * drho_LR_dT) *
597 N.transpose() * N * w;
601 (drho_wv_dp - rho_wv_over_rho_L * drho_LR_dp) +
602 L0 * phi * rho_wv_over_rho_L * dS_L_dp_cap) *
603 N.transpose() * N * w;
607 L0 * f_Tv_D_Tv * dNdx.transpose() * dNdx * w / rho_LR;
610 L0 * D_pv * dNdx.transpose() * dNdx * w / rho_LR;
617 storage_p_a_p = storage_p_a_p.colwise().sum().eval().asDiagonal();
618 storage_p_a_S = storage_p_a_S.colwise().sum().eval().asDiagonal();
620 storage_p_a_S_Jpp.colwise().sum().eval().asDiagonal();
630 .noalias() += M_TT / dt + K_TT;
635 .noalias() += K_Tp + dK_TT_dp;
641 .noalias() += laplace_p + storage_p_a_p / dt + storage_p_a_S_Jpp;
647 .noalias() += M_pT / dt + laplace_T;
654 M_TT * (T - T_prev) / dt + K_TT * T;
659 local_rhs.template segment<pressure_size>(
pressure_index).noalias() -=
660 laplace_p * p_L + laplace_T * T +
661 (storage_p_a_p + storage_p_a_S) * (p_L - p_L_prev) / dt +
662 M_pT * (T - T_prev) / dt;
669 .template block<temperature_size, pressure_size>(
671 .noalias() += M_Tp / dt;
674 .noalias() -= M_Tp * (p_L - p_L_prev) / dt;
681 double const t,
double const dt, std::vector<double>
const& local_x,
682 std::vector<double>
const& local_x_prev, std::vector<double>& local_M_data,
683 std::vector<double>& local_K_data, std::vector<double>& local_rhs_data)
686 assert(local_x.size() == local_matrix_dim);
688 auto const T = Eigen::Map<
typename ShapeMatricesType::template VectorType<
691 auto const p_L = Eigen::Map<
692 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
695 auto const p_L_prev = Eigen::Map<
696 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
700 typename ShapeMatricesType::template MatrixType<local_matrix_dim,
702 local_K_data, local_matrix_dim, local_matrix_dim);
705 typename ShapeMatricesType::template MatrixType<local_matrix_dim,
707 local_M_data, local_matrix_dim, local_matrix_dim);
710 typename ShapeMatricesType::template VectorType<local_matrix_dim>>(
711 local_rhs_data, local_matrix_dim);
714 auto const& liquid_phase =
716 auto const& solid_phase =
723 unsigned const n_integration_points =
725 for (
unsigned ip = 0; ip < n_integration_points; ip++)
727 auto const& w =
_ip_data[ip].integration_weight;
730 auto const& dNdx =
_ip_data[ip].dNdx;
744 double p_cap_prev_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;
771 variables, x_position, t, dt);
774 double const drho_LR_dp =
778 auto const beta_LR = drho_LR_dp / rho_LR;
781 variables, x_position, t, dt);
786 double const dS_L_dp_cap =
792 double const DeltaS_L_Deltap_cap =
793 (p_cap_ip == p_cap_prev_ip)
795 : (S_L - S_L_prev) / (p_cap_ip - p_cap_prev_ip);
798 auto chi_S_L_prev = S_L_prev;
801 auto const chi = [&medium, x_position, t, dt](
double const S_L)
806 .template value<double>(variables, x_position, t, dt);
809 chi_S_L_prev = chi(S_L_prev);
824 variables, variables_prev, x_position, t, dt);
831 "ThermoRichardsFlow: Biot-coefficient {} is smaller than "
832 "porosity {} in element/integration point {}/{}.",
838 .template value<double>(variables, x_position, t, dt);
841 variables, x_position, t, dt);
849 medium, variables, x_position, t, dt, K_intrinsic, mu);
857 Eigen::Matrix<double, 3, 3>
const
858 solid_linear_thermal_expansion_coefficient =
862 .value(variables, x_position, t, dt));
866 variables, x_position, t, dt);
874 .noalias() += dNdx.transpose() * k_rel * rho_Ki_over_mu * dNdx * w;
876 const double alphaB_minus_phi = alpha - phi;
877 double const a0 = alphaB_minus_phi * beta_SR;
878 double const specific_storage_a_p =
879 S_L * (phi * beta_LR + S_L * a0 +
880 chi_S_L * alpha * alpha *
881 solid_elasticity.storageContribution(
882 solid_phase, variables, x_position, t, dt));
883 double const specific_storage_a_S = phi - p_cap_ip * S_L * a0;
888 .noalias() += N.transpose() * rho_LR *
889 (specific_storage_a_p -
890 specific_storage_a_S * DeltaS_L_Deltap_cap) *
893 local_rhs.template segment<pressure_size>(
pressure_index).noalias() +=
894 dNdx.transpose() * rho_LR * k_rel * rho_Ki_over_mu * b * w;
899 double const fluid_volumetric_thermal_expansion_coefficient =
902 const double eff_thermal_expansion =
903 S_L * (alphaB_minus_phi *
904 solid_linear_thermal_expansion_coefficient.trace() +
905 phi * fluid_volumetric_thermal_expansion_coefficient +
906 alpha * solid_elasticity.thermalExpansivityContribution(
907 solid_linear_thermal_expansion_coefficient,
908 solid_phase, variables, x_position, t, dt));
914 dNdx.transpose() * rho_LR * K_pT_thermal_osmosis * dNdx * w;
920 N.transpose() * rho_LR * eff_thermal_expansion * N * w;
926 auto const specific_heat_capacity_fluid =
928 .template value<double>(variables, x_position, t, dt);
930 auto const specific_heat_capacity_solid =
933 .template value<double>(variables, x_position, t, dt);
936 .template block<temperature_size, temperature_size>(
940 (rho_SR * specific_heat_capacity_solid * (1 - phi) +
941 (S_L * rho_LR * specific_heat_capacity_fluid) * phi) *
944 auto const thermal_conductivity =
947 thermal_conductivity]
948 .value(variables, x_position, t, dt));
951 -Ki_over_mu * k_rel * (dNdx * p_L - rho_LR * b) -
952 K_pT_thermal_osmosis * dNdx * T);
955 .template block<temperature_size, temperature_size>(
957 .noalias() += (dNdx.transpose() * thermal_conductivity * dNdx +
958 N.transpose() * velocity_L.transpose() * dNdx *
959 rho_LR * specific_heat_capacity_fluid) *
962 .template block<temperature_size, pressure_size>(
965 dNdx.transpose() * T_ip * K_pT_thermal_osmosis * dNdx * w;
967 if (gas_phase && S_L < 1.0)
971 double const rho_wv =
973 .template value<double>(variables, x_position, t, dt);
975 double const drho_wv_dT =
977 .template dValue<double>(variables,
980 double const drho_wv_dp =
982 .template dValue<double>(
989 .template value<double>(variables, x_position, t, dt);
992 auto const tortuosity =
994 .template value<double>(variables, x_position, t, dt);
996 phi * (1.0 - S_L) * tortuosity *
998 .template value<double>(variables, x_position, t, dt);
1000 double const f_Tv_D_Tv = f_Tv * D_v * drho_wv_dT;
1001 double const D_pv = D_v * drho_wv_dp;
1006 -(f_Tv_D_Tv * grad_T - D_pv * grad_p_cap);
1007 double const specific_heat_capacity_vapour =
1009 .template value<double>(variables, x_position, t, dt);
1012 .template block<temperature_size, temperature_size>(
1015 w * (rho_wv * specific_heat_capacity_vapour * (1 - S_L) * phi) *
1019 .template block<temperature_size, temperature_size>(
1021 .noalias() += N.transpose() * vapour_flux.transpose() * dNdx *
1022 specific_heat_capacity_vapour * w;
1024 double const storage_coefficient_by_water_vapor =
1025 phi * (rho_wv * dS_L_dp_cap + (1 - S_L) * drho_wv_dp);
1030 N.transpose() * storage_coefficient_by_water_vapor * N * w;
1032 double const vapor_expansion_factor = phi * (1 - S_L) * drho_wv_dT;
1034 .template block<pressure_size, temperature_size>(
1036 .noalias() += N.transpose() * vapor_expansion_factor * N * w;
1039 .noalias() -= f_Tv_D_Tv * dNdx.transpose() * (dNdx * T) * w;
1044 .noalias() += dNdx.transpose() * D_pv * dNdx * w;
1051 double const factor = phi * (1 - S_L) / rho_LR;
1055 .template value<double>(variables, x_position, t, dt) *
1058 double const drho_LR_dT =
1060 .template dValue<double>(variables,
1064 double const rho_wv_over_rho_L = rho_wv / rho_LR;
1066 .template block<temperature_size, temperature_size>(
1070 (drho_wv_dT - rho_wv_over_rho_L * drho_LR_dT) *
1071 N.transpose() * N * w;
1074 .template block<temperature_size, pressure_size>(
1078 (drho_wv_dp - rho_wv_over_rho_L * drho_LR_dp) +
1079 L0 * phi * rho_wv_over_rho_L * dS_L_dp_cap) *
1080 N.transpose() * N * w;
1084 .template block<temperature_size, temperature_size>(
1087 L0 * f_Tv_D_Tv * dNdx.transpose() * dNdx * w / rho_LR;
1090 .template block<temperature_size, pressure_size>(
1093 L0 * D_pv * dNdx.transpose() * dNdx * w / rho_LR;
1100 auto Mpp = local_M.template block<pressure_size, pressure_size>(
1102 Mpp = Mpp.colwise().sum().eval().asDiagonal();
1189 Eigen::VectorXd
const& local_x,
1190 Eigen::VectorXd
const& local_x_prev)
1195 auto const p_L = local_x.template segment<pressure_size>(
pressure_index);
1201 auto const& liquid_phase =
1203 auto const& solid_phase =
1208 unsigned const n_integration_points =
1211 double saturation_avg = 0;
1212 double porosity_avg = 0;
1214 for (
unsigned ip = 0; ip < n_integration_points; ip++)
1230 double p_cap_prev_ip;
1241 auto& S_L =
_ip_data[ip].saturation;
1242 auto const S_L_prev =
_ip_data[ip].saturation_prev;
1244 variables, x_position, t, dt);
1249 auto chi_S_L_prev = S_L_prev;
1252 auto const chi = [&medium, x_position, t, dt](
double const S_L)
1257 .template value<double>(variables, x_position, t, dt);
1260 chi_S_L_prev = chi(S_L_prev);
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;
1280 variables, variables_prev, x_position, t, dt);
1286 variables, x_position, t, dt);
1289 variables, x_position, t, dt);
1295 double const k_rel =
1297 .template value<double>(variables, x_position, t, dt);
1303 variables, x_position, t, dt);
1304 _ip_data[ip].dry_density_solid = (1 - phi) * rho_SR;
1310 medium, variables, x_position, t, dt, K_intrinsic, mu);
1313 auto const& dNdx =
_ip_data[ip].dNdx;
1314 _ip_data[ip].v_darcy.noalias() = -K_over_mu * dNdx * p_L -
1315 K_pT_thermal_osmosis * dNdx * T +
1316 rho_LR * K_over_mu * b;
1318 saturation_avg += S_L;
1319 porosity_avg += phi;
1321 saturation_avg /= n_integration_points;
1322 porosity_avg /= n_integration_points;