OGS
ThermoHydroMechanicsFEM-impl.h
Go to the documentation of this file.
1
11#pragma once
12
13#include <typeinfo>
14
28
29namespace ProcessLib
30{
31namespace ThermoHydroMechanics
32{
33template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
34 int DisplacementDim>
35ThermoHydroMechanicsLocalAssembler<ShapeFunctionDisplacement,
36 ShapeFunctionPressure, DisplacementDim>::
37 ThermoHydroMechanicsLocalAssembler(
38 MeshLib::Element const& e,
39 std::size_t const /*local_matrix_size*/,
40 NumLib::GenericIntegrationMethod const& integration_method,
41 bool const is_axially_symmetric,
43 : _process_data(process_data),
44 _integration_method(integration_method),
45 _element(e),
46 _is_axially_symmetric(is_axially_symmetric)
47{
48 unsigned const n_integration_points =
50
51 _ip_data.reserve(n_integration_points);
52 _ip_data_output.resize(n_integration_points);
53 _secondary_data.N_u.resize(n_integration_points);
54
55 auto const shape_matrices_u =
56 NumLib::initShapeMatrices<ShapeFunctionDisplacement,
58 DisplacementDim>(e, is_axially_symmetric,
60
61 auto const shape_matrices_p =
62 NumLib::initShapeMatrices<ShapeFunctionPressure,
63 ShapeMatricesTypePressure, DisplacementDim>(
64 e, is_axially_symmetric, _integration_method);
65
66 auto const& solid_material =
68 _process_data.solid_materials, _process_data.material_ids,
69 e.getID());
70
71 // Consistency check: if frozen liquid phase is given, then the constitutive
72 // relation for ice must also be given, and vice versa.
73 auto const& medium = _process_data.media_map.getMedium(_element.getID());
74 if (medium->hasPhase("FrozenLiquid") !=
75 (_process_data.ice_constitutive_relation != nullptr))
76 {
78 "Frozen liquid phase is {:s} and the solid material constitutive "
79 "relation for ice is {:s}. But both must be given (or both "
80 "omitted).",
81 medium->hasPhase("FrozenLiquid") ? "specified" : "not specified",
82 _process_data.ice_constitutive_relation != nullptr
83 ? "specified"
84 : "not specified");
85 }
86 for (unsigned ip = 0; ip < n_integration_points; ip++)
87 {
88 _ip_data.emplace_back(solid_material);
89 auto& ip_data = _ip_data[ip];
90 auto const& sm_u = shape_matrices_u[ip];
91 ip_data.integration_weight =
93 sm_u.integralMeasure * sm_u.detJ;
94
95 ip_data.N_u = sm_u.N;
96 ip_data.dNdx_u = sm_u.dNdx;
97
98 ip_data.N = shape_matrices_p[ip].N;
99 ip_data.dNdx = shape_matrices_p[ip].dNdx;
100
101 _secondary_data.N_u[ip] = shape_matrices_u[ip].N;
102 }
103}
104
105template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
106 int DisplacementDim>
108 ShapeFunctionDisplacement, ShapeFunctionPressure,
109 DisplacementDim>::setIPDataInitialConditions(std::string const& name,
110 double const* values,
111 int const integration_order)
112{
113 if (integration_order !=
114 static_cast<int>(_integration_method.getIntegrationOrder()))
115 {
116 OGS_FATAL(
117 "Setting integration point initial conditions; The integration "
118 "order of the local assembler for element {:d} is different from "
119 "the integration order in the initial condition.",
120 _element.getID());
121 }
122
123 if (name == "sigma_ip")
124 {
125 if (_process_data.initial_stress != nullptr)
126 {
127 OGS_FATAL(
128 "Setting initial conditions for stress from integration "
129 "point data and from a parameter '{:s}' is not possible "
130 "simultaneously.",
131 _process_data.initial_stress->name);
132 }
133
134 return ProcessLib::setIntegrationPointKelvinVectorData<DisplacementDim>(
135 values, _ip_data, &IpData::sigma_eff);
136 }
137 if (name == "epsilon_ip")
138 {
139 return ProcessLib::setIntegrationPointKelvinVectorData<DisplacementDim>(
140 values, _ip_data, &IpData::eps);
141 }
142
143 return 0;
144}
145
146template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
147 int DisplacementDim>
149 ShapeFunctionDisplacement, ShapeFunctionPressure, DisplacementDim>::
150 updateConstitutiveRelations(
151 Eigen::Ref<Eigen::VectorXd const> const local_x,
152 Eigen::Ref<Eigen::VectorXd const> const local_x_prev,
153 ParameterLib::SpatialPosition const& x_position, double const t,
154 double const dt, IpData& ip_data,
156{
157 assert(local_x.size() ==
158 pressure_size + displacement_size + temperature_size);
159
160 auto const [T, p, u] = localDOF(local_x);
161 auto const [T_prev, p_prev, u_prev] = localDOF(local_x_prev);
162
163 auto const& solid_material =
165 _process_data.solid_materials, _process_data.material_ids,
166 _element.getID());
167
168 auto const& medium = _process_data.media_map.getMedium(_element.getID());
169 auto const& liquid_phase = medium->phase("AqueousLiquid");
170 auto const& solid_phase = medium->phase("Solid");
171 auto* const frozen_liquid_phase = medium->hasPhase("FrozenLiquid")
172 ? &medium->phase("FrozenLiquid")
173 : nullptr;
175
176 auto const& N_u = ip_data.N_u;
177 auto const& dNdx_u = ip_data.dNdx_u;
178
179 auto const& N = ip_data.N;
180 auto const& dNdx = ip_data.dNdx;
181
182 auto const T_int_pt = N.dot(T);
183 auto const T_prev_int_pt = N.dot(T_prev);
184 double const dT_int_pt = T_int_pt - T_prev_int_pt;
185
186 auto const x_coord =
187 NumLib::interpolateXCoordinate<ShapeFunctionDisplacement,
189 N_u);
190 auto const B =
191 LinearBMatrix::computeBMatrix<DisplacementDim,
192 ShapeFunctionDisplacement::NPOINTS,
194 dNdx_u, N_u, x_coord, _is_axially_symmetric);
195
197
198 auto& eps = ip_data.eps;
199 eps.noalias() = B * u;
200
201 vars.temperature = T_int_pt;
202 double const p_int_pt = N.dot(p);
203 vars.phase_pressure = p_int_pt;
204
205 vars.liquid_saturation = 1.0;
206
207 auto const solid_density =
209 .template value<double>(vars, x_position, t, dt);
210
211 auto const porosity =
213 .template value<double>(vars, x_position, t, dt);
214 vars.porosity = porosity;
215 ip_data.porosity = porosity;
216
217 crv.alpha_biot =
219 .template value<double>(vars, x_position, t, dt);
220 auto const& alpha = crv.alpha_biot;
221
222 auto const C_el = ip_data.computeElasticTangentStiffness(
223 t, x_position, dt, static_cast<double>(T_int_pt));
224 auto const solid_skeleton_compressibility =
225 1 / solid_material.getBulkModulus(t, x_position, &C_el);
226
227 crv.beta_SR = (1 - alpha) * solid_skeleton_compressibility;
228
229 // Set mechanical variables for the intrinsic permeability model
230 // For stress dependent permeability.
231 {
232 auto const& identity2 = Invariants::identity2;
233 auto const sigma_total =
234 (ip_data.sigma_eff - alpha * p_int_pt * identity2).eval();
235 vars.total_stress.emplace<SymmetricTensor>(
237 }
238 // For strain dependent permeability
239 vars.volumetric_strain = Invariants::trace(ip_data.eps);
241 ip_data.material_state_variables->getEquivalentPlasticStrain();
242
243 auto const intrinsic_permeability =
244 MaterialPropertyLib::formEigenTensor<DisplacementDim>(
246 .value(vars, x_position, t, dt));
247
248 auto const fluid_density =
249 liquid_phase.property(MaterialPropertyLib::PropertyType::density)
250 .template value<double>(vars, x_position, t, dt);
251 ip_data_output.fluid_density = fluid_density;
252 vars.density = fluid_density;
253
254 auto const drho_dp =
255 liquid_phase.property(MaterialPropertyLib::PropertyType::density)
256 .template dValue<double>(
258 t, dt);
259
260 crv.fluid_compressibility = 1 / fluid_density * drho_dp;
261
262 double const fluid_volumetric_thermal_expansion_coefficient =
264 liquid_phase, vars, fluid_density, x_position, t, dt);
265
266 // Use the viscosity model to compute the viscosity
267 ip_data_output.viscosity =
269 .template value<double>(vars, x_position, t, dt);
270 crv.K_over_mu = intrinsic_permeability / ip_data_output.viscosity;
271
272 auto const& b = _process_data.specific_body_force;
273
274 // Consider also anisotropic thermal expansion.
275 crv.solid_linear_thermal_expansion_coefficient =
276 MPL::formKelvinVector<DisplacementDim>(
277 solid_phase
278 .property(
280 .value(vars, x_position, t, dt));
281
283 dthermal_strain =
284 crv.solid_linear_thermal_expansion_coefficient * dT_int_pt;
285
286 crv.K_pT_thermal_osmosis =
287 (solid_phase.hasProperty(
289 ? MaterialPropertyLib::formEigenTensor<DisplacementDim>(
290 solid_phase
292 thermal_osmosis_coefficient)
293 .value(vars, x_position, t, dt))
294 : Eigen::MatrixXd::Zero(DisplacementDim, DisplacementDim));
295
296 GlobalDimVectorType const velocity = -crv.K_over_mu * dNdx * p -
297 crv.K_pT_thermal_osmosis * dNdx * T +
298 crv.K_over_mu * fluid_density * b;
299 ip_data_output.velocity = velocity;
300
301 //
302 // displacement equation, displacement part
303 //
304 auto& eps_prev = ip_data.eps_prev;
305 auto& eps_m = ip_data.eps_m;
306 auto& eps_m_prev = ip_data.eps_m_prev;
307 eps_m.noalias() = eps_m_prev + eps - eps_prev - dthermal_strain;
310 eps_m);
311
312 crv.C = ip_data.updateConstitutiveRelation(vars, t, x_position, dt,
313 T_prev_int_pt);
314
315 crv.rho = solid_density * (1 - porosity) + porosity * fluid_density;
316
317 crv.beta =
318 porosity * fluid_volumetric_thermal_expansion_coefficient +
319 (alpha - porosity) *
320 Invariants::trace(crv.solid_linear_thermal_expansion_coefficient);
321
322 //
323 // pressure equation, displacement part.
324 //
325 // Reusing Kup.transpose().
326
327 //
328 // temperature equation, temperature part.
329 //
330 crv.c_f =
331 liquid_phase
333 .template value<double>(vars, x_position, t, dt);
334 crv.effective_thermal_conductivity =
335 MaterialPropertyLib::formEigenTensor<DisplacementDim>(
336 medium
337 ->property(
339 .value(vars, x_position, t, dt));
340
341 // Thermal conductivity is moved outside and zero matrix is passed instead
342 // due to multiplication with fluid's density times specific heat capacity.
343 crv.effective_thermal_conductivity.noalias() +=
344 fluid_density * crv.c_f *
346 _process_data.stabilizer, _element.getID(),
347 GlobalDimMatrixType::Zero(DisplacementDim, DisplacementDim),
348 velocity, 0. /* phi */, 0. /* dispersivity_transversal */,
349 0. /*dispersivity_longitudinal*/);
350
351 double const c_s =
352 solid_phase
354 .template value<double>(vars, x_position, t, dt);
355
356 // Also modified by freezing terms.
357 crv.effective_volumetric_heat_capacity =
358 porosity * fluid_density * crv.c_f +
359 (1.0 - porosity) * solid_density * c_s;
360
361 if (frozen_liquid_phase)
362 {
364 double const phi_fr =
366 .template value<double>(vars, x_position, t, dt);
367 ip_data.phi_fr = phi_fr;
368
369 auto const frozen_liquid_value =
371 {
372 return (*frozen_liquid_phase)[p].template value<double>(
373 vars, x_position, t, dt);
374 };
375
376 double const rho_fr =
378
379 double const c_fr = frozen_liquid_value(
381
382 double const l_fr = frozen_liquid_value(
384
385 double const dphi_fr_dT =
387 .template dValue<double>(
389 x_position, t, dt);
390
391 double const phi_fr_prev = [&]()
392 {
394 vars_prev.temperature = T_prev_int_pt;
396 .template value<double>(vars_prev, x_position, t, dt);
397 }();
398 ip_data.phi_fr_prev = phi_fr_prev;
399
400 // alpha_T^I
402 DisplacementDim> const ice_linear_thermal_expansion_coefficient =
403 MPL::formKelvinVector<DisplacementDim>(
404 frozen_liquid_phase
405 ->property(
407 .value(vars, x_position, t, dt));
408
410 dthermal_strain_ice =
411 ice_linear_thermal_expansion_coefficient * dT_int_pt;
412
413 // alpha_{phi_I} -- linear expansion coeff. due to water-to-ice
414 // transition (phase change), and related phase_change_strain term
416 phase_change_expansion_coefficient =
417 MPL::formKelvinVector<DisplacementDim>(
418 frozen_liquid_phase
420 phase_change_expansivity)
421 .value(vars, x_position, t, dt));
422
424 dphase_change_strain = phase_change_expansion_coefficient *
425 (phi_fr - phi_fr_prev) / porosity;
426
427 // eps0 ia a 'history variable' -- a solid matrix strain accrued
428 // prior to the onset of ice forming
429 auto& eps0 = ip_data.eps0;
430 auto const& eps0_prev = ip_data.eps0_prev;
431
432 // definition of eps_m_ice
433 auto& eps_m_ice = ip_data.eps_m_ice;
434 auto const& eps_m_ice_prev = ip_data.eps_m_ice_prev;
435
436 eps_m_ice.noalias() = eps_m_ice_prev + eps - eps_prev -
437 (eps0 - eps0_prev) - dthermal_strain_ice -
438 dphase_change_strain;
439
440 vars_ice.mechanical_strain
442 eps_m_ice);
443 auto const C_IR = ip_data.updateConstitutiveRelationIce(
444 *_process_data.ice_constitutive_relation, vars_ice, t, x_position,
445 dt, T_prev_int_pt);
446 crv.effective_volumetric_heat_capacity +=
447 -phi_fr * fluid_density * crv.c_f + phi_fr * rho_fr * c_fr -
448 l_fr * rho_fr * dphi_fr_dT;
449
450 // part of dMTT_dT derivative for freezing
451 double const d2phi_fr_dT2 =
453 .template d2Value<double>(
456 dt);
457
458 crv.J_uu_fr = phi_fr * C_IR;
459
460 auto const& sigma_eff_ice = ip_data.sigma_eff_ice;
461 crv.r_u_fr = phi_fr * sigma_eff_ice;
462
463 crv.J_uT_fr = phi_fr * C_IR * ice_linear_thermal_expansion_coefficient;
464
465 crv.J_TT_fr = ((rho_fr * c_fr - fluid_density * crv.c_f) * dphi_fr_dT +
466 l_fr * rho_fr * d2phi_fr_dT2) *
467 dT_int_pt / dt;
468 }
469 return crv;
470}
471
472// Assembles the local Jacobian matrix. So far, the linearisation of HT part is
473// not considered as that in HT process.
474template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
475 int DisplacementDim>
477 ShapeFunctionDisplacement, ShapeFunctionPressure, DisplacementDim>::
478 assembleWithJacobian(double const t, double const dt,
479 std::vector<double> const& local_x,
480 std::vector<double> const& local_x_prev,
481 std::vector<double>& /*local_M_data*/,
482 std::vector<double>& /*local_K_data*/,
483 std::vector<double>& local_rhs_data,
484 std::vector<double>& local_Jac_data)
485{
486 assert(local_x.size() ==
487 pressure_size + displacement_size + temperature_size);
488
489 auto const x =
490 Eigen::Map<Eigen::VectorXd const>(local_x.data(), local_x.size());
491 auto const x_prev = Eigen::Map<Eigen::VectorXd const>(local_x_prev.data(),
492 local_x_prev.size());
493
494 auto const [T, p, u] = localDOF(local_x);
495 auto const [T_prev, p_prev, u_prev] = localDOF(local_x_prev);
496
497 auto local_Jac = MathLib::createZeroedMatrix<
498 typename ShapeMatricesTypeDisplacement::template MatrixType<
499 temperature_size + displacement_size + pressure_size,
500 temperature_size + displacement_size + pressure_size>>(
501 local_Jac_data, displacement_size + pressure_size + temperature_size,
502 displacement_size + pressure_size + temperature_size);
503
504 auto local_rhs = MathLib::createZeroedVector<
505 typename ShapeMatricesTypeDisplacement::template VectorType<
506 displacement_size + pressure_size + temperature_size>>(
507 local_rhs_data, displacement_size + pressure_size + temperature_size);
508
510 MTT.setZero(temperature_size, temperature_size);
511
513 KTT.setZero(temperature_size, temperature_size);
514
516 KTp.setZero(temperature_size, pressure_size);
517
519 dKTT_dp.setZero(temperature_size, pressure_size);
520
522 laplace_p.setZero(pressure_size, pressure_size);
523
525 laplace_T.setZero(pressure_size, temperature_size);
526
528 storage_p.setZero(pressure_size, pressure_size);
529
531 storage_T.setZero(pressure_size, temperature_size);
532
533 typename ShapeMatricesTypeDisplacement::template MatrixType<
534 displacement_size, pressure_size>
535 Kup;
536 Kup.setZero(displacement_size, pressure_size);
537
538 auto const& medium = _process_data.media_map.getMedium(_element.getID());
539 bool const has_frozen_liquid_phase = medium->hasPhase("FrozenLiquid");
540
541 unsigned const n_integration_points =
542 _integration_method.getNumberOfPoints();
543
544 std::vector<GlobalDimVectorType> ip_flux_vector;
545 double average_velocity_norm = 0.0;
546 ip_flux_vector.reserve(n_integration_points);
547
548 for (unsigned ip = 0; ip < n_integration_points; ip++)
549 {
550 auto const& N_u = _ip_data[ip].N_u;
551 ParameterLib::SpatialPosition const x_position{
552 std::nullopt, _element.getID(), ip,
554 NumLib::interpolateCoordinates<ShapeFunctionDisplacement,
556 _element, N_u))};
557
558 auto const crv = updateConstitutiveRelations(
559 x, x_prev, x_position, t, dt, _ip_data[ip], _ip_data_output[ip]);
560
561 auto const& w = _ip_data[ip].integration_weight;
562
563 auto const& dNdx_u = _ip_data[ip].dNdx_u;
564
565 auto const& N = _ip_data[ip].N;
566 auto const& dNdx = _ip_data[ip].dNdx;
567
568 auto const T_int_pt = N.dot(T);
569
570 auto const x_coord =
571 NumLib::interpolateXCoordinate<ShapeFunctionDisplacement,
573 _element, N_u);
574 auto const B =
575 LinearBMatrix::computeBMatrix<DisplacementDim,
576 ShapeFunctionDisplacement::NPOINTS,
578 dNdx_u, N_u, x_coord, _is_axially_symmetric);
579
580 auto const& b = _process_data.specific_body_force;
581 auto const velocity = _ip_data_output[ip].velocity;
582
583 //
584 // displacement equation, displacement part
585 //
586
587 if (has_frozen_liquid_phase)
588 {
589 local_Jac
590 .template block<displacement_size, displacement_size>(
591 displacement_index, displacement_index)
592 .noalias() += B.transpose() * crv.J_uu_fr * B * w;
593
594 local_rhs.template segment<displacement_size>(displacement_index)
595 .noalias() -= B.transpose() * crv.r_u_fr * w;
596
597 local_Jac
598 .template block<displacement_size, temperature_size>(
599 displacement_index, temperature_index)
600 .noalias() -= B.transpose() * crv.J_uT_fr * N * w;
601 }
602
603 local_Jac
604 .template block<displacement_size, displacement_size>(
605 displacement_index, displacement_index)
606 .noalias() += B.transpose() * crv.C * B * w;
607
608 local_Jac
609 .template block<displacement_size, temperature_size>(
610 displacement_index, temperature_index)
611 .noalias() -= B.transpose() * crv.C *
612 crv.solid_linear_thermal_expansion_coefficient * N *
613 w;
614
615 local_rhs.template segment<displacement_size>(displacement_index)
616 .noalias() -= (B.transpose() * _ip_data[ip].sigma_eff -
617 N_u_op(N_u).transpose() * crv.rho * b) *
618 w;
619
620 //
621 // displacement equation, pressure part (K_up)
622 //
623 Kup.noalias() +=
624 B.transpose() * crv.alpha_biot * Invariants::identity2 * N * w;
625
626 //
627 // pressure equation, pressure part (K_pp and M_pp).
628 //
629 laplace_p.noalias() += dNdx.transpose() * crv.K_over_mu * dNdx * w;
630
631 storage_p.noalias() +=
632 N.transpose() *
633 (_ip_data[ip].porosity * crv.fluid_compressibility +
634 (crv.alpha_biot - _ip_data[ip].porosity) * crv.beta_SR) *
635 N * w;
636
637 laplace_T.noalias() +=
638 dNdx.transpose() * crv.K_pT_thermal_osmosis * dNdx * w;
639 //
640 // RHS, pressure part
641 //
642 double const fluid_density = _ip_data_output[ip].fluid_density;
643 local_rhs.template segment<pressure_size>(pressure_index).noalias() +=
644 dNdx.transpose() * fluid_density * crv.K_over_mu * b * w;
645 //
646 // pressure equation, temperature part (M_pT)
647 //
648 storage_T.noalias() += N.transpose() * crv.beta * N * w;
649
650 //
651 // pressure equation, displacement part.
652 //
653 // Reusing Kup.transpose().
654
655 //
656 // temperature equation, temperature part.
657 //
658 KTT.noalias() +=
659 dNdx.transpose() * crv.effective_thermal_conductivity * dNdx * w;
660
661 ip_flux_vector.emplace_back(velocity * fluid_density * crv.c_f);
662 average_velocity_norm += velocity.norm();
663
664 if (has_frozen_liquid_phase)
665 {
666 local_Jac
667 .template block<temperature_size, temperature_size>(
668 temperature_index, temperature_index)
669 .noalias() -= N.transpose() * crv.J_TT_fr * N * w;
670 }
671
672 MTT.noalias() +=
673 N.transpose() * crv.effective_volumetric_heat_capacity * N * w;
674
675 //
676 // temperature equation, pressure part
677 //
678 KTp.noalias() +=
679 dNdx.transpose() * T_int_pt * crv.K_pT_thermal_osmosis * dNdx * w;
680
681 // linearized darcy
682 dKTT_dp.noalias() -= fluid_density * crv.c_f * N.transpose() *
683 (dNdx * T).transpose() * crv.K_over_mu * dNdx * w;
684
685 /* TODO (Joerg) Temperature changes due to thermal dilatation of the
686 * fluid, which are usually discarded as being very small.
687 * Zhou et al. (10.1016/S0020-7683(98)00089-4) states that:
688 * "Biot (1956) neglected this term and it is included here for
689 * completeness"
690 * Keeping the code here in the case these are needed for the named
691 * effects in the future.
692 if (fluid_compressibility != 0)
693 {
694 auto const C_el = _ip_data[ip].computeElasticTangentStiffness(
695 t, x_position, dt, static_cast<double>(T_int_pt));
696 auto const solid_skeleton_compressibility =
697 1 / solid_material.getBulkModulus(t, x_position, &C_el);
698 double const fluid_volumetric_thermal_expansion_coefficient =
699 MaterialPropertyLib::getLiquidThermalExpansivity(
700 liquid_phase, vars, fluid_density, x_position, t, dt);
701
702 KTT.noalias() +=
703 dNdx.transpose() *
704 (-T_int_pt * fluid_volumetric_thermal_expansion_coefficient *
705 K_pT_thermal_osmosis / fluid_compressibility) *
706 dNdx * w;
707
708 local_rhs.template segment<temperature_size>(temperature_index)
709 .noalias() +=
710 dNdx.transpose() *
711 (-T_int_pt * fluid_volumetric_thermal_expansion_coefficient /
712 fluid_compressibility) *
713 fluid_density * K_over_mu * b * w;
714 MTu part for rhs and Jacobian:
715 (-T_int_pt *
716 Invariants::trace(solid_linear_thermal_expansion_coefficient) /
717 solid_skeleton_compressibility) *
718 N.transpose() * identity2.transpose() * B * w;
719 KTp part for rhs and Jacobian:
720 dNdx.transpose() *
721 (T_int_pt * fluid_volumetric_thermal_expansion_coefficient *
722 K_over_mu / fluid_compressibility) *
723 dNdx * w;
724 }
725 */
726 }
727
729 _process_data.stabilizer, _ip_data, ip_flux_vector,
730 average_velocity_norm / static_cast<double>(n_integration_points), KTT);
731
732 // temperature equation, temperature part
733 local_Jac
734 .template block<temperature_size, temperature_size>(temperature_index,
735 temperature_index)
736 .noalias() += KTT + MTT / dt;
737
738 // temperature equation, pressure part
739 local_Jac
740 .template block<temperature_size, pressure_size>(temperature_index,
741 pressure_index)
742 .noalias() += KTp + dKTT_dp;
743
744 // displacement equation, pressure part
745 local_Jac
746 .template block<displacement_size, pressure_size>(displacement_index,
747 pressure_index)
748 .noalias() -= Kup;
749
750 // pressure equation, temperature part.
751 local_Jac
752 .template block<pressure_size, temperature_size>(pressure_index,
753 temperature_index)
754 .noalias() -= storage_T / dt - laplace_T;
755
756 // pressure equation, pressure part.
757 local_Jac
758 .template block<pressure_size, pressure_size>(pressure_index,
759 pressure_index)
760 .noalias() += laplace_p + storage_p / dt;
761
762 // pressure equation, displacement part.
763 local_Jac
764 .template block<pressure_size, displacement_size>(pressure_index,
765 displacement_index)
766 .noalias() += Kup.transpose() / dt;
767
768 // pressure equation (f_p)
769 local_rhs.template segment<pressure_size>(pressure_index).noalias() -=
770 laplace_p * p + laplace_T * T + storage_p * (p - p_prev) / dt -
771 storage_T * (T - T_prev) / dt + Kup.transpose() * (u - u_prev) / dt;
772
773 // displacement equation (f_u)
774 local_rhs.template segment<displacement_size>(displacement_index)
775 .noalias() += Kup * p;
776
777 // temperature equation (f_T)
778 local_rhs.template segment<temperature_size>(temperature_index).noalias() -=
779 KTT * T + MTT * (T - T_prev) / dt;
780
781 local_rhs.template segment<temperature_size>(temperature_index).noalias() -=
782 KTp * p;
783}
784
785template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
786 int DisplacementDim>
787std::vector<double> const& ThermoHydroMechanicsLocalAssembler<
788 ShapeFunctionDisplacement, ShapeFunctionPressure, DisplacementDim>::
789 getIntPtDarcyVelocity(
790 const double /*t*/,
791 std::vector<GlobalVector*> const& /*x*/,
792 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
793 std::vector<double>& cache) const
794{
795 unsigned const n_integration_points =
796 _integration_method.getNumberOfPoints();
797
798 cache.clear();
799 auto cache_matrix = MathLib::createZeroedMatrix<Eigen::Matrix<
800 double, DisplacementDim, Eigen::Dynamic, Eigen::RowMajor>>(
801 cache, DisplacementDim, n_integration_points);
802
803 for (unsigned ip = 0; ip < n_integration_points; ip++)
804 {
805 cache_matrix.col(ip).noalias() = _ip_data_output[ip].velocity;
806 }
807
808 return cache;
809}
810
811template <typename ShapeFunctionDisplacement, typename ShapeFunction,
812 int DisplacementDim>
813std::vector<double> const& ThermoHydroMechanicsLocalAssembler<
814 ShapeFunctionDisplacement, ShapeFunction, DisplacementDim>::
815 getIntPtFluidDensity(
816 const double /*t*/,
817 std::vector<GlobalVector*> const& /*x*/,
818 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
819 std::vector<double>& cache) const
820{
822 _ip_data_output,
824}
825
826template <typename ShapeFunctionDisplacement, typename ShapeFunction,
827 int DisplacementDim>
828std::vector<double> const& ThermoHydroMechanicsLocalAssembler<
829 ShapeFunctionDisplacement, ShapeFunction, DisplacementDim>::
830 getIntPtViscosity(
831 const double /*t*/,
832 std::vector<GlobalVector*> const& /*x*/,
833 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
834 std::vector<double>& cache) const
835{
837 _ip_data_output,
839}
840
841template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
842 int DisplacementDim>
844 ShapeFunctionDisplacement, ShapeFunctionPressure, DisplacementDim>::
845 computeSecondaryVariableConcrete(double const t, double const dt,
846 Eigen::VectorXd const& local_x,
847 Eigen::VectorXd const& local_x_prev)
848{
849 auto const p = local_x.template segment<pressure_size>(pressure_index);
850 auto const T =
851 local_x.template segment<temperature_size>(temperature_index);
852
853 unsigned const n_integration_points =
854 _integration_method.getNumberOfPoints();
855
856 double fluid_density_avg = 0;
857 double viscosity_avg = 0;
858
860 KV sigma_avg = KV::Zero();
861
862 for (unsigned ip = 0; ip < n_integration_points; ip++)
863 {
864 auto& ip_data = _ip_data[ip];
865 auto const& N_u = ip_data.N_u;
866
867 ParameterLib::SpatialPosition const x_position{
868 std::nullopt, _element.getID(), ip,
870 NumLib::interpolateCoordinates<ShapeFunctionDisplacement,
872 _element, N_u))};
873
874 updateConstitutiveRelations(local_x, local_x_prev, x_position, t, dt,
875 _ip_data[ip], _ip_data_output[ip]);
876
877 fluid_density_avg += _ip_data_output[ip].fluid_density;
878 viscosity_avg += _ip_data_output[ip].viscosity;
879 sigma_avg += ip_data.sigma_eff;
880 }
881
882 fluid_density_avg /= n_integration_points;
883 viscosity_avg /= n_integration_points;
884 sigma_avg /= n_integration_points;
885
886 (*_process_data.element_fluid_density)[_element.getID()] =
887 fluid_density_avg;
888 (*_process_data.element_viscosity)[_element.getID()] = viscosity_avg;
889
890 Eigen::Map<KV>(&(*_process_data.element_stresses)[_element.getID() *
891 KV::RowsAtCompileTime]) =
893
895 ShapeFunctionPressure, typename ShapeFunctionDisplacement::MeshElement,
896 DisplacementDim>(_element, _is_axially_symmetric, p,
897 *_process_data.pressure_interpolated);
898
900 ShapeFunctionPressure, typename ShapeFunctionDisplacement::MeshElement,
901 DisplacementDim>(_element, _is_axially_symmetric, T,
902 *_process_data.temperature_interpolated);
903}
904} // namespace ThermoHydroMechanics
905} // namespace ProcessLib
#define OGS_FATAL(...)
Definition: Error.h:26
std::variant< std::monostate, Eigen::Matrix< double, 4, 1 >, Eigen::Matrix< double, 6, 1 > > mechanical_strain
Definition: VariableType.h:182
std::variant< std::monostate, Eigen::Matrix< double, 4, 1 >, Eigen::Matrix< double, 6, 1 > > total_stress
Definition: VariableType.h:201
double getWeight() const
Definition: WeightedPoint.h:80
virtual std::size_t getID() const final
Returns the ID of the element.
Definition: Element.h:89
MathLib::WeightedPoint const & getWeightedPoint(unsigned const igp) const
MatrixType< _kelvin_vector_size, _number_of_dof > BMatrixType
Definition: BMatrixPolicy.h:55
ThermoHydroMechanicsProcessData< DisplacementDim > & _process_data
std::vector< IntegrationPointDataForOutput< DisplacementDim >, Eigen::aligned_allocator< IntegrationPointDataForOutput< DisplacementDim > > > _ip_data_output
ShapeMatrixPolicyType< ShapeFunctionPressure, DisplacementDim > ShapeMatricesTypePressure
SecondaryData< typename ShapeMatricesTypeDisplacement::ShapeMatrices::ShapeType > _secondary_data
std::vector< IpData, Eigen::aligned_allocator< IpData > > _ip_data
typename ShapeMatricesTypePressure::GlobalDimVectorType GlobalDimVectorType
ShapeMatrixPolicyType< ShapeFunctionDisplacement, DisplacementDim > ShapeMatricesTypeDisplacement
auto & selectSolidConstitutiveRelation(SolidMaterialsMap const &constitutive_relations, MeshLib::PropertyVector< int > const *const material_ids, std::size_t const element_id)
double getLiquidThermalExpansivity(Phase const &phase, VariableArray const &vars, const double density, ParameterLib::SpatialPosition const &pos, double const t, double const dt)
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), 1, Eigen::ColMajor > KelvinVectorType
Definition: KelvinVector.h:49
Eigen::Matrix< double, 4, 1 > kelvinVectorToSymmetricTensor(Eigen::Matrix< double, 4, 1, Eigen::ColMajor, 4, 1 > const &v)
Eigen::Map< Vector > createZeroedVector(std::vector< double > &data, Eigen::VectorXd::Index size)
Eigen::Map< Matrix > createZeroedMatrix(std::vector< double > &data, Eigen::MatrixXd::Index rows, Eigen::MatrixXd::Index cols)
Definition: EigenMapTools.h:32
void assembleAdvectionMatrix(IPData const &ip_data_vector, std::vector< FluxVectorType > const &ip_flux_vector, Eigen::MatrixBase< Derived > &laplacian_matrix)
double interpolateXCoordinate(MeshLib::Element const &e, typename ShapeMatricesType::ShapeMatrices::ShapeType const &N)
void interpolateToHigherOrderNodes(MeshLib::Element const &element, bool const is_axially_symmetric, Eigen::MatrixBase< EigenMatrixType > const &node_values, MeshLib::PropertyVector< double > &interpolated_values_global_vector)
std::vector< typename ShapeMatricesType::ShapeMatrices, Eigen::aligned_allocator< typename ShapeMatricesType::ShapeMatrices > > initShapeMatrices(MeshLib::Element const &e, bool const is_axially_symmetric, IntegrationMethod const &integration_method)
Eigen::MatrixXd computeHydrodynamicDispersion(NumericalStabilization const &stabilizer, std::size_t const element_id, Eigen::MatrixXd const &pore_diffusion_coefficient, Eigen::VectorXd const &velocity, double const porosity, double const solute_dispersivity_transverse, double const solute_dispersivity_longitudinal)
std::array< double, 3 > interpolateCoordinates(MeshLib::Element const &e, typename ShapeMatricesType::ShapeMatrices::ShapeType const &N)
BMatrixType computeBMatrix(DNDX_Type const &dNdx, N_Type const &N, const double radius, const bool is_axially_symmetric)
Fills a B-matrix based on given shape function dN/dx values.
Definition: LinearBMatrix.h:42
std::vector< double > const & getIntegrationPointScalarData(IntegrationPointDataVector const &ip_data_vector, MemberType IpData::*const member, std::vector< double > &cache)
void setIPDataInitialConditions(std::vector< std::unique_ptr< MeshLib::IntegrationPointWriter > > const &_integration_point_writer, MeshLib::Properties const &mesh_properties, LocalAssemblersVector &local_assemblers, bool const remove_name_suffix=false)
MatrixType< ShapeFunction::NPOINTS, ShapeFunction::NPOINTS > NodalMatrixType
std::vector< ShapeMatrixType, Eigen::aligned_allocator< ShapeMatrixType > > N_u
BMatricesType::KelvinMatrixType updateConstitutiveRelation(MaterialPropertyLib::VariableArray const &variable_array, double const t, ParameterLib::SpatialPosition const &x_position, double const dt, double const temperature_prev)
MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > computeElasticTangentStiffness(double const t, ParameterLib::SpatialPosition const &x_position, double const dt, double const temperature)
ShapeMatricesTypePressure::GlobalDimNodalMatrixType dNdx
std::unique_ptr< typename MaterialLib::Solids::MechanicsBase< DisplacementDim >::MaterialStateVariables > material_state_variables
ShapeMatrixTypeDisplacement::NodalRowVectorType N_u
BMatricesType::KelvinMatrixType updateConstitutiveRelationIce(MaterialLib::Solids::MechanicsBase< DisplacementDim > const &ice_constitutive_relation, MaterialPropertyLib::VariableArray const &variable_array, double const t, ParameterLib::SpatialPosition const &x_position, double const dt, double const temperature_prev)
ShapeMatricesTypePressure::NodalRowVectorType N
ShapeMatrixTypeDisplacement::GlobalDimNodalMatrixType dNdx_u