151 std::vector<double>
const& local_x,
152 std::vector<double>
const& local_x_prev,
153 std::vector<double>& local_rhs_data,
154 std::vector<double>& local_Jac_data)
157 assert(local_x.size() == local_matrix_dim);
159 auto const T = Eigen::Map<
typename ShapeMatricesType::template VectorType<
162 auto const p_L = Eigen::Map<
163 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
167 Eigen::Map<
typename ShapeMatricesType::template VectorType<
170 auto const p_L_prev = Eigen::Map<
171 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
175 typename ShapeMatricesType::template MatrixType<local_matrix_dim,
177 local_Jac_data, local_matrix_dim, local_matrix_dim);
180 typename ShapeMatricesType::template VectorType<local_matrix_dim>>(
181 local_rhs_data, local_matrix_dim);
216 auto const& liquid_phase =
218 auto const& solid_phase =
225 unsigned const n_integration_points =
227 for (
unsigned ip = 0; ip < n_integration_points; ip++)
229 auto const& w =
_ip_data[ip].integration_weight;
232 auto const& dNdx =
_ip_data[ip].dNdx;
246 double p_cap_prev_ip;
256 auto& S_L =
_ip_data[ip].saturation;
257 auto const S_L_prev =
_ip_data[ip].saturation_prev;
260 variables, x_position, t, dt);
262 auto& solid_elasticity = *
_process_data.simplified_elasticity;
266 solid_elasticity.bulkCompressibilityFromYoungsModulus(
267 solid_phase, variables, x_position, t, dt);
268 auto const beta_SR = (1 - alpha) * beta_S;
273 variables, x_position, t, dt);
277 double const drho_LR_dp =
281 auto const beta_LR = drho_LR_dp / rho_LR;
284 variables, x_position, t, dt);
289 double const dS_L_dp_cap =
295 double const DeltaS_L_Deltap_cap =
296 (p_cap_ip == p_cap_prev_ip)
298 : (S_L - S_L_prev) / (p_cap_ip - p_cap_prev_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)
310 .template value<double>(variables, x_position, t, dt);
313 chi_S_L_prev = chi(S_L_prev);
316 .template dValue<double>(
333 variables, variables_prev, x_position, t, dt);
340 "ThermoRichardsFlow: Biot-coefficient {} is smaller than "
341 "porosity {} in element/integration point {}/{}.",
347 .template value<double>(variables, x_position, t, dt);
350 variables, x_position, t, dt);
359 auto const K_pT_thermal_osmosis =
360 (solid_phase.hasProperty(
365 .value(variables, x_position, t, dt))
366 : Eigen::MatrixXd::Zero(GlobalDim, GlobalDim));
371 Eigen::Matrix<double, 3, 3>
const
372 solid_linear_thermal_expansion_coefficient =
376 .value(variables, x_position, t, dt));
380 variables, x_position, t, dt);
385 laplace_p.noalias() +=
386 dNdx.transpose() * k_rel * rho_Ki_over_mu * dNdx * w;
387 laplace_T.noalias() +=
388 dNdx.transpose() * rho_LR * K_pT_thermal_osmosis * dNdx * w;
389 const double alphaB_minus_phi = alpha - phi;
390 double const a0 = alphaB_minus_phi * beta_SR;
391 double const specific_storage_a_p =
392 S_L * (phi * beta_LR + S_L * a0 +
393 chi_S_L * alpha * alpha *
394 solid_elasticity.storageContribution(
395 solid_phase, variables, x_position, t, dt));
396 double const specific_storage_a_S = phi - p_cap_ip * S_L * a0;
398 double const dspecific_storage_a_p_dp_cap =
399 dS_L_dp_cap * (phi * beta_LR + 2 * S_L * a0 +
401 solid_elasticity.storageContribution(
402 solid_phase, variables, x_position, t, dt) *
403 (chi_S_L + dchi_dS_L * S_L));
404 double const dspecific_storage_a_S_dp_cap =
405 -a0 * (S_L + p_cap_ip * dS_L_dp_cap);
407 storage_p_a_p.noalias() +=
408 N.transpose() * rho_LR * specific_storage_a_p * N * w;
410 storage_p_a_S.noalias() -= N.transpose() * rho_LR *
411 specific_storage_a_S * DeltaS_L_Deltap_cap *
417 .noalias() += N.transpose() * (p_cap_ip - p_cap_prev_ip) / dt *
418 rho_LR * dspecific_storage_a_p_dp_cap * N * w;
420 storage_p_a_S_Jpp.noalias() -=
421 N.transpose() * rho_LR *
422 ((S_L - S_L_prev) * dspecific_storage_a_S_dp_cap +
423 specific_storage_a_S * dS_L_dp_cap) /
426 double const dk_rel_dS_L =
428 .template dValue<double>(variables,
435 .noalias() += dNdx.transpose() * rho_Ki_over_mu * grad_p_cap *
436 dk_rel_dS_L * dS_L_dp_cap * N * w;
441 .noalias() += dNdx.transpose() * rho_LR * rho_Ki_over_mu * b *
442 dk_rel_dS_L * dS_L_dp_cap * N * w;
444 local_rhs.template segment<pressure_size>(
pressure_index).noalias() +=
445 dNdx.transpose() * rho_LR * k_rel * rho_Ki_over_mu * b * w;
450 double const fluid_volumetric_thermal_expansion_coefficient =
453 const double eff_thermal_expansion =
454 S_L * (alphaB_minus_phi *
455 solid_linear_thermal_expansion_coefficient.trace() +
456 phi * fluid_volumetric_thermal_expansion_coefficient +
457 alpha * solid_elasticity.thermalExpansivityContribution(
458 solid_linear_thermal_expansion_coefficient,
459 solid_phase, variables, x_position, t, dt));
461 N.transpose() * rho_LR * eff_thermal_expansion * N * w;
467 auto const specific_heat_capacity_fluid =
469 .template value<double>(variables, x_position, t, dt);
471 auto const specific_heat_capacity_solid =
474 .template value<double>(variables, x_position, t, dt);
478 (rho_SR * specific_heat_capacity_solid * (1 - phi) +
479 (S_L * rho_LR * specific_heat_capacity_fluid) * phi) *
482 auto const thermal_conductivity =
485 thermal_conductivity]
486 .value(variables, x_position, t, dt));
489 -Ki_over_mu * k_rel * (dNdx * p_L - rho_LR * b) -
490 K_pT_thermal_osmosis * dNdx * T);
492 K_TT.noalias() += (dNdx.transpose() * thermal_conductivity * dNdx +
493 N.transpose() * velocity_L.transpose() * dNdx *
494 rho_LR * specific_heat_capacity_fluid) *
501 dNdx.transpose() * T_ip * K_pT_thermal_osmosis * dNdx * w;
502 dK_TT_dp.noalias() -= rho_LR * specific_heat_capacity_fluid *
503 N.transpose() * (dNdx * T).transpose() *
504 k_rel * Ki_over_mu * dNdx * w;
506 dK_TT_dp.noalias() -= rho_LR * specific_heat_capacity_fluid *
507 N.transpose() * velocity_L.dot(dNdx * T) /
508 k_rel * dk_rel_dS_L * dS_L_dp_cap * N * w;
510 if (gas_phase && S_L < 1.0)
514 double const rho_wv =
516 .template value<double>(variables, x_position, t, dt);
518 double const drho_wv_dT =
520 .template dValue<double>(variables,
523 double const drho_wv_dp =
525 .template dValue<double>(
532 .template value<double>(variables, x_position, t, dt);
535 auto const tortuosity =
537 .template value<double>(variables, x_position, t, dt);
539 phi * (1.0 - S_L) * tortuosity *
541 .template value<double>(variables, x_position, t, dt);
543 double const f_Tv_D_Tv = f_Tv * D_v * drho_wv_dT;
544 double const D_pv = D_v * drho_wv_dp;
548 -(f_Tv_D_Tv * grad_T - D_pv * grad_p_cap);
549 double const specific_heat_capacity_vapour =
551 .template value<double>(variables, x_position, t, dt);
554 w * (rho_wv * specific_heat_capacity_vapour * (1 - S_L) * phi) *
557 K_TT.noalias() += N.transpose() * vapour_flux.transpose() * dNdx *
558 specific_heat_capacity_vapour * w;
560 double const storage_coefficient_by_water_vapor =
561 phi * (rho_wv * dS_L_dp_cap + (1 - S_L) * drho_wv_dp);
563 storage_p_a_p.noalias() +=
564 N.transpose() * storage_coefficient_by_water_vapor * N * w;
566 double const vapor_expansion_factor = phi * (1 - S_L) * drho_wv_dT;
567 M_pT.noalias() += N.transpose() * vapor_expansion_factor * N * w;
570 .template block<pressure_size, temperature_size>(
572 .noalias() += dNdx.transpose() * f_Tv_D_Tv * dNdx * w;
575 .noalias() -= f_Tv_D_Tv * dNdx.transpose() * (dNdx * T) * w;
577 laplace_p.noalias() += dNdx.transpose() * D_pv * dNdx * w;
584 double const factor = phi * (1 - S_L) / rho_LR;
588 .template value<double>(variables, x_position, t, dt) *
591 double const drho_LR_dT =
593 .template dValue<double>(variables,
597 double const rho_wv_over_rho_L = rho_wv / rho_LR;
600 (drho_wv_dT - rho_wv_over_rho_L * drho_LR_dT) *
601 N.transpose() * N * w;
605 (drho_wv_dp - rho_wv_over_rho_L * drho_LR_dp) +
606 L0 * phi * rho_wv_over_rho_L * dS_L_dp_cap) *
607 N.transpose() * N * w;
611 L0 * f_Tv_D_Tv * dNdx.transpose() * dNdx * w / rho_LR;
614 L0 * D_pv * dNdx.transpose() * dNdx * w / rho_LR;
621 storage_p_a_p = storage_p_a_p.colwise().sum().eval().asDiagonal();
622 storage_p_a_S = storage_p_a_S.colwise().sum().eval().asDiagonal();
624 storage_p_a_S_Jpp.colwise().sum().eval().asDiagonal();
634 .noalias() += M_TT / dt + K_TT;
639 .noalias() += K_Tp + dK_TT_dp;
645 .noalias() += laplace_p + storage_p_a_p / dt + storage_p_a_S_Jpp;
651 .noalias() += M_pT / dt + laplace_T;
658 M_TT * (T - T_prev) / dt + K_TT * T;
663 local_rhs.template segment<pressure_size>(
pressure_index).noalias() -=
664 laplace_p * p_L + laplace_T * T +
665 (storage_p_a_p + storage_p_a_S) * (p_L - p_L_prev) / dt +
666 M_pT * (T - T_prev) / dt;
673 .template block<temperature_size, pressure_size>(
675 .noalias() += M_Tp / dt;
678 .noalias() -= M_Tp * (p_L - p_L_prev) / dt;
685 double const t,
double const dt, std::vector<double>
const& local_x,
686 std::vector<double>
const& local_x_prev, std::vector<double>& local_M_data,
687 std::vector<double>& local_K_data, std::vector<double>& local_rhs_data)
690 assert(local_x.size() == local_matrix_dim);
692 auto const T = Eigen::Map<
typename ShapeMatricesType::template VectorType<
695 auto const p_L = Eigen::Map<
696 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
699 auto const p_L_prev = Eigen::Map<
700 typename ShapeMatricesType::template VectorType<pressure_size>
const>(
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);
718 auto const& liquid_phase =
720 auto const& solid_phase =
727 unsigned const n_integration_points =
729 for (
unsigned ip = 0; ip < n_integration_points; ip++)
731 auto const& w =
_ip_data[ip].integration_weight;
734 auto const& dNdx =
_ip_data[ip].dNdx;
748 double p_cap_prev_ip;
758 auto& S_L =
_ip_data[ip].saturation;
759 auto const S_L_prev =
_ip_data[ip].saturation_prev;
762 variables, x_position, t, dt);
764 auto& solid_elasticity = *
_process_data.simplified_elasticity;
768 solid_elasticity.bulkCompressibilityFromYoungsModulus(
769 solid_phase, variables, x_position, t, dt);
770 auto const beta_SR = (1 - alpha) * beta_S;
775 variables, x_position, t, dt);
778 double const drho_LR_dp =
782 auto const beta_LR = drho_LR_dp / rho_LR;
785 variables, x_position, t, dt);
790 double const dS_L_dp_cap =
796 double const DeltaS_L_Deltap_cap =
797 (p_cap_ip == p_cap_prev_ip)
799 : (S_L - S_L_prev) / (p_cap_ip - p_cap_prev_ip);
802 auto chi_S_L_prev = S_L_prev;
805 auto const chi = [&medium, x_position, t, dt](
double const S_L)
810 .template value<double>(variables, x_position, t, dt);
813 chi_S_L_prev = chi(S_L_prev);
828 variables, variables_prev, x_position, t, dt);
835 "ThermoRichardsFlow: Biot-coefficient {} is smaller than "
836 "porosity {} in element/integration point {}/{}.",
840 auto const K_pT_thermal_osmosis =
841 (solid_phase.hasProperty(
846 .value(variables, x_position, t, dt))
847 : Eigen::MatrixXd::Zero(GlobalDim, GlobalDim));
851 .template value<double>(variables, x_position, t, dt);
854 variables, x_position, t, dt);
866 Eigen::Matrix<double, 3, 3>
const
867 solid_linear_thermal_expansion_coefficient =
871 .value(variables, x_position, t, dt));
875 variables, x_position, t, dt);
883 .noalias() += dNdx.transpose() * k_rel * rho_Ki_over_mu * dNdx * w;
885 const double alphaB_minus_phi = alpha - phi;
886 double const a0 = alphaB_minus_phi * beta_SR;
887 double const specific_storage_a_p =
888 S_L * (phi * beta_LR + S_L * a0 +
889 chi_S_L * alpha * alpha *
890 solid_elasticity.storageContribution(
891 solid_phase, variables, x_position, t, dt));
892 double const specific_storage_a_S = phi - p_cap_ip * S_L * a0;
897 .noalias() += N.transpose() * rho_LR *
898 (specific_storage_a_p -
899 specific_storage_a_S * DeltaS_L_Deltap_cap) *
902 local_rhs.template segment<pressure_size>(
pressure_index).noalias() +=
903 dNdx.transpose() * rho_LR * k_rel * rho_Ki_over_mu * b * w;
908 double const fluid_volumetric_thermal_expansion_coefficient =
911 const double eff_thermal_expansion =
912 S_L * (alphaB_minus_phi *
913 solid_linear_thermal_expansion_coefficient.trace() +
914 phi * fluid_volumetric_thermal_expansion_coefficient +
915 alpha * solid_elasticity.thermalExpansivityContribution(
916 solid_linear_thermal_expansion_coefficient,
917 solid_phase, variables, x_position, t, dt));
923 dNdx.transpose() * rho_LR * K_pT_thermal_osmosis * dNdx * w;
929 N.transpose() * rho_LR * eff_thermal_expansion * N * w;
935 auto const specific_heat_capacity_fluid =
937 .template value<double>(variables, x_position, t, dt);
939 auto const specific_heat_capacity_solid =
942 .template value<double>(variables, x_position, t, dt);
945 .template block<temperature_size, temperature_size>(
949 (rho_SR * specific_heat_capacity_solid * (1 - phi) +
950 (S_L * rho_LR * specific_heat_capacity_fluid) * phi) *
953 auto const thermal_conductivity =
956 thermal_conductivity]
957 .value(variables, x_position, t, dt));
960 -Ki_over_mu * k_rel * (dNdx * p_L - rho_LR * b) -
961 K_pT_thermal_osmosis * dNdx * T);
964 .template block<temperature_size, temperature_size>(
966 .noalias() += (dNdx.transpose() * thermal_conductivity * dNdx +
967 N.transpose() * velocity_L.transpose() * dNdx *
968 rho_LR * specific_heat_capacity_fluid) *
971 .template block<temperature_size, pressure_size>(
974 dNdx.transpose() * T_ip * K_pT_thermal_osmosis * dNdx * w;
976 if (gas_phase && S_L < 1.0)
980 double const rho_wv =
982 .template value<double>(variables, x_position, t, dt);
984 double const drho_wv_dT =
986 .template dValue<double>(variables,
989 double const drho_wv_dp =
991 .template dValue<double>(
998 .template value<double>(variables, x_position, t, dt);
1001 auto const tortuosity =
1003 .template value<double>(variables, x_position, t, dt);
1005 phi * (1.0 - S_L) * tortuosity *
1007 .template value<double>(variables, x_position, t, dt);
1009 double const f_Tv_D_Tv = f_Tv * D_v * drho_wv_dT;
1010 double const D_pv = D_v * drho_wv_dp;
1015 -(f_Tv_D_Tv * grad_T - D_pv * grad_p_cap);
1016 double const specific_heat_capacity_vapour =
1018 .template value<double>(variables, x_position, t, dt);
1021 .template block<temperature_size, temperature_size>(
1024 w * (rho_wv * specific_heat_capacity_vapour * (1 - S_L) * phi) *
1028 .template block<temperature_size, temperature_size>(
1030 .noalias() += N.transpose() * vapour_flux.transpose() * dNdx *
1031 specific_heat_capacity_vapour * w;
1033 double const storage_coefficient_by_water_vapor =
1034 phi * (rho_wv * dS_L_dp_cap + (1 - S_L) * drho_wv_dp);
1039 N.transpose() * storage_coefficient_by_water_vapor * N * w;
1041 double const vapor_expansion_factor = phi * (1 - S_L) * drho_wv_dT;
1043 .template block<pressure_size, temperature_size>(
1045 .noalias() += N.transpose() * vapor_expansion_factor * N * w;
1048 .noalias() -= f_Tv_D_Tv * dNdx.transpose() * (dNdx * T) * w;
1053 .noalias() += dNdx.transpose() * D_pv * dNdx * w;
1060 double const factor = phi * (1 - S_L) / rho_LR;
1064 .template value<double>(variables, x_position, t, dt) *
1067 double const drho_LR_dT =
1069 .template dValue<double>(variables,
1073 double const rho_wv_over_rho_L = rho_wv / rho_LR;
1075 .template block<temperature_size, temperature_size>(
1079 (drho_wv_dT - rho_wv_over_rho_L * drho_LR_dT) *
1080 N.transpose() * N * w;
1083 .template block<temperature_size, pressure_size>(
1087 (drho_wv_dp - rho_wv_over_rho_L * drho_LR_dp) +
1088 L0 * phi * rho_wv_over_rho_L * dS_L_dp_cap) *
1089 N.transpose() * N * w;
1093 .template block<temperature_size, temperature_size>(
1096 L0 * f_Tv_D_Tv * dNdx.transpose() * dNdx * w / rho_LR;
1099 .template block<temperature_size, pressure_size>(
1102 L0 * D_pv * dNdx.transpose() * dNdx * w / rho_LR;
1109 auto Mpp = local_M.template block<pressure_size, pressure_size>(
1111 Mpp = Mpp.colwise().sum().eval().asDiagonal();
1198 Eigen::VectorXd
const& local_x,
1199 Eigen::VectorXd
const& local_x_prev)
1204 auto const p_L = local_x.template segment<pressure_size>(
pressure_index);
1210 auto const& liquid_phase =
1212 auto const& solid_phase =
1217 unsigned const n_integration_points =
1220 double saturation_avg = 0;
1221 double porosity_avg = 0;
1223 for (
unsigned ip = 0; ip < n_integration_points; ip++)
1239 double p_cap_prev_ip;
1250 auto& S_L =
_ip_data[ip].saturation;
1251 auto const S_L_prev =
_ip_data[ip].saturation_prev;
1253 variables, x_position, t, dt);
1258 auto chi_S_L_prev = S_L_prev;
1261 auto const chi = [&medium, x_position, t, dt](
double const S_L)
1266 .template value<double>(variables, x_position, t, dt);
1269 chi_S_L_prev = chi(S_L_prev);
1276 variables, x_position, t, dt);
1278 auto& solid_elasticity = *
_process_data.simplified_elasticity;
1280 solid_elasticity.bulkCompressibilityFromYoungsModulus(
1281 solid_phase, variables, x_position, t, dt);
1282 auto const beta_SR = (1 - alpha) * beta_S;
1289 variables, variables_prev, x_position, t, dt);
1295 variables, x_position, t, dt);
1298 variables, x_position, t, dt);
1304 double const k_rel =
1306 .template value<double>(variables, x_position, t, dt);
1312 variables, x_position, t, dt);
1313 _ip_data[ip].dry_density_solid = (1 - phi) * rho_SR;
1317 auto const K_pT_thermal_osmosis =
1318 (solid_phase.hasProperty(
1323 .value(variables, x_position, t, dt))
1324 : Eigen::MatrixXd::Zero(GlobalDim, GlobalDim));
1327 auto const& dNdx =
_ip_data[ip].dNdx;
1328 _ip_data[ip].v_darcy.noalias() = -K_over_mu * dNdx * p_L -
1329 K_pT_thermal_osmosis * dNdx * T +
1330 rho_LR * K_over_mu * b;
1332 saturation_avg += S_L;
1333 porosity_avg += phi;
1335 saturation_avg /= n_integration_points;
1336 porosity_avg /= n_integration_points;