OGS
ThermoHydroMechanicsFEM.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 <memory>
7#include <vector>
8
17#include "NumLib/DOF/LocalDOF.h"
28
29namespace ProcessLib
30{
32{
33namespace MPL = MaterialPropertyLib;
34
37template <typename ShapeMatrixType>
39{
40 std::vector<ShapeMatrixType, Eigen::aligned_allocator<ShapeMatrixType>> N_u;
41};
42
43template <typename ShapeFunctionDisplacement, typename ShapeFunctionPressure,
44 int DisplacementDim>
46 : public LocalAssemblerInterface<DisplacementDim>
47{
48public:
51
52 // Types for pressure.
55
58
61
62 static int const KelvinVectorSize =
65
66 using SymmetricTensor = Eigen::Matrix<double, KelvinVectorSize, 1>;
67
68 static constexpr auto& N_u_op = MathLib::eigenBlockMatrixView<
69 DisplacementDim,
71
75 delete;
76
78 MeshLib::Element const& e,
79 std::size_t const /*local_matrix_size*/,
80 NumLib::GenericIntegrationMethod const& integration_method,
81 bool const is_axially_symmetric,
83
86 std::string_view const name,
87 double const* values,
88 int const integration_order) override;
89
90 void assemble(double const /*t*/, double const /*dt*/,
91 std::vector<double> const& /*local_x*/,
92 std::vector<double> const& /*local_x_prev*/,
93 std::vector<double>& /*local_M_data*/,
94 std::vector<double>& /*local_K_data*/,
95 std::vector<double>& /*local_rhs_data*/) override
96 {
98 "ThermoHydroMechanicsLocalAssembler: assembly without Jacobian is "
99 "not implemented.");
100 }
101
102 void assembleWithJacobian(double const t, double const dt,
103 std::vector<double> const& local_x,
104 std::vector<double> const& local_x_prev,
105 std::vector<double>& local_rhs_data,
106 std::vector<double>& local_Jac_data) override;
107
108 void initializeConcrete() override
109 {
110 unsigned const n_integration_points =
111 _integration_method.getNumberOfPoints();
112
113 for (unsigned ip = 0; ip < n_integration_points; ip++)
114 {
115 auto& ip_data = _ip_data[ip];
116
117 ParameterLib::SpatialPosition const x_position{
118 std::nullopt, _element.getID(),
121 ShapeFunctionDisplacement,
123
125 if (_process_data.initial_stress.value)
126 {
127 ip_data.sigma_eff =
129 DisplacementDim>((*_process_data.initial_stress.value)(
130 std::numeric_limits<double>::quiet_NaN() /* time
131 independent
132 */
133 ,
134 x_position));
135 }
136
137 double const t = 0; // TODO (naumov) pass t from top
138 ip_data.solid_material.initializeInternalStateVariables(
139 t, x_position, *ip_data.material_state_variables);
140
141 ip_data.pushBackState();
142 }
143 }
144
145 void setInitialConditionsConcrete(Eigen::VectorXd const local_x,
146 double const t,
147 int const process_id) override;
148
149 void preTimestepConcrete(std::vector<double> const& /*local_x*/,
150 double const /*t*/, double const /*dt*/) override
151 {
152 unsigned const n_integration_points =
153 _integration_method.getNumberOfPoints();
154
155 for (unsigned ip = 0; ip < n_integration_points; ip++)
156 {
157 _ip_data_output[ip].velocity.setConstant(
158 DisplacementDim, std::numeric_limits<double>::quiet_NaN());
159 }
160 }
161
162 void postTimestepConcrete(Eigen::VectorXd const& local_x,
163 Eigen::VectorXd const& local_x_prev,
164 double const t, double const dt,
165 int const /*process_id*/) override
166 {
167 unsigned const n_integration_points =
168 _integration_method.getNumberOfPoints();
169
170 auto const [T, p, u] = localDOF(local_x);
171 auto const [T_prev, p_prev, u_prev] = localDOF(local_x_prev);
172
173 // Stored sensible heat integrated over the element, for output.
174 double sensible_heat = 0.0;
175
176 for (unsigned ip = 0; ip < n_integration_points; ip++)
177 {
178 auto& ip_data = _ip_data[ip];
179 auto const& N_u = ip_data.N_u;
180 auto const& dNdx_u = ip_data.dNdx_u;
181
182 ParameterLib::SpatialPosition const x_position{
183 std::nullopt, _element.getID(),
186 ShapeFunctionDisplacement,
188
189 auto const crv = updateConstitutiveRelations(
190 local_x, local_x_prev, x_position, t, dt, _ip_data[ip],
191 _ip_data_output[ip]);
192
193 // Stored sensible heat (latent already excluded).
194 sensible_heat += crv.sensible_volumetric_heat_capacity *
195 ip_data.N.dot(T) * ip_data.integration_weight;
196
197 auto const x_coord =
198 x_position.getCoordinates().value()[0]; // r for axisymmetry
199 auto const B = LinearBMatrix::computeBMatrix<
200 DisplacementDim, ShapeFunctionDisplacement::NPOINTS,
201 typename BMatricesType::BMatrixType>(dNdx_u, N_u, x_coord,
203
205 eps_prev = B * u_prev;
206
207 _ip_data[ip].eps0 =
208 _ip_data[ip].eps0_prev +
209 (1 - _ip_data[ip].phi_fr_prev / _ip_data[ip].porosity) *
210 (eps_prev - _ip_data[ip].eps0_prev);
211 _ip_data[ip].pushBackState();
212 }
213
214 (*_process_data.cell_sensible_heat)[_element.getID()] = sensible_heat;
215 }
216
218 double const t, double const dt, Eigen::VectorXd const& local_x,
219 Eigen::VectorXd const& local_x_prev) override;
220
221 Eigen::Map<const Eigen::RowVectorXd> getShapeMatrix(
222 const unsigned integration_point) const override
223 {
224 auto const& N_u = _secondary_data.N_u[integration_point];
225
226 // assumes N is stored contiguously in memory
227 return Eigen::Map<const Eigen::RowVectorXd>(N_u.data(), N_u.size());
228 }
229
230 std::vector<double> const& getIntPtDarcyVelocity(
231 const double t,
232 std::vector<GlobalVector*> const& x,
233 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_table,
234 std::vector<double>& cache) const override;
235
236 // TODO (naumov) This method is same as getIntPtSigma but for arguments and
237 // the ordering of the cache_mat.
238 // There should be only one.
239 std::vector<double> getSigma() const override
240 {
241 constexpr int kelvin_vector_size =
243
245 [this](std::vector<double>& values)
246 { return getIntPtSigma(0, {}, {}, values); });
247 }
248
249 std::vector<double> getSigmaIce() const override
250 {
251 constexpr int kelvin_vector_size =
253
255 [this](std::vector<double>& values)
256 { return getIntPtSigmaIce(0, {}, {}, values); });
257 }
258
259 std::vector<double> getIceVolumeFraction() const override
260 {
261 std::vector<double> result;
262 getIntPtIceVolume(0, {}, {}, result);
263 return result;
264 }
265
266 std::vector<double> const& getIntPtFluidDensity(
267 const double t,
268 std::vector<GlobalVector*> const& x,
269 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_table,
270 std::vector<double>& cache) const override;
271
272 std::vector<double> const& getIntPtViscosity(
273 const double t,
274 std::vector<GlobalVector*> const& x,
275 std::vector<NumLib::LocalToGlobalIndexMap const*> const& dof_table,
276 std::vector<double>& cache) const override;
277
279 {
280 return displacement_size;
281 }
282
283private:
286 using IpData =
288 ShapeMatricesTypePressure, DisplacementDim,
289 ShapeFunctionDisplacement::NPOINTS>;
290
291private:
293 Eigen::Ref<Eigen::VectorXd const> const local_x,
294 Eigen::Ref<Eigen::VectorXd const> const local_x_prev,
295 ParameterLib::SpatialPosition const& x_position, double const t,
296 double const dt, IpData& ip_data,
298
299 std::size_t setSigma(double const* values)
300 {
302 values, _ip_data, &IpData::sigma_eff);
303 }
304
305 std::vector<double> const& getIntPtSigma(
306 const double /*t*/,
307 std::vector<GlobalVector*> const& /*x*/,
308 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
309 std::vector<double>& cache) const override
310 {
312 _ip_data, &IpData::sigma_eff, cache);
313 }
314
315 std::vector<double> const& getIntPtSigmaIce(
316 const double /*t*/,
317 std::vector<GlobalVector*> const& /*x*/,
318 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
319 std::vector<double>& cache) const override
320 {
323 }
324
325 std::vector<double> getEpsilon0() const override
326 {
327 constexpr int kelvin_vector_size =
329
331 [this](std::vector<double>& values)
332 { return getIntPtEpsilon0(0, {}, {}, values); });
333 }
334
335 virtual std::vector<double> const& getIntPtEpsilon0(
336 const double /*t*/,
337 std::vector<GlobalVector*> const& /*x*/,
338 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
339 std::vector<double>& cache) const override
340 {
342 _ip_data, &IpData::eps0, cache);
343 }
344 std::vector<double> getEpsilonM() const override
345 {
346 constexpr int kelvin_vector_size =
348
350 [this](std::vector<double>& values)
351 { return getIntPtEpsilonM(0, {}, {}, values); });
352 }
353
354 virtual std::vector<double> const& getIntPtEpsilonM(
355 const double /*t*/,
356 std::vector<GlobalVector*> const& /*x*/,
357 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
358 std::vector<double>& cache) const override
359 {
361 _ip_data, &IpData::eps_m, cache);
362 }
363
364 std::vector<double> getEpsilon() const override
365 {
366 constexpr int kelvin_vector_size =
368
370 [this](std::vector<double>& values)
371 { return getIntPtEpsilon(0, {}, {}, values); });
372 }
373
374 virtual std::vector<double> const& getIntPtEpsilon(
375 const double /*t*/,
376 std::vector<GlobalVector*> const& /*x*/,
377 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
378 std::vector<double>& cache) const override
379 {
381 _ip_data, &IpData::eps, cache);
382 }
383
384 std::vector<double> const& getIntPtIceVolume(
385 const double /*t*/,
386 std::vector<GlobalVector*> const& /*x*/,
387 std::vector<NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
388 std::vector<double>& cache) const override
389 {
391 _ip_data, &IpData::phi_fr, cache);
392 }
393
394 unsigned getNumberOfIntegrationPoints() const override
395 {
396 return _integration_method.getNumberOfPoints();
397 }
398
399 int getMaterialID() const override
400 {
401 return _process_data.material_ids == nullptr
402 ? 0
403 : (*_process_data.material_ids)[_element.getID()];
404 }
405
407 std::function<std::span<double>(
409 MaterialStateVariables&)> const& get_values_span,
410 int const& n_components) const override
411 {
414 n_components);
415 }
416
418 DisplacementDim>::MaterialStateVariables const&
419 getMaterialStateVariablesAt(unsigned integration_point) const override
420 {
421 return *_ip_data[integration_point].material_state_variables;
422 }
423
424private:
425 template <typename SolutionVector>
426 static constexpr auto localDOF(SolutionVector const& x)
427 {
428 return NumLib::localDOF<
429 ShapeFunctionPressure, ShapeFunctionPressure,
431 }
432
434
435 std::vector<IpData, Eigen::aligned_allocator<IpData>> _ip_data;
436 std::vector<IntegrationPointDataForOutput<DisplacementDim>,
437 Eigen::aligned_allocator<
440
445 typename ShapeMatricesTypeDisplacement::ShapeMatrices::ShapeType>
447
448 // The shape function of pressure has the same form with the shape function
449 // of temperature
450 static const int temperature_index = 0;
451 static const int temperature_size = ShapeFunctionPressure::NPOINTS;
452 static const int pressure_index = ShapeFunctionPressure::NPOINTS;
453 static const int pressure_size = ShapeFunctionPressure::NPOINTS;
454 static const int displacement_index = ShapeFunctionPressure::NPOINTS * 2;
455 static const int displacement_size =
456 ShapeFunctionDisplacement::NPOINTS * DisplacementDim;
457};
458
459} // namespace ThermoHydroMechanics
460} // namespace ProcessLib
461
#define OGS_FATAL(...)
Definition Error.h:10
EigenFixedShapeMatrixPolicy< ShapeFunction, GlobalDim > ShapeMatrixPolicyType
std::optional< MathLib::Point3d > const getCoordinates() const
MatrixType< _kelvin_vector_size, _number_of_dof > BMatrixType
std::vector< double > const & getIntPtViscosity(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 & getIntPtFluidDensity(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
void assemble(double const, double const, std::vector< double > const &, std::vector< double > const &, std::vector< double > &, std::vector< double > &, std::vector< double > &) override
ThermoHydroMechanicsLocalAssembler(ThermoHydroMechanicsLocalAssembler const &)=delete
std::vector< double > getMaterialStateVariableInternalState(std::function< std::span< double >(typename MaterialLib::Solids::MechanicsBase< DisplacementDim >::MaterialStateVariables &)> const &get_values_span, int const &n_components) const override
std::vector< double > const & getIntPtSigmaIce(const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const override
typename ShapeMatricesTypePressure::GlobalDimMatrixType GlobalDimMatrixType
ConstitutiveRelationsValues< DisplacementDim > updateConstitutiveRelations(Eigen::Ref< Eigen::VectorXd const > const local_x, Eigen::Ref< Eigen::VectorXd const > const local_x_prev, ParameterLib::SpatialPosition const &x_position, double const t, double const dt, IpData &ip_data, IntegrationPointDataForOutput< DisplacementDim > &ip_data_output) const
ShapeMatrixPolicyType< ShapeFunctionDisplacement, DisplacementDim > ShapeMatricesTypeDisplacement
void preTimestepConcrete(std::vector< double > const &, double const, double const) override
BMatrixPolicyType< ShapeFunctionDisplacement, DisplacementDim > BMatricesType
typename ShapeMatricesTypePressure::GlobalDimVectorType GlobalDimVectorType
virtual std::vector< double > const & getIntPtEpsilon(const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const override
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
IntegrationPointData< BMatricesType, ShapeMatricesTypeDisplacement, ShapeMatricesTypePressure, DisplacementDim, ShapeFunctionDisplacement::NPOINTS > IpData
ThermoHydroMechanicsProcessData< DisplacementDim > & _process_data
std::vector< IntegrationPointDataForOutput< DisplacementDim >, Eigen::aligned_allocator< IntegrationPointDataForOutput< DisplacementDim > > > _ip_data_output
void postTimestepConcrete(Eigen::VectorXd const &local_x, Eigen::VectorXd const &local_x_prev, double const t, double const dt, int const) override
SecondaryData< typename ShapeMatricesTypeDisplacement::ShapeMatrices::ShapeType > _secondary_data
ShapeMatrixPolicyType< ShapeFunctionPressure, DisplacementDim > ShapeMatricesTypePressure
std::vector< IpData, Eigen::aligned_allocator< IpData > > _ip_data
virtual std::vector< double > const & getIntPtEpsilonM(const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const override
std::vector< double > const & getIntPtIceVolume(const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const override
MathLib::KelvinVector::Invariants< KelvinVectorSize > Invariants
MaterialLib::Solids::MechanicsBase< DisplacementDim >::MaterialStateVariables const & getMaterialStateVariablesAt(unsigned integration_point) const override
std::size_t setIPDataInitialConditions(std::string_view const name, double const *values, int const integration_order) override
Returns number of read integration points.
virtual std::vector< double > const & getIntPtEpsilon0(const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const override
ThermoHydroMechanicsLocalAssembler(ThermoHydroMechanicsLocalAssembler &&)=delete
void computeSecondaryVariableConcrete(double const t, double const dt, Eigen::VectorXd const &local_x, Eigen::VectorXd const &local_x_prev) override
Eigen::Map< const Eigen::RowVectorXd > getShapeMatrix(const unsigned integration_point) const override
Provides the shape matrix at the given integration point.
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
std::vector< double > const & getIntPtSigma(const double, std::vector< GlobalVector * > const &, std::vector< NumLib::LocalToGlobalIndexMap const * > const &, std::vector< double > &cache) const override
constexpr int kelvin_vector_dimensions(int const displacement_dim)
Kelvin vector dimensions for given displacement dimension.
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), 1, Eigen::ColMajor > KelvinVectorType
Eigen::Matrix< double, Eigen::MatrixBase< Derived >::RowsAtCompileTime, 1 > symmetricTensorToKelvinVector(Eigen::MatrixBase< Derived > const &v)
constexpr Eigen::CwiseNullaryOp< EigenBlockMatrixViewFunctor< D, M >, typename EigenBlockMatrixViewFunctor< D, M >::Matrix > eigenBlockMatrixView(const Eigen::MatrixBase< M > &matrix)
auto localDOF(ElementDOFVector const &x)
Definition LocalDOF.h:56
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.
std::vector< double > const & getIntegrationPointScalarData(IntegrationPointDataVector const &ip_data_vector, MemberType IpData::*const member, std::vector< double > &cache)
std::vector< double > transposeInPlace(StoreValuesFunction const &store_values_function)
std::vector< double > getIntegrationPointDataMaterialStateVariables(IntegrationPointDataVector const &ip_data_vector, MemberType member, std::function< std::span< double >(MaterialStateVariables &)> get_values_span, int const n_components)
std::vector< double > const & getIntegrationPointKelvinVectorData(IntegrationPointDataVector const &ip_data_vector, MemberType IpData::*const member, std::vector< double > &cache)
std::size_t setIntegrationPointKelvinVectorData(double const *values, IntegrationPointDataVector &ip_data_vector, MemberType IpData::*const member)
MatrixType< GlobalDim, GlobalDim > GlobalDimMatrixType
VectorType< GlobalDim > GlobalDimVectorType
RowVectorType< ShapeFunction::NPOINTS > NodalRowVectorType
std::vector< ShapeMatrixType, Eigen::aligned_allocator< ShapeMatrixType > > N_u