OGS
HTFEM.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 <Eigen/Core>
7#include <optional>
8#include <vector>
9
11#include "HTProcessData.h"
22
23namespace ProcessLib
24{
25namespace HT
26{
64 double const t, double const dt, ParameterLib::SpatialPosition const& pos,
65 MaterialPropertyLib::VariableArray const& vars,
66 MaterialPropertyLib::Medium const& medium,
67 MaterialPropertyLib::Phase const& liquid_phase,
68 MaterialPropertyLib::Phase const& solid_phase,
69 bool const has_solid_thermal_expansivity, double const specific_storage);
70
87void checkBiotStorageRelation(double const t, double const dt,
88 ParameterLib::SpatialPosition const& pos,
89 MaterialPropertyLib::VariableArray const& vars,
90 MaterialPropertyLib::Medium const& medium,
91 MaterialPropertyLib::Phase const& solid_phase);
92
93template <typename ShapeFunction, int GlobalDim>
95{
98
101
106
107public:
108 HTFEM(MeshLib::Element const& element,
109 std::size_t const local_matrix_size,
110 NumLib::GenericIntegrationMethod const& integration_method,
111 bool const is_axially_symmetric,
112 HTProcessData const& process_data,
113 const unsigned dof_per_node)
115 _element(element),
116 _process_data(process_data),
117 _integration_method(integration_method)
118 {
119 // This assertion is valid only if all nodal d.o.f. use the same shape
120 // matrices.
121 assert(local_matrix_size == ShapeFunction::NPOINTS * dof_per_node);
122 (void)local_matrix_size;
123 (void)dof_per_node;
124
125 unsigned const n_integration_points =
126 _integration_method.getNumberOfPoints();
127 _ip_data.reserve(n_integration_points);
128
130 pos.setElementID(_element.getID());
131
132 double const aperture_size = _process_data.aperture_size(0.0, pos)[0];
133
134 auto const shape_matrices =
136 GlobalDim>(element, is_axially_symmetric,
138
139 for (unsigned ip = 0; ip < n_integration_points; ip++)
140 {
141 _ip_data.emplace_back(
142 shape_matrices[ip].dNdx,
143 _integration_method.getWeightedPoint(ip).getWeight() *
144 shape_matrices[ip].integralMeasure *
145 shape_matrices[ip].detJ * aperture_size);
146 }
147 }
148
149 void initializeConcrete() override
150 {
151 auto const& medium =
152 *_process_data.media_map.getMedium(_element.getID());
153 auto const& solid_phase =
155
156 // The Biot coefficient is read only together with the solid thermal
157 // expansivity, see evalEffectiveThermalExpansivity().
158 if (!solid_phase.hasProperty(
160 {
161 return;
162 }
163
165 vars.liquid_saturation = 1.0;
166
167 auto const& Ns =
168 _process_data.shape_matrix_cache
169 .template NsHigherOrder<typename ShapeFunction::MeshElement>();
170
171 unsigned const n_integration_points =
172 _integration_method.getNumberOfPoints();
173 for (unsigned ip = 0; ip < n_integration_points; ip++)
174 {
176 std::nullopt, _element.getID(),
180 Ns[ip]))};
181
182 checkBiotStorageRelation(0.0 /* t */, 0.0 /* dt */, pos, vars,
183 medium, solid_phase);
184 }
185 }
186
187 Eigen::Map<const Eigen::RowVectorXd> getShapeMatrix(
188 const unsigned integration_point) const override
189 {
190 auto const& N = _process_data.shape_matrix_cache.NsHigherOrder<
191 typename ShapeFunction::MeshElement>()[integration_point];
192
193 // assumes N is stored contiguously in memory
194 return Eigen::Map<const Eigen::RowVectorXd>(N.data(), N.size());
195 }
196
199 Eigen::Vector3d getFlux(MathLib::Point3d const& pnt_local_coords,
200 double const t,
201 std::vector<double> const& local_x) const override
202 {
203 // Eval shape matrices at given point
204 // Note: Axial symmetry is set to false here, because we only need dNdx
205 // here, which is not affected by axial symmetry.
206 auto const shape_matrices =
208 GlobalDim>(
209 _element, false /*is_axially_symmetric*/,
210 std::array{pnt_local_coords})[0];
211
213 pos.setElementID(this->_element.getID());
214
216
217 // local_x contains the local temperature and pressure values
218 double T_int_pt = 0.0;
219 double p_int_pt = 0.0;
220 NumLib::shapeFunctionInterpolate(local_x, shape_matrices.N, T_int_pt,
221 p_int_pt);
222
223 vars.temperature = T_int_pt;
224 vars.liquid_phase_pressure = p_int_pt;
225
226 auto const& medium =
227 *_process_data.media_map.getMedium(_element.getID());
228 auto const& liquid_phase =
230
231 // TODO (naumov) Temporary value not used by current material models.
232 // Need extension of secondary variables interface.
233 double const dt = std::numeric_limits<double>::quiet_NaN();
234 // fetch permeability, viscosity, density
237 .value(vars, pos, t, dt));
238
239 auto const mu =
241 .template value<double>(vars, pos, t, dt);
242 GlobalDimMatrixType const K_over_mu = K / mu;
243
244 auto const p_nodal_values = Eigen::Map<const NodalVectorType>(
245 &local_x[local_x.size() / 2], ShapeFunction::NPOINTS);
247 -K_over_mu * shape_matrices.dNdx * p_nodal_values;
248
249 if (this->_process_data.has_gravity)
250 {
251 auto const rho_w =
252 liquid_phase
254 .template value<double>(vars, pos, t, dt);
255 auto const b =
256 this->_process_data.projected_specific_body_force_vectors
257 [this->_element.getID()];
258 q += K_over_mu * rho_w * b;
259 }
260
261 Eigen::Vector3d flux;
262 flux.head<GlobalDim>() = q;
263 return flux;
264 }
265
266protected:
269
271 std::vector<IntegrationPointData<GlobalDimNodalMatrixType>> _ip_data;
272
274 MaterialPropertyLib::VariableArray const& vars, const double porosity,
275 const double fluid_density, const double specific_heat_capacity_fluid,
276 ParameterLib::SpatialPosition const& pos, double const t,
277 double const dt)
278 {
279 auto const& medium =
280 *_process_data.media_map.getMedium(this->_element.getID());
281 auto const& solid_phase =
283
284 auto const specific_heat_capacity_solid =
285 solid_phase
286 .property(
288 .template value<double>(vars, pos, t, dt);
289
290 auto const solid_density =
292 .template value<double>(vars, pos, t, dt);
293
294 return solid_density * specific_heat_capacity_solid * (1 - porosity) +
295 fluid_density * specific_heat_capacity_fluid * porosity;
296 }
297
300 const double fluid_density, const double specific_heat_capacity_fluid,
301 const GlobalDimVectorType& velocity,
302 ParameterLib::SpatialPosition const& pos, double const t,
303 double const dt)
304 {
305 auto const& medium =
306 *_process_data.media_map.getMedium(_element.getID());
307
308 auto thermal_conductivity =
310 medium
311 .property(
313 .value(vars, pos, t, dt));
314
315 auto const thermal_dispersivity_transversal =
316 medium
318 thermal_transversal_dispersivity)
319 .template value<double>();
320
321 auto const thermal_dispersivity_longitudinal =
322 medium
324 thermal_longitudinal_dispersivity)
325 .template value<double>();
326
327 // Thermal conductivity is moved outside and zero matrix is passed
328 // instead due to multiplication with fluid's density times specific
329 // heat capacity.
330 return thermal_conductivity +
331 fluid_density * specific_heat_capacity_fluid *
333 _process_data.stabilizer, _element.getID(),
334 GlobalDimMatrixType::Zero(GlobalDim, GlobalDim),
335 velocity, 0 /* phi */, thermal_dispersivity_transversal,
336 thermal_dispersivity_longitudinal);
337 }
338
339 std::vector<double> const& getIntPtDarcyVelocityLocal(
340 const double t, std::vector<double> const& local_x,
341 std::vector<double>& cache) const
342 {
343 std::vector<double> local_p{
344 local_x.data() + pressure_index,
345 local_x.data() + pressure_index + pressure_size};
346 std::vector<double> local_T{
347 local_x.data() + temperature_index,
348 local_x.data() + temperature_index + temperature_size};
349
350 auto const n_integration_points =
351 _integration_method.getNumberOfPoints();
352
353 cache.clear();
354 auto cache_mat = MathLib::createZeroedMatrix<
355 Eigen::Matrix<double, GlobalDim, Eigen::Dynamic, Eigen::RowMajor>>(
356 cache, GlobalDim, n_integration_points);
357
359 pos.setElementID(_element.getID());
360
362
363 auto const p_nodal_values = Eigen::Map<const NodalVectorType>(
364 &local_p[0], ShapeFunction::NPOINTS);
365
366 auto const& medium =
367 *_process_data.media_map.getMedium(_element.getID());
368 auto const& liquid_phase =
370
371 auto const& Ns =
372 _process_data.shape_matrix_cache
373 .NsHigherOrder<typename ShapeFunction::MeshElement>();
374
375 for (unsigned ip = 0; ip < n_integration_points; ++ip)
376 {
377 auto const& ip_data = _ip_data[ip];
378 auto const& dNdx = ip_data.dNdx;
379 auto const& N = Ns[ip];
380
381 double T_int_pt = 0.0;
382 double p_int_pt = 0.0;
383 NumLib::shapeFunctionInterpolate(local_p, N, p_int_pt);
384 NumLib::shapeFunctionInterpolate(local_T, N, T_int_pt);
385
386 vars.temperature = T_int_pt;
387 vars.liquid_phase_pressure = p_int_pt;
388
389 // TODO (naumov) Temporary value not used by current material
390 // models. Need extension of secondary variables interface.
391 double const dt = std::numeric_limits<double>::quiet_NaN();
394 .value(vars, pos, t, dt));
395
396 auto const mu =
397 liquid_phase
399 .template value<double>(vars, pos, t, dt);
400 GlobalDimMatrixType const K_over_mu = K / mu;
401
402 cache_mat.col(ip).noalias() = -K_over_mu * dNdx * p_nodal_values;
403
404 if (_process_data.has_gravity)
405 {
406 auto const rho_w =
407 liquid_phase
409 .template value<double>(vars, pos, t, dt);
410 auto const b =
411 _process_data.projected_specific_body_force_vectors
412 [_element.getID()];
413 // here it is assumed that the vector b is directed 'downwards'
414 cache_mat.col(ip).noalias() += K_over_mu * rho_w * b;
415 }
416 }
417
418 return cache;
419 }
420
421protected:
422 static const int pressure_index = ShapeFunction::NPOINTS;
423 static const int pressure_size = ShapeFunction::NPOINTS;
424 static const int temperature_index = 0;
425 static const int temperature_size = ShapeFunction::NPOINTS;
426};
427
428} // namespace HT
429} // namespace ProcessLib
EigenFixedShapeMatrixPolicy< ShapeFunction, GlobalDim > ShapeMatrixPolicyType
std::size_t getID() const
Returns the ID of the element.
Definition Element.h:80
void setElementID(std::size_t element_id)
typename ShapeMatricesType::GlobalDimMatrixType GlobalDimMatrixType
Definition HTFEM.h:105
std::vector< double > const & getIntPtDarcyVelocityLocal(const double t, std::vector< double > const &local_x, std::vector< double > &cache) const
Definition HTFEM.h:339
typename ShapeMatricesType::ShapeMatrices ShapeMatrices
Definition HTFEM.h:97
NumLib::GenericIntegrationMethod const & _integration_method
Definition HTFEM.h:270
typename ShapeMatricesType::GlobalDimNodalMatrixType GlobalDimNodalMatrixType
Definition HTFEM.h:103
static const int temperature_index
Definition HTFEM.h:424
typename ShapeMatricesType::NodalVectorType NodalVectorType
Definition HTFEM.h:99
static const int temperature_size
Definition HTFEM.h:425
double getHeatEnergyCoefficient(MaterialPropertyLib::VariableArray const &vars, const double porosity, const double fluid_density, const double specific_heat_capacity_fluid, ParameterLib::SpatialPosition const &pos, double const t, double const dt)
Definition HTFEM.h:273
void initializeConcrete() override
Definition HTFEM.h:149
HTFEM(MeshLib::Element const &element, std::size_t const local_matrix_size, NumLib::GenericIntegrationMethod const &integration_method, bool const is_axially_symmetric, HTProcessData const &process_data, const unsigned dof_per_node)
Definition HTFEM.h:108
static const int pressure_size
Definition HTFEM.h:423
ShapeMatrixPolicyType< ShapeFunction, GlobalDim > ShapeMatricesType
Definition HTFEM.h:96
typename ShapeMatricesType::GlobalDimVectorType GlobalDimVectorType
Definition HTFEM.h:102
GlobalDimMatrixType getThermalConductivityDispersivity(MaterialPropertyLib::VariableArray const &vars, const double fluid_density, const double specific_heat_capacity_fluid, const GlobalDimVectorType &velocity, ParameterLib::SpatialPosition const &pos, double const t, double const dt)
Definition HTFEM.h:298
Eigen::Vector3d getFlux(MathLib::Point3d const &pnt_local_coords, double const t, std::vector< double > const &local_x) const override
Definition HTFEM.h:199
Eigen::Map< const Eigen::RowVectorXd > getShapeMatrix(const unsigned integration_point) const override
Provides the shape matrix at the given integration point.
Definition HTFEM.h:187
MeshLib::Element const & _element
Definition HTFEM.h:267
HTProcessData const & _process_data
Definition HTFEM.h:268
std::vector< IntegrationPointData< GlobalDimNodalMatrixType > > _ip_data
Definition HTFEM.h:271
static const int pressure_index
Definition HTFEM.h:422
typename ShapeMatricesType::NodalRowVectorType NodalRowVectorType
Definition HTFEM.h:100
constexpr Eigen::Matrix< double, GlobalDim, GlobalDim > formEigenTensor(MaterialPropertyLib::PropertyDataType const &values)
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::vector< typename ShapeMatricesType::ShapeMatrices, Eigen::aligned_allocator< typename ShapeMatricesType::ShapeMatrices > > computeShapeMatrices(MeshLib::Element const &e, bool const is_axially_symmetric, PointContainer const &points)
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)
void checkBiotStorageRelation(double const t, double const dt, ParameterLib::SpatialPosition const &pos, MaterialPropertyLib::VariableArray const &vars, MaterialPropertyLib::Medium const &medium, MaterialPropertyLib::Phase const &solid_phase)
Definition HTFEM.cpp:83
double evalEffectiveThermalExpansivity(double const t, double const dt, ParameterLib::SpatialPosition const &pos, MaterialPropertyLib::VariableArray const &vars, MaterialPropertyLib::Medium const &medium, MaterialPropertyLib::Phase const &liquid_phase, MaterialPropertyLib::Phase const &solid_phase, bool const has_solid_thermal_expansivity, double const specific_storage)
Definition HTFEM.cpp:43
NumLib::ShapeMatrices< NodalRowVectorType, DimNodalMatrixType, DimMatrixType, GlobalDimNodalMatrixType > ShapeMatrices
MatrixType< GlobalDim, ShapeFunction::NPOINTS > GlobalDimNodalMatrixType
MatrixType< GlobalDim, GlobalDim > GlobalDimMatrixType
VectorType< GlobalDim > GlobalDimVectorType
VectorType< ShapeFunction::NPOINTS > NodalVectorType
RowVectorType< ShapeFunction::NPOINTS > NodalRowVectorType