233 ShapeFunctionDisplacement, ShapeFunctionPressure, DisplacementDim>::
234 updateConstitutiveRelations(
235 Eigen::Ref<Eigen::VectorXd const>
const local_x,
236 Eigen::Ref<Eigen::VectorXd const>
const local_x_prev,
238 double const dt,
IpData& ip_data,
241 assert(local_x.size() ==
242 pressure_size + displacement_size + temperature_size);
244 auto const [T, p, u] = localDOF(local_x);
245 auto const [T_prev, p_prev, u_prev] = localDOF(local_x_prev);
247 auto const& solid_material =
249 _process_data.solid_materials, _process_data.material_ids,
252 auto const& medium = _process_data.media_map.getMedium(_element.getID());
253 auto const& liquid_phase = medium->phase(
"AqueousLiquid");
254 auto const& solid_phase = medium->phase(
"Solid");
255 auto*
const frozen_liquid_phase = medium->hasPhase(
"FrozenLiquid")
256 ? &medium->phase(
"FrozenLiquid")
260 auto const& N_u = ip_data.
N_u;
261 auto const& dNdx_u = ip_data.
dNdx_u;
263 auto const& N = ip_data.
N;
264 auto const& dNdx = ip_data.
dNdx;
266 auto const T_int_pt = N.dot(T);
267 auto const T_prev_int_pt = N.dot(T_prev);
268 double const dT_int_pt = T_int_pt - T_prev_int_pt;
276 ShapeFunctionDisplacement::NPOINTS,
278 dNdx_u, N_u, x_coord, _is_axially_symmetric);
282 auto& eps = ip_data.
eps;
283 eps.noalias() = B * u;
288 double const p_int_pt = N.dot(p);
293 auto const solid_density =
295 .template value<double>(vars, x_position, t, dt);
297 auto const porosity =
299 .template value<double>(vars, x_position, t, dt);
305 .template value<double>(vars, x_position, t, dt);
306 auto const& alpha = crv.alpha_biot;
309 t, x_position, dt,
static_cast<double>(T_int_pt));
310 auto const solid_skeleton_compressibility =
311 1 / solid_material.getBulkModulus(t, x_position, &C_el);
313 crv.beta_SR = (1 - alpha) * solid_skeleton_compressibility;
318 auto const& identity2 = Invariants::identity2;
319 auto const sigma_total =
320 (ip_data.
sigma_eff - alpha * p_int_pt * identity2).eval();
329 auto const intrinsic_permeability =
332 .value(vars, x_position, t, dt));
334 auto const fluid_density =
336 .template value<double>(vars, x_position, t, dt);
342 .template dValue<double>(
346 crv.fluid_compressibility = 1 / fluid_density * drho_dp;
348 double const fluid_volumetric_thermal_expansion_coefficient =
350 liquid_phase, vars, fluid_density, x_position, t, dt);
355 .template value<double>(vars, x_position, t, dt);
356 crv.K_over_mu = intrinsic_permeability / ip_data_output.
viscosity;
358 auto const& b = _process_data.specific_body_force;
361 crv.solid_linear_thermal_expansion_coefficient =
366 .value(vars, x_position, t, dt));
370 crv.solid_linear_thermal_expansion_coefficient * dT_int_pt;
372 crv.K_pT_thermal_osmosis =
373 (solid_phase.hasProperty(
378 thermal_osmosis_coefficient)
379 .value(vars, x_position, t, dt))
380 : Eigen::MatrixXd::Zero(DisplacementDim, DisplacementDim));
383 crv.K_pT_thermal_osmosis * dNdx * T +
384 crv.K_over_mu * fluid_density * b;
390 auto& eps_m = ip_data.
eps_m;
392 eps_m.noalias() = eps_m_prev + eps - eps_prev - dthermal_strain;
400 crv.rho = solid_density * (1 - porosity) + porosity * fluid_density;
403 porosity * fluid_volumetric_thermal_expansion_coefficient +
405 Invariants::trace(crv.solid_linear_thermal_expansion_coefficient);
418 .template value<double>(vars, x_position, t, dt);
419 crv.effective_thermal_conductivity =
424 .value(vars, x_position, t, dt));
428 crv.effective_thermal_conductivity.noalias() +=
429 fluid_density * crv.c_f *
431 _process_data.stabilizer, _element.getID(),
432 GlobalDimMatrixType::Zero(DisplacementDim, DisplacementDim),
439 .template value<double>(vars, x_position, t, dt);
442 crv.effective_volumetric_heat_capacity =
443 porosity * fluid_density * crv.c_f +
444 (1.0 - porosity) * solid_density * c_s;
446 if (frozen_liquid_phase)
449 double const phi_fr =
451 .template value<double>(vars, x_position, t, dt);
454 auto const frozen_liquid_value =
457 return (*frozen_liquid_phase)[p].template value<double>(
458 vars, x_position, t, dt);
461 double const rho_fr =
464 double const c_fr = frozen_liquid_value(
467 double const l_fr = frozen_liquid_value(
470 double const dphi_fr_dT =
472 .template dValue<double>(
476 double const phi_fr_prev = [&]()
481 .template value<double>(vars_prev, x_position, t, dt);
487 DisplacementDim>
const ice_linear_thermal_expansion_coefficient =
492 .value(vars, x_position, t, dt));
495 dthermal_strain_ice =
496 ice_linear_thermal_expansion_coefficient * dT_int_pt;
501 phase_change_expansion_coefficient =
505 phase_change_expansivity)
506 .value(vars, x_position, t, dt));
509 dphase_change_strain = phase_change_expansion_coefficient *
510 (phi_fr - phi_fr_prev) / porosity;
514 auto& eps0 = ip_data.
eps0;
515 auto const& eps0_prev = ip_data.
eps0_prev;
521 eps_m_ice.noalias() = eps_m_ice_prev + eps - eps_prev -
522 (eps0 - eps0_prev) - dthermal_strain_ice -
523 dphase_change_strain;
529 *_process_data.ice_constitutive_relation, vars_ice, t, x_position,
531 crv.effective_volumetric_heat_capacity +=
532 -phi_fr * fluid_density * crv.c_f + phi_fr * rho_fr * c_fr -
533 l_fr * rho_fr * dphi_fr_dT;
536 double const d2phi_fr_dT2 =
538 .template d2Value<double>(
543 crv.J_uu_fr = phi_fr * C_IR;
546 crv.r_u_fr = phi_fr * sigma_eff_ice;
548 crv.J_uT_fr = phi_fr * C_IR * ice_linear_thermal_expansion_coefficient;
550 crv.J_TT_fr = ((rho_fr * c_fr - fluid_density * crv.c_f) * dphi_fr_dT +
551 l_fr * rho_fr * d2phi_fr_dT2) *
563 DisplacementDim>::assembleWithJacobian(
double const t,
double const dt,
564 std::vector<double>
const& local_x,
565 std::vector<double>
const&
567 std::vector<double>& local_rhs_data,
568 std::vector<double>& local_Jac_data)
570 assert(local_x.size() ==
571 pressure_size + displacement_size + temperature_size);
574 Eigen::Map<Eigen::VectorXd const>(local_x.data(), local_x.size());
575 auto const x_prev = Eigen::Map<Eigen::VectorXd const>(local_x_prev.data(),
576 local_x_prev.size());
578 auto const [T, p, u] = localDOF(local_x);
579 auto const [T_prev, p_prev, u_prev] = localDOF(local_x_prev);
582 typename ShapeMatricesTypeDisplacement::template MatrixType<
583 temperature_size + displacement_size + pressure_size,
584 temperature_size + displacement_size + pressure_size>>(
585 local_Jac_data, displacement_size + pressure_size + temperature_size,
586 displacement_size + pressure_size + temperature_size);
589 typename ShapeMatricesTypeDisplacement::template VectorType<
590 displacement_size + pressure_size + temperature_size>>(
591 local_rhs_data, displacement_size + pressure_size + temperature_size);
594 MTT.setZero(temperature_size, temperature_size);
597 KTT.setZero(temperature_size, temperature_size);
600 KTp.setZero(temperature_size, pressure_size);
603 dKTT_dp.setZero(temperature_size, pressure_size);
606 laplace_p.setZero(pressure_size, pressure_size);
609 laplace_T.setZero(pressure_size, temperature_size);
612 storage_p.setZero(pressure_size, pressure_size);
615 storage_T.setZero(pressure_size, temperature_size);
617 typename ShapeMatricesTypeDisplacement::template MatrixType<
618 displacement_size, pressure_size>
620 Kup.setZero(displacement_size, pressure_size);
622 auto const& medium = _process_data.media_map.getMedium(_element.getID());
623 bool const has_frozen_liquid_phase = medium->hasPhase(
"FrozenLiquid");
625 unsigned const n_integration_points =
626 _integration_method.getNumberOfPoints();
628 std::vector<GlobalDimVectorType> ip_flux_vector;
629 double average_velocity_norm = 0.0;
630 ip_flux_vector.reserve(n_integration_points);
632 for (
unsigned ip = 0; ip < n_integration_points; ip++)
634 auto const& N_u = _ip_data[ip].N_u;
636 std::nullopt, _element.getID(),
642 auto const crv = updateConstitutiveRelations(
643 x, x_prev, x_position, t, dt, _ip_data[ip], _ip_data_output[ip]);
645 auto const& w = _ip_data[ip].integration_weight;
647 auto const& dNdx_u = _ip_data[ip].dNdx_u;
649 auto const& N = _ip_data[ip].N;
650 auto const& dNdx = _ip_data[ip].dNdx;
652 auto const T_int_pt = N.dot(T);
660 ShapeFunctionDisplacement::NPOINTS,
662 dNdx_u, N_u, x_coord, _is_axially_symmetric);
664 auto const& b = _process_data.specific_body_force;
665 auto const velocity = _ip_data_output[ip].velocity;
671 if (has_frozen_liquid_phase)
674 .template block<displacement_size, displacement_size>(
675 displacement_index, displacement_index)
676 .noalias() += B.transpose() * crv.J_uu_fr * B * w;
678 local_rhs.template segment<displacement_size>(displacement_index)
679 .noalias() -= B.transpose() * crv.r_u_fr * w;
682 .template block<displacement_size, temperature_size>(
683 displacement_index, temperature_index)
684 .noalias() -= B.transpose() * crv.J_uT_fr * N * w;
688 .template block<displacement_size, displacement_size>(
689 displacement_index, displacement_index)
690 .noalias() += B.transpose() * crv.C * B * w;
693 .template block<displacement_size, temperature_size>(
694 displacement_index, temperature_index)
695 .noalias() -= B.transpose() * crv.C *
696 crv.solid_linear_thermal_expansion_coefficient * N *
699 local_rhs.template segment<displacement_size>(displacement_index)
700 .noalias() -= (B.transpose() * _ip_data[ip].sigma_eff -
701 N_u_op(N_u).transpose() * crv.rho * b) *
708 B.transpose() * crv.alpha_biot * Invariants::identity2 * N * w;
713 laplace_p.noalias() += dNdx.transpose() * crv.K_over_mu * dNdx * w;
715 storage_p.noalias() +=
717 (_ip_data[ip].porosity * crv.fluid_compressibility +
718 (crv.alpha_biot - _ip_data[ip].porosity) * crv.beta_SR) *
721 laplace_T.noalias() +=
722 dNdx.transpose() * crv.K_pT_thermal_osmosis * dNdx * w;
726 double const fluid_density = _ip_data_output[ip].fluid_density;
727 local_rhs.template segment<pressure_size>(pressure_index).noalias() +=
728 dNdx.transpose() * fluid_density * crv.K_over_mu * b * w;
732 storage_T.noalias() += N.transpose() * crv.beta * N * w;
743 dNdx.transpose() * crv.effective_thermal_conductivity * dNdx * w;
745 ip_flux_vector.emplace_back(velocity * fluid_density * crv.c_f);
746 average_velocity_norm += velocity.norm();
748 if (has_frozen_liquid_phase)
751 .template block<temperature_size, temperature_size>(
752 temperature_index, temperature_index)
753 .noalias() -= N.transpose() * crv.J_TT_fr * N * w;
757 N.transpose() * crv.effective_volumetric_heat_capacity * N * w;
763 dNdx.transpose() * T_int_pt * crv.K_pT_thermal_osmosis * dNdx * w;
766 dKTT_dp.noalias() -= fluid_density * crv.c_f * N.transpose() *
767 (dNdx * T).transpose() * crv.K_over_mu * dNdx * w;
813 _process_data.stabilizer, _ip_data, ip_flux_vector,
814 average_velocity_norm /
static_cast<double>(n_integration_points), KTT);
818 .template block<temperature_size, temperature_size>(temperature_index,
820 .noalias() += KTT + MTT / dt;
824 .template block<temperature_size, pressure_size>(temperature_index,
826 .noalias() += KTp + dKTT_dp;
830 .template block<displacement_size, pressure_size>(displacement_index,
836 .template block<pressure_size, temperature_size>(pressure_index,
838 .noalias() += -storage_T / dt + laplace_T;
842 .template block<pressure_size, pressure_size>(pressure_index,
844 .noalias() += laplace_p + storage_p / dt;
848 .template block<pressure_size, displacement_size>(pressure_index,
850 .noalias() += Kup.transpose() / dt;
853 local_rhs.template segment<pressure_size>(pressure_index).noalias() -=
854 laplace_p * p + laplace_T * T + storage_p * (p - p_prev) / dt -
855 storage_T * (T - T_prev) / dt + Kup.transpose() * (u - u_prev) / dt;
858 local_rhs.template segment<displacement_size>(displacement_index)
859 .noalias() += Kup * p;
862 local_rhs.template segment<temperature_size>(temperature_index).noalias() -=
863 KTT * T + MTT * (T - T_prev) / dt;
865 local_rhs.template segment<temperature_size>(temperature_index).noalias() -=
928 ShapeFunctionDisplacement, ShapeFunctionPressure, DisplacementDim>::
929 computeSecondaryVariableConcrete(
double const ,
double const ,
930 Eigen::VectorXd
const& local_x,
931 Eigen::VectorXd
const& )
933 auto const p = local_x.template segment<pressure_size>(pressure_index);
935 local_x.template segment<temperature_size>(temperature_index);
937 unsigned const n_integration_points =
938 _integration_method.getNumberOfPoints();
940 double phi_fr_avg = 0;
941 double fluid_density_avg = 0;
942 double viscosity_avg = 0;
945 KV sigma_avg = KV::Zero();
947 for (
unsigned ip = 0; ip < n_integration_points; ip++)
949 auto& ip_data = _ip_data[ip];
951 phi_fr_avg += _ip_data[ip].phi_fr;
952 fluid_density_avg += _ip_data_output[ip].fluid_density;
953 viscosity_avg += _ip_data_output[ip].viscosity;
954 sigma_avg += ip_data.sigma_eff;
957 phi_fr_avg /= n_integration_points;
958 fluid_density_avg /= n_integration_points;
959 viscosity_avg /= n_integration_points;
960 sigma_avg /= n_integration_points;
962 (*_process_data.element_phi_fr)[_element.getID()] = phi_fr_avg;
963 (*_process_data.element_fluid_density)[_element.getID()] =
965 (*_process_data.element_viscosity)[_element.getID()] = viscosity_avg;
967 Eigen::Map<KV>(&(*_process_data.element_stresses)[_element.getID() *
968 KV::RowsAtCompileTime]) =
972 ShapeFunctionPressure,
typename ShapeFunctionDisplacement::MeshElement,
973 DisplacementDim>(_element, _is_axially_symmetric, p,
974 *_process_data.pressure_interpolated);
977 ShapeFunctionPressure,
typename ShapeFunctionDisplacement::MeshElement,
978 DisplacementDim>(_element, _is_axially_symmetric, T,
979 *_process_data.temperature_interpolated);