OGS
ThermoRichardsFlowFEM-impl.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#pragma once
5
6#include <cassert>
7
22
23namespace ProcessLib
24{
25namespace ThermoRichardsFlow
26{
27template <typename ShapeFunction, int GlobalDim>
30 MeshLib::Element const& e,
31 std::size_t const /*local_matrix_size*/,
32 NumLib::GenericIntegrationMethod const& integration_method,
33 bool const is_axially_symmetric,
35 : _process_data(process_data),
36 _integration_method(integration_method),
37 _element(e),
38 _is_axially_symmetric(is_axially_symmetric)
39{
40 unsigned const n_integration_points =
41 _integration_method.getNumberOfPoints();
42
43 _ip_data.reserve(n_integration_points);
44
45 auto const shape_matrices =
47 e, is_axially_symmetric, _integration_method);
48
49 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
50
51 for (unsigned ip = 0; ip < n_integration_points; ip++)
52 {
53 auto const& sm = shape_matrices[ip];
54 _ip_data.emplace_back();
55 auto& ip_data = _ip_data[ip];
56 _ip_data[ip].integration_weight =
57 _integration_method.getWeightedPoint(ip).getWeight() *
58 sm.integralMeasure * sm.detJ;
59
60 ip_data.N = sm.N;
61 ip_data.dNdx = sm.dNdx;
62
63 ParameterLib::SpatialPosition const x_position{
64 std::nullopt, _element.getID(),
67 _element, sm.N))};
68 // Initial porosity. Could be read from integration point data or mesh.
69 ip_data.porosity = medium[MPL::porosity].template initialValue<double>(
70 x_position,
71 std::numeric_limits<double>::quiet_NaN() /* t independent */);
72 }
73}
74
75template <typename ShapeFunction, int GlobalDim>
77 setIPDataInitialConditions(std::string_view const name,
78 double const* values,
79 int const integration_order)
80{
81 if (integration_order !=
82 static_cast<int>(_integration_method.getIntegrationOrder()))
83 {
85 "Setting integration point initial conditions; The integration "
86 "order of the local assembler for element {:d} is different "
87 "from the integration order in the initial condition.",
88 _element.getID());
89 }
90
91 if (name == "saturation")
92 {
95 }
96 if (name == "porosity")
97 {
100 }
101 return 0;
102}
103
104template <typename ShapeFunction, int GlobalDim>
106 setInitialConditionsConcrete(Eigen::VectorXd const local_x,
107 double const t,
108 int const /*process_id*/)
109{
110 assert(local_x.size() == temperature_size + pressure_size);
111
112 auto const p_L = local_x.template segment<pressure_size>(pressure_index);
113
114 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
115 MPL::VariableArray variables;
116
117 unsigned const n_integration_points =
118 _integration_method.getNumberOfPoints();
119 for (unsigned ip = 0; ip < n_integration_points; ip++)
120 {
121 auto const& N = _ip_data[ip].N;
122
123 ParameterLib::SpatialPosition const x_position{
124 std::nullopt, _element.getID(),
127 _element, N))};
128
129 double p_cap_ip;
130 NumLib::shapeFunctionInterpolate(-p_L, N, p_cap_ip);
131
132 variables.capillary_pressure = p_cap_ip;
133 variables.liquid_phase_pressure = -p_cap_ip;
134 // setting pG to 1 atm
135 // TODO : rewrite equations s.t. p_L = pG-p_cap
136 variables.gas_phase_pressure = 1.0e5;
137
138 // Note: temperature dependent saturation model is not considered so
139 // far.
140 _ip_data[ip].saturation_prev =
141 medium[MPL::PropertyType::saturation].template value<double>(
142 variables, x_position, t,
143 std::numeric_limits<double>::quiet_NaN());
144 }
145}
146
147template <typename ShapeFunction, int GlobalDim>
149 assembleWithJacobian(double const t, double const dt,
150 std::vector<double> const& local_x,
151 std::vector<double> const& local_x_prev,
152 std::vector<double>& local_rhs_data,
153 std::vector<double>& local_Jac_data)
154{
155 auto const local_matrix_dim = pressure_size + temperature_size;
156 assert(local_x.size() == local_matrix_dim);
157
158 auto const T = Eigen::Map<typename ShapeMatricesType::template VectorType<
159 temperature_size> const>(local_x.data() + temperature_index,
161 auto const p_L = Eigen::Map<
162 typename ShapeMatricesType::template VectorType<pressure_size> const>(
163 local_x.data() + pressure_index, pressure_size);
164
165 auto const T_prev =
166 Eigen::Map<typename ShapeMatricesType::template VectorType<
167 temperature_size> const>(local_x_prev.data() + temperature_index,
169 auto const p_L_prev = Eigen::Map<
170 typename ShapeMatricesType::template VectorType<pressure_size> const>(
171 local_x_prev.data() + pressure_index, pressure_size);
172
173 auto local_Jac = MathLib::createZeroedMatrix<
174 typename ShapeMatricesType::template MatrixType<local_matrix_dim,
175 local_matrix_dim>>(
176 local_Jac_data, local_matrix_dim, local_matrix_dim);
177
178 auto local_rhs = MathLib::createZeroedVector<
179 typename ShapeMatricesType::template VectorType<local_matrix_dim>>(
180 local_rhs_data, local_matrix_dim);
181
183 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
186 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
189 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
192 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
194 typename ShapeMatricesType::NodalMatrixType dK_TT_dp =
195 ShapeMatricesType::NodalMatrixType::Zero(temperature_size,
198 ShapeMatricesType::NodalMatrixType::Zero(pressure_size,
200 typename ShapeMatricesType::NodalMatrixType laplace_p =
201 ShapeMatricesType::NodalMatrixType::Zero(pressure_size, pressure_size);
202 typename ShapeMatricesType::NodalMatrixType laplace_T =
203 ShapeMatricesType::NodalMatrixType::Zero(pressure_size,
205 typename ShapeMatricesType::NodalMatrixType storage_p_a_p =
206 ShapeMatricesType::NodalMatrixType::Zero(pressure_size, pressure_size);
207
208 typename ShapeMatricesType::NodalMatrixType storage_p_a_S_Jpp =
209 ShapeMatricesType::NodalMatrixType::Zero(pressure_size, pressure_size);
210
211 typename ShapeMatricesType::NodalMatrixType storage_p_a_S =
212 ShapeMatricesType::NodalMatrixType::Zero(pressure_size, pressure_size);
213
214 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
215 auto const& liquid_phase = medium.phase("AqueousLiquid");
216 auto const& solid_phase = medium.phase("Solid");
217 MPL::Phase const* gas_phase =
218 medium.hasPhase("Gas") ? &medium.phase("Gas") : nullptr;
219 MPL::VariableArray variables;
220 MPL::VariableArray variables_prev;
221
222 unsigned const n_integration_points =
223 _integration_method.getNumberOfPoints();
224 for (unsigned ip = 0; ip < n_integration_points; ip++)
225 {
226 auto const& w = _ip_data[ip].integration_weight;
227
228 auto const& N = _ip_data[ip].N;
229 auto const& dNdx = _ip_data[ip].dNdx;
230
231 ParameterLib::SpatialPosition const x_position{
232 std::nullopt, _element.getID(),
235 _element, N))};
236
237 double T_ip;
239
240 double p_cap_ip;
241 NumLib::shapeFunctionInterpolate(-p_L, N, p_cap_ip);
242
243 double p_cap_prev_ip;
244 NumLib::shapeFunctionInterpolate(-p_L_prev, N, p_cap_prev_ip);
245
246 variables.capillary_pressure = p_cap_ip;
247 variables.liquid_phase_pressure = -p_cap_ip;
248 // setting pG to 1 atm
249 // TODO : rewrite equations s.t. p_L = pG-p_cap
250 variables.gas_phase_pressure = 1.0e5;
251 variables.temperature = T_ip;
252
253 auto& S_L = _ip_data[ip].saturation;
254 auto const S_L_prev = _ip_data[ip].saturation_prev;
255 auto const alpha =
256 medium[MPL::PropertyType::biot_coefficient].template value<double>(
257 variables, x_position, t, dt);
258
259 auto& solid_elasticity = *_process_data.simplified_elasticity;
260 // TODO (buchwaldj)
261 // is bulk_modulus good name for bulk modulus of solid skeleton?
262 auto const beta_S =
263 solid_elasticity.bulkCompressibilityFromYoungsModulus(
264 solid_phase, variables, x_position, t, dt);
265 auto const beta_SR = (1 - alpha) * beta_S;
266 variables.grain_compressibility = beta_SR;
267
268 auto const rho_LR =
269 liquid_phase[MPL::PropertyType::density].template value<double>(
270 variables, x_position, t, dt);
271 variables.density = rho_LR;
272 auto const& b = _process_data.specific_body_force;
273
274 double const drho_LR_dp =
275 liquid_phase[MPL::PropertyType::density].template dValue<double>(
276 variables, MPL::Variable::liquid_phase_pressure, x_position, t,
277 dt);
278 auto const beta_LR = drho_LR_dp / rho_LR;
279
280 S_L = medium[MPL::PropertyType::saturation].template value<double>(
281 variables, x_position, t, dt);
282 variables.liquid_saturation = S_L;
283 variables_prev.liquid_saturation = S_L_prev;
284
285 // tangent derivative for Jacobian
286 double const dS_L_dp_cap =
287 medium[MPL::PropertyType::saturation].template dValue<double>(
288 variables, MPL::Variable::capillary_pressure, x_position, t,
289 dt);
290 // secant derivative from time discretization for storage
291 // use tangent, if secant is not available
292 double const DeltaS_L_Deltap_cap =
293 (p_cap_ip == p_cap_prev_ip)
294 ? dS_L_dp_cap
295 : (S_L - S_L_prev) / (p_cap_ip - p_cap_prev_ip);
296
297 auto chi_S_L = S_L;
298 auto chi_S_L_prev = S_L_prev;
299 auto dchi_dS_L = 1.0;
300 if (medium.hasProperty(MPL::PropertyType::bishops_effective_stress))
301 {
302 auto const chi = [&medium, x_position, t, dt](double const S_L)
303 {
304 MPL::VariableArray variables;
305 variables.liquid_saturation = S_L;
307 .template value<double>(variables, x_position, t, dt);
308 };
309 chi_S_L = chi(S_L);
310 chi_S_L_prev = chi(S_L_prev);
311
313 .template dValue<double>(
315 x_position, t, dt);
316 }
317 // TODO (buchwaldj)
318 // should solid_grain_pressure or effective_pore_pressure remain?
319 // double const p_FR = -chi_S_L * p_cap_ip;
320 // variables.solid_grain_pressure = p_FR;
321
322 variables.effective_pore_pressure = -chi_S_L * p_cap_ip;
323 variables_prev.effective_pore_pressure = -chi_S_L_prev * p_cap_prev_ip;
324
325 auto& phi = _ip_data[ip].porosity;
326 { // Porosity update
327
328 variables_prev.porosity = _ip_data[ip].porosity_prev;
329 phi = medium[MPL::PropertyType::porosity].template value<double>(
330 variables, variables_prev, x_position, t, dt);
331 variables.porosity = phi;
332 }
333
334 if (alpha < phi)
335 {
336 OGS_FATAL(
337 "ThermoRichardsFlow: Biot-coefficient {} is smaller than "
338 "porosity {} in element/integration point {}/{}.",
339 alpha, phi, _element.getID(), ip);
340 }
341
342 double const k_rel =
344 .template value<double>(variables, x_position, t, dt);
345 auto const mu =
346 liquid_phase[MPL::PropertyType::viscosity].template value<double>(
347 variables, x_position, t, dt);
348
349 auto const K_intrinsic = MPL::formEigenTensor<GlobalDim>(
350 medium[MPL::PropertyType::permeability].value(variables, x_position,
351 t, dt));
352
353 GlobalDimMatrixType const Ki_over_mu = K_intrinsic / mu;
354 GlobalDimMatrixType const rho_Ki_over_mu = rho_LR * Ki_over_mu;
355
356 auto const K_pT_thermal_osmosis =
357 (solid_phase.hasProperty(
360 solid_phase
362 .value(variables, x_position, t, dt))
363 : Eigen::MatrixXd::Zero(GlobalDim, GlobalDim));
364
365 // Consider anisotropic thermal expansion.
366 // Read in 3x3 tensor. 2D case also requires expansion coeff. for z-
367 // component.
368 Eigen::Matrix<double, 3, 3> const
369 solid_linear_thermal_expansion_coefficient =
371 solid_phase
373 .value(variables, x_position, t, dt));
374
375 auto const rho_SR =
376 solid_phase[MPL::PropertyType::density].template value<double>(
377 variables, x_position, t, dt);
378
379 //
380 // pressure equation, pressure part.
381 //
382 laplace_p.noalias() +=
383 dNdx.transpose() * k_rel * rho_Ki_over_mu * dNdx * w;
384 laplace_T.noalias() +=
385 dNdx.transpose() * rho_LR * K_pT_thermal_osmosis * dNdx * w;
386 const double alphaB_minus_phi = alpha - phi;
387 double const a0 = alphaB_minus_phi * beta_SR;
388 double const specific_storage_a_p =
389 S_L * (phi * beta_LR + S_L * a0 +
390 chi_S_L * alpha * alpha *
391 solid_elasticity.storageContribution(
392 solid_phase, variables, x_position, t, dt));
393 double const specific_storage_a_S = phi - p_cap_ip * S_L * a0;
394
395 double const dspecific_storage_a_p_dp_cap =
396 dS_L_dp_cap * (phi * beta_LR + 2 * S_L * a0 +
397 alpha * alpha *
398 solid_elasticity.storageContribution(
399 solid_phase, variables, x_position, t, dt) *
400 (chi_S_L + dchi_dS_L * S_L));
401 double const dspecific_storage_a_S_dp_cap =
402 -a0 * (S_L + p_cap_ip * dS_L_dp_cap);
403
404 storage_p_a_p.noalias() +=
405 N.transpose() * rho_LR * specific_storage_a_p * N * w;
406
407 storage_p_a_S.noalias() -= N.transpose() * rho_LR *
408 specific_storage_a_S * DeltaS_L_Deltap_cap *
409 N * w;
410
411 local_Jac
412 .template block<pressure_size, pressure_size>(pressure_index,
414 .noalias() += N.transpose() * (p_cap_ip - p_cap_prev_ip) / dt *
415 rho_LR * dspecific_storage_a_p_dp_cap * N * w;
416
417 storage_p_a_S_Jpp.noalias() -=
418 N.transpose() * rho_LR *
419 ((S_L - S_L_prev) * dspecific_storage_a_S_dp_cap +
420 specific_storage_a_S * dS_L_dp_cap) /
421 dt * N * w;
422
423 double const dk_rel_dS_L =
425 .template dValue<double>(variables,
427 x_position, t, dt);
428 GlobalDimVectorType const grad_p_cap = -dNdx * p_L;
429 local_Jac
430 .template block<pressure_size, pressure_size>(pressure_index,
432 .noalias() += dNdx.transpose() * rho_Ki_over_mu * grad_p_cap *
433 dk_rel_dS_L * dS_L_dp_cap * N * w;
434
435 local_Jac
436 .template block<pressure_size, pressure_size>(pressure_index,
438 .noalias() += dNdx.transpose() * rho_LR * rho_Ki_over_mu * b *
439 dk_rel_dS_L * dS_L_dp_cap * N * w;
440
441 local_rhs.template segment<pressure_size>(pressure_index).noalias() +=
442 dNdx.transpose() * rho_LR * k_rel * rho_Ki_over_mu * b * w;
443
444 //
445 // pressure equation, temperature part.
446 //
447 double const fluid_volumetric_thermal_expansion_coefficient =
448 MPL::getLiquidThermalExpansivity(liquid_phase, variables, rho_LR,
449 x_position, t, dt);
450 const double eff_thermal_expansion =
451 S_L * (alphaB_minus_phi *
452 solid_linear_thermal_expansion_coefficient.trace() +
453 phi * fluid_volumetric_thermal_expansion_coefficient +
454 alpha * solid_elasticity.thermalExpansivityContribution(
455 solid_linear_thermal_expansion_coefficient,
456 solid_phase, variables, x_position, t, dt));
457 M_pT.noalias() -=
458 N.transpose() * rho_LR * eff_thermal_expansion * N * w;
459
460 //
461 // temperature equation.
462 //
463 {
464 auto const specific_heat_capacity_fluid =
466 .template value<double>(variables, x_position, t, dt);
467
468 auto const specific_heat_capacity_solid =
469 solid_phase
471 .template value<double>(variables, x_position, t, dt);
472
473 M_TT.noalias() +=
474 w *
475 (rho_SR * specific_heat_capacity_solid * (1 - phi) +
476 (S_L * rho_LR * specific_heat_capacity_fluid) * phi) *
477 N.transpose() * N;
478
479 auto const thermal_conductivity =
482 thermal_conductivity]
483 .value(variables, x_position, t, dt));
484
485 GlobalDimVectorType const velocity_L = GlobalDimVectorType(
486 -Ki_over_mu * k_rel * (dNdx * p_L - rho_LR * b) -
487 K_pT_thermal_osmosis * dNdx * T);
488
489 K_TT.noalias() += (dNdx.transpose() * thermal_conductivity * dNdx +
490 N.transpose() * velocity_L.transpose() * dNdx *
491 rho_LR * specific_heat_capacity_fluid) *
492 w;
493
494 //
495 // temperature equation, pressure part
496 //
497 K_Tp.noalias() +=
498 dNdx.transpose() * T_ip * K_pT_thermal_osmosis * dNdx * w;
499 dK_TT_dp.noalias() -= rho_LR * specific_heat_capacity_fluid *
500 N.transpose() * (dNdx * T).transpose() *
501 k_rel * Ki_over_mu * dNdx * w;
502
503 dK_TT_dp.noalias() -= rho_LR * specific_heat_capacity_fluid *
504 N.transpose() * velocity_L.dot(dNdx * T) /
505 k_rel * dk_rel_dS_L * dS_L_dp_cap * N * w;
506 }
507 if (gas_phase && S_L < 1.0)
508 {
509 variables.density = rho_LR;
510
511 double const rho_wv =
513 .template value<double>(variables, x_position, t, dt);
514
515 double const drho_wv_dT =
517 .template dValue<double>(variables,
519 x_position, t, dt);
520 double const drho_wv_dp =
522 .template dValue<double>(
524 x_position, t, dt);
525 auto const f_Tv =
526 gas_phase
527 ->property(
529 .template value<double>(variables, x_position, t, dt);
530
531 variables.porosity = phi;
532 auto const tortuosity =
533 medium.property(MPL::PropertyType::tortuosity)
534 .template value<double>(variables, x_position, t, dt);
535 double const D_v =
536 phi * (1.0 - S_L) * tortuosity *
538 .template value<double>(variables, x_position, t, dt);
539
540 double const f_Tv_D_Tv = f_Tv * D_v * drho_wv_dT;
541 double const D_pv = D_v * drho_wv_dp;
542
543 GlobalDimVectorType const grad_T = dNdx * T;
544 GlobalDimVectorType const vapour_flux =
545 -(f_Tv_D_Tv * grad_T - D_pv * grad_p_cap);
546 double const specific_heat_capacity_vapour =
548 .template value<double>(variables, x_position, t, dt);
549
550 M_TT.noalias() +=
551 w * (rho_wv * specific_heat_capacity_vapour * (1 - S_L) * phi) *
552 N.transpose() * N;
553
554 K_TT.noalias() += N.transpose() * vapour_flux.transpose() * dNdx *
555 specific_heat_capacity_vapour * w;
556
557 double const storage_coefficient_by_water_vapor =
558 phi * (rho_wv * dS_L_dp_cap + (1 - S_L) * drho_wv_dp);
559
560 storage_p_a_p.noalias() +=
561 N.transpose() * storage_coefficient_by_water_vapor * N * w;
562
563 double const vapor_expansion_factor = phi * (1 - S_L) * drho_wv_dT;
564 M_pT.noalias() += N.transpose() * vapor_expansion_factor * N * w;
565
566 local_Jac
567 .template block<pressure_size, temperature_size>(
569 .noalias() += dNdx.transpose() * f_Tv_D_Tv * dNdx * w;
570
571 local_rhs.template segment<pressure_size>(pressure_index)
572 .noalias() -= f_Tv_D_Tv * dNdx.transpose() * (dNdx * T) * w;
573
574 laplace_p.noalias() += dNdx.transpose() * D_pv * dNdx * w;
575
576 //
577 // Latent heat term
578 //
580 {
581 double const factor = phi * (1 - S_L) / rho_LR;
582 // The volumetric latent heat of vaporization of liquid water
583 double const L0 =
585 .template value<double>(variables, x_position, t, dt) *
586 rho_LR;
587
588 double const drho_LR_dT =
589 liquid_phase.property(MPL::PropertyType::density)
590 .template dValue<double>(variables,
592 x_position, t, dt);
593
594 double const rho_wv_over_rho_L = rho_wv / rho_LR;
595 M_TT.noalias() +=
596 factor * L0 *
597 (drho_wv_dT - rho_wv_over_rho_L * drho_LR_dT) *
598 N.transpose() * N * w;
599
600 M_Tp.noalias() +=
601 (factor * L0 *
602 (drho_wv_dp - rho_wv_over_rho_L * drho_LR_dp) +
603 L0 * phi * rho_wv_over_rho_L * dS_L_dp_cap) *
604 N.transpose() * N * w;
605
606 // temperature equation, temperature part
607 K_TT.noalias() +=
608 L0 * f_Tv_D_Tv * dNdx.transpose() * dNdx * w / rho_LR;
609 // temperature equation, pressure part
610 K_Tp.noalias() +=
611 L0 * D_pv * dNdx.transpose() * dNdx * w / rho_LR;
612 }
613 }
614 }
615
616 if (_process_data.apply_mass_lumping)
617 {
618 storage_p_a_p = storage_p_a_p.colwise().sum().eval().asDiagonal();
619 storage_p_a_S = storage_p_a_S.colwise().sum().eval().asDiagonal();
620 storage_p_a_S_Jpp =
621 storage_p_a_S_Jpp.colwise().sum().eval().asDiagonal();
622 }
623
624 //
625 // -- Jacobian
626 //
627 // temperature equation.
628 local_Jac
629 .template block<temperature_size, temperature_size>(temperature_index,
631 .noalias() += M_TT / dt + K_TT;
632 // temperature equation, pressure part
633 local_Jac
634 .template block<temperature_size, pressure_size>(temperature_index,
636 .noalias() += K_Tp + dK_TT_dp;
637
638 // pressure equation, pressure part.
639 local_Jac
640 .template block<pressure_size, pressure_size>(pressure_index,
642 .noalias() += laplace_p + storage_p_a_p / dt + storage_p_a_S_Jpp;
643
644 // pressure equation, temperature part (contributed by thermal expansion).
645 local_Jac
646 .template block<pressure_size, temperature_size>(pressure_index,
648 .noalias() += M_pT / dt + laplace_T;
649
650 //
651 // -- Residual
652 //
653 // temperature equation
654 local_rhs.template segment<temperature_size>(temperature_index).noalias() -=
655 M_TT * (T - T_prev) / dt + K_TT * T;
656 local_rhs.template segment<temperature_size>(temperature_index).noalias() -=
657 K_Tp * p_L;
658
659 // pressure equation
660 local_rhs.template segment<pressure_size>(pressure_index).noalias() -=
661 laplace_p * p_L + laplace_T * T +
662 (storage_p_a_p + storage_p_a_S) * (p_L - p_L_prev) / dt +
663 M_pT * (T - T_prev) / dt;
664 if (gas_phase)
665 {
667 {
668 // Jacobian: temperature equation, pressure part
669 local_Jac
670 .template block<temperature_size, pressure_size>(
672 .noalias() += M_Tp / dt;
673 // RHS: temperature part
674 local_rhs.template segment<temperature_size>(temperature_index)
675 .noalias() -= M_Tp * (p_L - p_L_prev) / dt;
676 }
677 }
678}
679
680template <typename ShapeFunction, int GlobalDim>
682 double const t, double const dt, std::vector<double> const& local_x,
683 std::vector<double> const& local_x_prev, std::vector<double>& local_M_data,
684 std::vector<double>& local_K_data, std::vector<double>& local_rhs_data)
685{
686 auto const local_matrix_dim = pressure_size + temperature_size;
687 assert(local_x.size() == local_matrix_dim);
688
689 auto const T = Eigen::Map<typename ShapeMatricesType::template VectorType<
690 temperature_size> const>(local_x.data() + temperature_index,
692 auto const p_L = Eigen::Map<
693 typename ShapeMatricesType::template VectorType<pressure_size> const>(
694 local_x.data() + pressure_index, pressure_size);
695
696 auto const p_L_prev = Eigen::Map<
697 typename ShapeMatricesType::template VectorType<pressure_size> const>(
698 local_x_prev.data() + pressure_index, pressure_size);
699
700 auto local_K = MathLib::createZeroedMatrix<
701 typename ShapeMatricesType::template MatrixType<local_matrix_dim,
702 local_matrix_dim>>(
703 local_K_data, local_matrix_dim, local_matrix_dim);
704
705 auto local_M = MathLib::createZeroedMatrix<
706 typename ShapeMatricesType::template MatrixType<local_matrix_dim,
707 local_matrix_dim>>(
708 local_M_data, local_matrix_dim, local_matrix_dim);
709
710 auto local_rhs = MathLib::createZeroedVector<
711 typename ShapeMatricesType::template VectorType<local_matrix_dim>>(
712 local_rhs_data, local_matrix_dim);
713
714 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
715 auto const& liquid_phase = medium.phase("AqueousLiquid");
716 auto const& solid_phase = medium.phase("Solid");
717 MPL::Phase const* gas_phase =
718 medium.hasPhase("Gas") ? &medium.phase("Gas") : nullptr;
719 MPL::VariableArray variables;
720 MPL::VariableArray variables_prev;
721
722 unsigned const n_integration_points =
723 _integration_method.getNumberOfPoints();
724 for (unsigned ip = 0; ip < n_integration_points; ip++)
725 {
726 auto const& w = _ip_data[ip].integration_weight;
727
728 auto const& N = _ip_data[ip].N;
729 auto const& dNdx = _ip_data[ip].dNdx;
730
731 ParameterLib::SpatialPosition const x_position{
732 std::nullopt, _element.getID(),
735 _element, N))};
736
737 double T_ip;
739
740 double p_cap_ip;
741 NumLib::shapeFunctionInterpolate(-p_L, N, p_cap_ip);
742
743 double p_cap_prev_ip;
744 NumLib::shapeFunctionInterpolate(-p_L_prev, N, p_cap_prev_ip);
745
746 variables.capillary_pressure = p_cap_ip;
747 variables.liquid_phase_pressure = -p_cap_ip;
748 // setting pG to 1 atm
749 // TODO : rewrite equations s.t. p_L = pG-p_cap
750 variables.gas_phase_pressure = 1.0e5;
751 variables.temperature = T_ip;
752
753 auto& S_L = _ip_data[ip].saturation;
754 auto const S_L_prev = _ip_data[ip].saturation_prev;
755 auto const alpha =
756 medium[MPL::PropertyType::biot_coefficient].template value<double>(
757 variables, x_position, t, dt);
758
759 auto& solid_elasticity = *_process_data.simplified_elasticity;
760 // TODO (buchwaldj)
761 // is bulk_modulus good name for bulk modulus of solid skeleton?
762 auto const beta_S =
763 solid_elasticity.bulkCompressibilityFromYoungsModulus(
764 solid_phase, variables, x_position, t, dt);
765 auto const beta_SR = (1 - alpha) * beta_S;
766 variables.grain_compressibility = beta_SR;
767
768 auto const rho_LR =
769 liquid_phase[MPL::PropertyType::density].template value<double>(
770 variables, x_position, t, dt);
771 auto const& b = _process_data.specific_body_force;
772
773 double const drho_LR_dp =
774 liquid_phase[MPL::PropertyType::density].template dValue<double>(
775 variables, MPL::Variable::liquid_phase_pressure, x_position, t,
776 dt);
777 auto const beta_LR = drho_LR_dp / rho_LR;
778
779 S_L = medium[MPL::PropertyType::saturation].template value<double>(
780 variables, x_position, t, dt);
781 variables.liquid_saturation = S_L;
782 variables_prev.liquid_saturation = S_L_prev;
783
784 // tangent derivative for Jacobian
785 double const dS_L_dp_cap =
786 medium[MPL::PropertyType::saturation].template dValue<double>(
787 variables, MPL::Variable::capillary_pressure, x_position, t,
788 dt);
789 // secant derivative from time discretization for storage
790 // use tangent, if secant is not available
791 double const DeltaS_L_Deltap_cap =
792 (p_cap_ip == p_cap_prev_ip)
793 ? dS_L_dp_cap
794 : (S_L - S_L_prev) / (p_cap_ip - p_cap_prev_ip);
795
796 auto chi_S_L = S_L;
797 auto chi_S_L_prev = S_L_prev;
798 if (medium.hasProperty(MPL::PropertyType::bishops_effective_stress))
799 {
800 auto const chi = [&medium, x_position, t, dt](double const S_L)
801 {
802 MPL::VariableArray variables;
803 variables.liquid_saturation = S_L;
805 .template value<double>(variables, x_position, t, dt);
806 };
807 chi_S_L = chi(S_L);
808 chi_S_L_prev = chi(S_L_prev);
809 }
810 // TODO (buchwaldj)
811 // should solid_grain_pressure or effective_pore_pressure remain?
812 // double const p_FR = -chi_S_L * p_cap_ip;
813 // variables.solid_grain_pressure = p_FR;
814
815 variables.effective_pore_pressure = -chi_S_L * p_cap_ip;
816 variables_prev.effective_pore_pressure = -chi_S_L_prev * p_cap_prev_ip;
817
818 auto& phi = _ip_data[ip].porosity;
819 { // Porosity update
820
821 variables_prev.porosity = _ip_data[ip].porosity_prev;
822 phi = medium[MPL::PropertyType::porosity].template value<double>(
823 variables, variables_prev, x_position, t, dt);
824 variables.porosity = phi;
825 }
826
827 if (alpha < phi)
828 {
829 OGS_FATAL(
830 "ThermoRichardsFlow: Biot-coefficient {} is smaller than "
831 "porosity {} in element/integration point {}/{}.",
832 alpha, phi, _element.getID(), ip);
833 }
834
835 auto const K_pT_thermal_osmosis =
836 (solid_phase.hasProperty(
839 solid_phase
841 .value(variables, x_position, t, dt))
842 : Eigen::MatrixXd::Zero(GlobalDim, GlobalDim));
843
844 double const k_rel =
846 .template value<double>(variables, x_position, t, dt);
847 auto const mu =
848 liquid_phase[MPL::PropertyType::viscosity].template value<double>(
849 variables, x_position, t, dt);
850
851 auto const K_intrinsic = MPL::formEigenTensor<GlobalDim>(
852 medium[MPL::PropertyType::permeability].value(variables, x_position,
853 t, dt));
854
855 GlobalDimMatrixType const Ki_over_mu = K_intrinsic / mu;
856 GlobalDimMatrixType const rho_Ki_over_mu = rho_LR * Ki_over_mu;
857
858 // Consider anisotropic thermal expansion.
859 // Read in 3x3 tensor. 2D case also requires expansion coeff. for z-
860 // component.
861 Eigen::Matrix<double, 3, 3> const
862 solid_linear_thermal_expansion_coefficient =
864 solid_phase
866 .value(variables, x_position, t, dt));
867
868 auto const rho_SR =
869 solid_phase[MPL::PropertyType::density].template value<double>(
870 variables, x_position, t, dt);
871
872 //
873 // pressure equation, pressure part.
874 //
875 local_K
876 .template block<pressure_size, pressure_size>(pressure_index,
878 .noalias() += dNdx.transpose() * k_rel * rho_Ki_over_mu * dNdx * w;
879
880 const double alphaB_minus_phi = alpha - phi;
881 double const a0 = alphaB_minus_phi * beta_SR;
882 double const specific_storage_a_p =
883 S_L * (phi * beta_LR + S_L * a0 +
884 chi_S_L * alpha * alpha *
885 solid_elasticity.storageContribution(
886 solid_phase, variables, x_position, t, dt));
887 double const specific_storage_a_S = phi - p_cap_ip * S_L * a0;
888
889 local_M
890 .template block<pressure_size, pressure_size>(pressure_index,
892 .noalias() += N.transpose() * rho_LR *
893 (specific_storage_a_p -
894 specific_storage_a_S * DeltaS_L_Deltap_cap) *
895 N * w;
896
897 local_rhs.template segment<pressure_size>(pressure_index).noalias() +=
898 dNdx.transpose() * rho_LR * k_rel * rho_Ki_over_mu * b * w;
899
900 //
901 // pressure equation, temperature part.
902 //
903 double const fluid_volumetric_thermal_expansion_coefficient =
904 MPL::getLiquidThermalExpansivity(liquid_phase, variables, rho_LR,
905 x_position, t, dt);
906 const double eff_thermal_expansion =
907 S_L * (alphaB_minus_phi *
908 solid_linear_thermal_expansion_coefficient.trace() +
909 phi * fluid_volumetric_thermal_expansion_coefficient +
910 alpha * solid_elasticity.thermalExpansivityContribution(
911 solid_linear_thermal_expansion_coefficient,
912 solid_phase, variables, x_position, t, dt));
913
914 local_K
915 .template block<pressure_size, temperature_size>(pressure_index,
917 .noalias() +=
918 dNdx.transpose() * rho_LR * K_pT_thermal_osmosis * dNdx * w;
919
920 local_M
921 .template block<pressure_size, temperature_size>(pressure_index,
923 .noalias() -=
924 N.transpose() * rho_LR * eff_thermal_expansion * N * w;
925
926 //
927 // temperature equation.
928 //
929 {
930 auto const specific_heat_capacity_fluid =
932 .template value<double>(variables, x_position, t, dt);
933
934 auto const specific_heat_capacity_solid =
935 solid_phase
937 .template value<double>(variables, x_position, t, dt);
938
939 local_M
940 .template block<temperature_size, temperature_size>(
942 .noalias() +=
943 w *
944 (rho_SR * specific_heat_capacity_solid * (1 - phi) +
945 (S_L * rho_LR * specific_heat_capacity_fluid) * phi) *
946 N.transpose() * N;
947
948 auto const thermal_conductivity =
951 thermal_conductivity]
952 .value(variables, x_position, t, dt));
953
954 GlobalDimVectorType const velocity_L = GlobalDimVectorType(
955 -Ki_over_mu * k_rel * (dNdx * p_L - rho_LR * b) -
956 K_pT_thermal_osmosis * dNdx * T);
957
958 local_K
959 .template block<temperature_size, temperature_size>(
961 .noalias() += (dNdx.transpose() * thermal_conductivity * dNdx +
962 N.transpose() * velocity_L.transpose() * dNdx *
963 rho_LR * specific_heat_capacity_fluid) *
964 w;
965 local_K
966 .template block<temperature_size, pressure_size>(
968 .noalias() +=
969 dNdx.transpose() * T_ip * K_pT_thermal_osmosis * dNdx * w;
970 }
971 if (gas_phase && S_L < 1.0)
972 {
973 variables.density = rho_LR;
974
975 double const rho_wv =
977 .template value<double>(variables, x_position, t, dt);
978
979 double const drho_wv_dT =
981 .template dValue<double>(variables,
983 x_position, t, dt);
984 double const drho_wv_dp =
986 .template dValue<double>(
988 x_position, t, dt);
989 auto const f_Tv =
990 gas_phase
991 ->property(
993 .template value<double>(variables, x_position, t, dt);
994
995 variables.porosity = phi;
996 auto const tortuosity =
997 medium.property(MPL::PropertyType::tortuosity)
998 .template value<double>(variables, x_position, t, dt);
999 double const D_v =
1000 phi * (1.0 - S_L) * tortuosity *
1002 .template value<double>(variables, x_position, t, dt);
1003
1004 double const f_Tv_D_Tv = f_Tv * D_v * drho_wv_dT;
1005 double const D_pv = D_v * drho_wv_dp;
1006
1007 GlobalDimVectorType const grad_T = dNdx * T;
1008 GlobalDimVectorType const grad_p_cap = -dNdx * p_L;
1009 GlobalDimVectorType const vapour_flux =
1010 -(f_Tv_D_Tv * grad_T - D_pv * grad_p_cap);
1011 double const specific_heat_capacity_vapour =
1013 .template value<double>(variables, x_position, t, dt);
1014
1015 local_M
1016 .template block<temperature_size, temperature_size>(
1018 .noalias() +=
1019 w * (rho_wv * specific_heat_capacity_vapour * (1 - S_L) * phi) *
1020 N.transpose() * N;
1021
1022 local_K
1023 .template block<temperature_size, temperature_size>(
1025 .noalias() += N.transpose() * vapour_flux.transpose() * dNdx *
1026 specific_heat_capacity_vapour * w;
1027
1028 double const storage_coefficient_by_water_vapor =
1029 phi * (rho_wv * dS_L_dp_cap + (1 - S_L) * drho_wv_dp);
1030 local_M
1031 .template block<pressure_size, pressure_size>(pressure_index,
1033 .noalias() +=
1034 N.transpose() * storage_coefficient_by_water_vapor * N * w;
1035
1036 double const vapor_expansion_factor = phi * (1 - S_L) * drho_wv_dT;
1037 local_M
1038 .template block<pressure_size, temperature_size>(
1040 .noalias() += N.transpose() * vapor_expansion_factor * N * w;
1041
1042 local_rhs.template segment<pressure_size>(pressure_index)
1043 .noalias() -= f_Tv_D_Tv * dNdx.transpose() * (dNdx * T) * w;
1044
1045 local_K
1046 .template block<pressure_size, pressure_size>(pressure_index,
1048 .noalias() += dNdx.transpose() * D_pv * dNdx * w;
1049
1050 //
1051 // Latent heat term
1052 //
1054 {
1055 double const factor = phi * (1 - S_L) / rho_LR;
1056 // The volumetric latent heat of vaporization of liquid water
1057 double const L0 =
1059 .template value<double>(variables, x_position, t, dt) *
1060 rho_LR;
1061
1062 double const drho_LR_dT =
1063 liquid_phase.property(MPL::PropertyType::density)
1064 .template dValue<double>(variables,
1066 x_position, t, dt);
1067
1068 double const rho_wv_over_rho_L = rho_wv / rho_LR;
1069 local_M
1070 .template block<temperature_size, temperature_size>(
1072 .noalias() +=
1073 factor * L0 *
1074 (drho_wv_dT - rho_wv_over_rho_L * drho_LR_dT) *
1075 N.transpose() * N * w;
1076
1077 local_M
1078 .template block<temperature_size, pressure_size>(
1080 .noalias() +=
1081 (factor * L0 *
1082 (drho_wv_dp - rho_wv_over_rho_L * drho_LR_dp) +
1083 L0 * phi * rho_wv_over_rho_L * dS_L_dp_cap) *
1084 N.transpose() * N * w;
1085
1086 // temperature equation, temperature part
1087 local_K
1088 .template block<temperature_size, temperature_size>(
1090 .noalias() +=
1091 L0 * f_Tv_D_Tv * dNdx.transpose() * dNdx * w / rho_LR;
1092 // temperature equation, pressure part
1093 local_K
1094 .template block<temperature_size, pressure_size>(
1096 .noalias() +=
1097 L0 * D_pv * dNdx.transpose() * dNdx * w / rho_LR;
1098 }
1099 }
1100 }
1101
1102 if (_process_data.apply_mass_lumping)
1103 {
1104 auto Mpp = local_M.template block<pressure_size, pressure_size>(
1106 Mpp = Mpp.colwise().sum().eval().asDiagonal();
1107 }
1108}
1109
1110template <typename ShapeFunction, int GlobalDim>
1111std::vector<double> const&
1114 const double /*t*/,
1115 std::vector<GlobalVector*> const& /*x*/,
1116 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
1117 std::vector<double>& cache) const
1118{
1119 unsigned const n_integration_points =
1120 _integration_method.getNumberOfPoints();
1121
1122 cache.clear();
1123 auto cache_matrix = MathLib::createZeroedMatrix<
1124 Eigen::Matrix<double, GlobalDim, Eigen::Dynamic, Eigen::RowMajor>>(
1125 cache, GlobalDim, n_integration_points);
1126
1127 for (unsigned ip = 0; ip < n_integration_points; ip++)
1128 {
1129 cache_matrix.col(ip).noalias() = _ip_data[ip].v_darcy;
1130 }
1131
1132 return cache;
1133}
1134
1135template <typename ShapeFunction, int GlobalDim>
1136std::vector<double> ThermoRichardsFlowLocalAssembler<
1138{
1139 std::vector<double> result;
1140 getIntPtSaturation(0, {}, {}, result);
1141 return result;
1142}
1143
1144template <typename ShapeFunction, int GlobalDim>
1145std::vector<double> const&
1147 const double /*t*/,
1148 std::vector<GlobalVector*> const& /*x*/,
1149 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
1150 std::vector<double>& cache) const
1151{
1153 _ip_data, &IpData::saturation, cache);
1154}
1155
1156template <typename ShapeFunction, int GlobalDim>
1157std::vector<double>
1159{
1160 std::vector<double> result;
1161 getIntPtPorosity(0, {}, {}, result);
1162 return result;
1163}
1164
1165template <typename ShapeFunction, int GlobalDim>
1166std::vector<double> const&
1168 const double /*t*/,
1169 std::vector<GlobalVector*> const& /*x*/,
1170 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
1171 std::vector<double>& cache) const
1172{
1174 &IpData::porosity, cache);
1175}
1176
1177template <typename ShapeFunction, int GlobalDim>
1178std::vector<double> const&
1181 const double /*t*/,
1182 std::vector<GlobalVector*> const& /*x*/,
1183 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
1184 std::vector<double>& cache) const
1185{
1188}
1189
1190template <typename ShapeFunction, int GlobalDim>
1192 computeSecondaryVariableConcrete(double const t, double const dt,
1193 Eigen::VectorXd const& local_x,
1194 Eigen::VectorXd const& local_x_prev)
1195{
1196 auto const T =
1197 local_x.template segment<temperature_size>(temperature_index);
1198
1199 auto const p_L = local_x.template segment<pressure_size>(pressure_index);
1200
1201 auto p_L_prev =
1202 local_x_prev.template segment<pressure_size>(pressure_index);
1203
1204 auto const& medium = *_process_data.media_map.getMedium(_element.getID());
1205 auto const& liquid_phase = medium.phase("AqueousLiquid");
1206 auto const& solid_phase = medium.phase("Solid");
1207 MPL::VariableArray variables;
1208 MPL::VariableArray variables_prev;
1209
1210 unsigned const n_integration_points =
1211 _integration_method.getNumberOfPoints();
1212
1213 double saturation_avg = 0;
1214 double porosity_avg = 0;
1215
1216 for (unsigned ip = 0; ip < n_integration_points; ip++)
1217 {
1218 auto const& N = _ip_data[ip].N;
1219
1220 ParameterLib::SpatialPosition const x_position{
1221 std::nullopt, _element.getID(),
1224 _element, N))};
1225
1226 double T_ip;
1228
1229 double p_cap_ip;
1230 NumLib::shapeFunctionInterpolate(-p_L, N, p_cap_ip);
1231
1232 double p_cap_prev_ip;
1233 NumLib::shapeFunctionInterpolate(-p_L_prev, N, p_cap_prev_ip);
1234
1235 variables.capillary_pressure = p_cap_ip;
1236 variables.liquid_phase_pressure = -p_cap_ip;
1237 // setting pG to 1 atm
1238 // TODO : rewrite equations s.t. p_L = pG-p_cap
1239 variables.gas_phase_pressure = 1.0e5;
1240
1241 variables.temperature = T_ip;
1242
1243 auto& S_L = _ip_data[ip].saturation;
1244 auto const S_L_prev = _ip_data[ip].saturation_prev;
1245 S_L = medium[MPL::PropertyType::saturation].template value<double>(
1246 variables, x_position, t, dt);
1247 variables.liquid_saturation = S_L;
1248 variables_prev.liquid_saturation = S_L_prev;
1249
1250 auto chi_S_L = S_L;
1251 auto chi_S_L_prev = S_L_prev;
1252 if (medium.hasProperty(MPL::PropertyType::bishops_effective_stress))
1253 {
1254 auto const chi = [&medium, x_position, t, dt](double const S_L)
1255 {
1256 MPL::VariableArray variables;
1257 variables.liquid_saturation = S_L;
1259 .template value<double>(variables, x_position, t, dt);
1260 };
1261 chi_S_L = chi(S_L);
1262 chi_S_L_prev = chi(S_L_prev);
1263 }
1264 variables.effective_pore_pressure = -chi_S_L * p_cap_ip;
1265 variables_prev.effective_pore_pressure = -chi_S_L_prev * p_cap_prev_ip;
1266
1267 auto const alpha =
1268 medium[MPL::PropertyType::biot_coefficient].template value<double>(
1269 variables, x_position, t, dt);
1270
1271 auto& solid_elasticity = *_process_data.simplified_elasticity;
1272 auto const beta_S =
1273 solid_elasticity.bulkCompressibilityFromYoungsModulus(
1274 solid_phase, variables, x_position, t, dt);
1275 auto const beta_SR = (1 - alpha) * beta_S;
1276 variables.grain_compressibility = beta_SR;
1277
1278 auto& phi = _ip_data[ip].porosity;
1279 { // Porosity update
1280 variables_prev.porosity = _ip_data[ip].porosity_prev;
1281 phi = medium[MPL::PropertyType::porosity].template value<double>(
1282 variables, variables_prev, x_position, t, dt);
1283 variables.porosity = phi;
1284 }
1285
1286 auto const mu =
1287 liquid_phase[MPL::PropertyType::viscosity].template value<double>(
1288 variables, x_position, t, dt);
1289 auto const rho_LR =
1290 liquid_phase[MPL::PropertyType::density].template value<double>(
1291 variables, x_position, t, dt);
1292
1293 auto const K_intrinsic = MPL::formEigenTensor<GlobalDim>(
1294 medium[MPL::PropertyType::permeability].value(variables, x_position,
1295 t, dt));
1296
1297 double const k_rel =
1299 .template value<double>(variables, x_position, t, dt);
1300
1301 GlobalDimMatrixType const K_over_mu = k_rel * K_intrinsic / mu;
1302
1303 auto const rho_SR =
1304 solid_phase[MPL::PropertyType::density].template value<double>(
1305 variables, x_position, t, dt);
1306 _ip_data[ip].dry_density_solid = (1 - phi) * rho_SR;
1307
1308 auto const& b = _process_data.specific_body_force;
1309
1310 auto const K_pT_thermal_osmosis =
1311 (solid_phase.hasProperty(
1314 solid_phase
1316 .value(variables, x_position, t, dt))
1317 : Eigen::MatrixXd::Zero(GlobalDim, GlobalDim));
1318
1319 // Compute the velocity
1320 auto const& dNdx = _ip_data[ip].dNdx;
1321 _ip_data[ip].v_darcy.noalias() = -K_over_mu * dNdx * p_L -
1322 K_pT_thermal_osmosis * dNdx * T +
1323 rho_LR * K_over_mu * b;
1324
1325 saturation_avg += S_L;
1326 porosity_avg += phi;
1327 }
1328 saturation_avg /= n_integration_points;
1329 porosity_avg /= n_integration_points;
1330
1331 (*_process_data.element_saturation)[_element.getID()] = saturation_avg;
1332 (*_process_data.element_porosity)[_element.getID()] = porosity_avg;
1333}
1334
1335template <typename ShapeFunction, int GlobalDim>
1338{
1339 return _integration_method.getNumberOfPoints();
1340}
1341
1342} // namespace ThermoRichardsFlow
1343} // namespace ProcessLib
#define OGS_FATAL(...)
Definition Error.h:19
Property const & property(PropertyType const &p) const
Definition Phase.cpp:44
bool hasProperty(PropertyType const &p) const
Definition Phase.cpp:60
void assembleWithJacobian(double const t, double const dt, std::vector< double > const &local_x, std::vector< double > const &local_x_prev, std::vector< double > &local_rhs_data, std::vector< double > &local_Jac_data) override
std::vector< double > const & getIntPtSaturation(const double t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_table, std::vector< double > &cache) const override
std::size_t setIPDataInitialConditions(std::string_view const name, double const *values, int const integration_order) override
std::vector< double > const & getIntPtDryDensitySolid(const double t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_table, std::vector< double > &cache) const override
std::vector< double > const & getIntPtDarcyVelocity(const double t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_table, std::vector< double > &cache) const override
typename ShapeMatricesType::GlobalDimVectorType GlobalDimVectorType
void assemble(double const t, double const dt, std::vector< double > const &local_x, std::vector< double > const &local_x_prev, std::vector< double > &local_M_data, std::vector< double > &local_K_data, std::vector< double > &local_rhs_data) override
ThermoRichardsFlowLocalAssembler(ThermoRichardsFlowLocalAssembler const &)=delete
std::vector< double > const & getIntPtPorosity(const double t, std::vector< GlobalVector * > const &x, std::vector< NumLib::LocalToGlobalIndexMap const * > const &dof_table, std::vector< double > &cache) const override
void setInitialConditionsConcrete(Eigen::VectorXd const local_x, double const t, int const process_id) override
typename ShapeMatricesType::GlobalDimMatrixType GlobalDimMatrixType
ShapeMatrixPolicyType< ShapeFunction, GlobalDim > ShapeMatricesType
void computeSecondaryVariableConcrete(double const t, double const dt, Eigen::VectorXd const &local_x, Eigen::VectorXd const &local_x_prev) override
std::vector< IpData, Eigen::aligned_allocator< IpData > > _ip_data
constexpr Eigen::Matrix< double, GlobalDim, GlobalDim > formEigenTensor(MaterialPropertyLib::PropertyDataType const &values)
template Eigen::Matrix< double, 3, 3 > formEigenTensor< 3 >(MaterialPropertyLib::PropertyDataType const &values)
double getLiquidThermalExpansivity(Phase const &phase, VariableArray const &vars, const double density, ParameterLib::SpatialPosition const &pos, double const t, double const dt)
@ thermal_diffusion_enhancement_factor
Thermal diffusion enhancement factor for water vapor flow.
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)
void shapeFunctionInterpolate(const NodalValues &, const ShapeMatrix &)
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)
std::array< double, 3 > interpolateCoordinates(MeshLib::Element const &e, typename ShapeMatricesType::ShapeMatrices::ShapeType const &N)
std::vector< double > const & getIntegrationPointScalarData(IntegrationPointDataVector const &ip_data_vector, MemberType IpData::*const member, std::vector< double > &cache)
std::size_t setIntegrationPointScalarData(double const *values, IntegrationPointDataVector &ip_data_vector, MemberType IpData::*const member)
MatrixType< ShapeFunction::NPOINTS, ShapeFunction::NPOINTS > NodalMatrixType