OGS
LIE/HydroMechanics/CreateHydroMechanicsProcess.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
5
6#include <cassert>
7#include <range/v3/numeric/accumulate.hpp>
8#include <range/v3/view/transform.hpp>
9
22#include "ParameterLib/Utils.h"
24
25namespace ProcessLib
26{
27namespace LIE
28{
30{
31template <int DisplacementDim>
32std::unique_ptr<Process> createHydroMechanicsProcess(
33 std::string const& name,
34 MeshLib::Mesh& mesh,
35 std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
36 std::vector<ProcessVariable> const& variables,
37 std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
38 std::optional<ParameterLib::CoordinateSystem> const&
39 local_coordinate_system,
40 unsigned const integration_order,
41 BaseLib::ConfigTree const& config,
42 std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media)
43{
45 config.checkConfigParameter("type", "HYDRO_MECHANICS_WITH_LIE");
46 DBUG("Create HydroMechanicsProcess with LIE.");
47 auto const coupling_scheme =
49 config.getConfigParameterOptional<std::string>("coupling_scheme");
50 const bool use_monolithic_scheme =
51 !(coupling_scheme && (*coupling_scheme == "staggered"));
52
55 auto const pv_conf = config.getConfigSubtree("process_variables");
57 auto range =
59 pv_conf.getConfigParameterList<std::string>("process_variable");
60 std::vector<std::reference_wrapper<ProcessVariable>> p_u_process_variables;
61 std::vector<std::reference_wrapper<ProcessVariable>> p_process_variables;
62 std::vector<std::reference_wrapper<ProcessVariable>> u_process_variables;
63 std::vector<std::vector<std::reference_wrapper<ProcessVariable>>>
64 process_variables;
65 for (std::string const& pv_name : range)
66 {
67 if (pv_name != "pressure" && pv_name != "displacement" &&
68 !pv_name.starts_with("displacement_jump"))
69 {
71 "Found a process variable name '{}'. It should be "
72 "'displacement' or 'displacement_jumpN' or 'pressure'",
73 pv_name);
74 }
75 auto variable = std::find_if(variables.cbegin(), variables.cend(),
76 [&pv_name](ProcessVariable const& v)
77 { return v.getName() == pv_name; });
78
79 if (variable == variables.end())
80 {
82 "Could not find process variable '{:s}' in the provided "
83 "variables list for config tag <{:s}>.",
84 pv_name, "process_variable");
85 }
86 DBUG("Found process variable '{:s}' for config tag <{:s}>.",
87 variable->getName(), "process_variable");
88
89 if (pv_name.find("displacement") != std::string::npos &&
90 variable->getNumberOfGlobalComponents() != DisplacementDim)
91 {
93 "Number of components of the process variable '{:s}' is "
94 "different from the displacement dimension: got {:d}, expected "
95 "{:d}",
96 variable->getName(),
97 variable->getNumberOfGlobalComponents(),
98 DisplacementDim);
99 }
100
101 if (!use_monolithic_scheme)
102 {
103 if (pv_name == "pressure")
104 {
105 p_process_variables.emplace_back(
106 const_cast<ProcessVariable&>(*variable));
107 }
108 else
109 {
110 u_process_variables.emplace_back(
111 const_cast<ProcessVariable&>(*variable));
112 }
113 }
114 else
115 {
116 p_u_process_variables.emplace_back(
117 const_cast<ProcessVariable&>(*variable));
118 }
119 }
120
121 if (p_u_process_variables.size() > 3 || u_process_variables.size() > 2)
122 {
123 OGS_FATAL("Currently only one displacement jump is supported");
124 }
125
126 if (!use_monolithic_scheme)
127 {
128 process_variables.push_back(std::move(p_process_variables));
129 process_variables.push_back(std::move(u_process_variables));
130 }
131 else
132 {
133 process_variables.push_back(std::move(p_u_process_variables));
134 }
135
137 auto solid_constitutive_relations =
139 parameters, local_coordinate_system, materialIDs(mesh), config);
140
141 // Specific body force
142 Eigen::Matrix<double, DisplacementDim, 1> specific_body_force;
143 {
144 std::vector<double> const b =
146 config.getConfigParameter<std::vector<double>>(
147 "specific_body_force");
148 if (b.size() != DisplacementDim)
149 {
150 OGS_FATAL(
151 "The size of the specific body force vector does not match the "
152 "displacement dimension. Vector size is {:d}, displacement "
153 "dimension is {:d}",
154 b.size(), DisplacementDim);
155 }
156
157 std::copy_n(b.data(), b.size(), specific_body_force.data());
158 }
159
160 // Fracture constitutive relation.
161 std::unique_ptr<MaterialLib::Fracture::FractureModelBase<DisplacementDim>>
162 fracture_model = nullptr;
163 auto const opt_fracture_model_config =
165 config.getConfigSubtreeOptional("fracture_model");
166 if (opt_fracture_model_config)
167 {
168 auto& fracture_model_config = *opt_fracture_model_config;
169
170 auto const frac_type =
172 fracture_model_config.peekConfigParameter<std::string>("type");
173
174 if (frac_type == "LinearElasticIsotropic")
175 {
176 fracture_model =
178 DisplacementDim>(parameters, fracture_model_config);
179 }
180 else if (frac_type == "Coulomb")
181 {
182 fracture_model =
184 parameters, fracture_model_config);
185 }
186 else if (frac_type == "CohesiveZoneModeI")
187 {
190 fracture_model_config);
191 }
192 else
193 {
194 OGS_FATAL(
195 "Cannot construct fracture constitutive relation of given type "
196 "'{:s}'.",
197 frac_type);
198 }
199 }
200
201 // Fracture properties
202 std::vector<FractureProperty> fracture_properties;
203 for (
204 auto fracture_properties_config :
206 config.getConfigSubtreeList("fracture_properties"))
207 {
208 fracture_properties.emplace_back(
209 fracture_properties.size(),
211 fracture_properties_config.getConfigParameter<int>("material_id"),
214 fracture_properties_config, "initial_aperture", parameters, 1,
215 &mesh));
216 }
217
218 std::size_t const n_var_du =
219 ranges::accumulate(
220 process_variables | ranges::views::transform(ranges::size),
221 std::size_t{0}) -
222 2 /* for pressure and displacement */;
223 if (n_var_du != fracture_properties.size())
224 {
225 OGS_FATAL(
226 "The number of displacement jumps {} and the number of "
227 "<fracture_properties> {} are not consistent.",
228 n_var_du,
229 fracture_properties.size());
230 }
231
232 // initial effective stress in matrix
233 auto& initial_effective_stress = ParameterLib::findParameter<double>(
234 config,
236 "initial_effective_stress", parameters,
238 &mesh);
239 DBUG("Use '{:s}' as initial effective stress parameter.",
240 initial_effective_stress.name);
241
242 // initial effective stress in fracture
243 auto& initial_fracture_effective_stress = ParameterLib::findParameter<
244 double>(
245 config,
247 "initial_fracture_effective_stress", parameters, DisplacementDim,
248 &mesh);
249 DBUG("Use '{:s}' as initial fracture effective stress parameter.",
250 initial_fracture_effective_stress.name);
251
252 // deactivation of matrix elements in flow
253 auto opt_deactivate_matrix_in_flow =
255 config.getConfigParameterOptional<bool>("deactivate_matrix_in_flow");
256 bool const deactivate_matrix_in_flow =
257 opt_deactivate_matrix_in_flow && *opt_deactivate_matrix_in_flow;
258
259 if (deactivate_matrix_in_flow)
260 INFO("Deactivate matrix elements in flow calculation.");
261
263 auto const use_b_bar = config.getConfigParameter<bool>("use_b_bar", false);
264
265 auto media_map =
267
268 std::array const requiredMediumProperties = {
272 std::array const requiredFluidProperties = {MaterialPropertyLib::viscosity,
274 std::array const requiredSolidProperties = {MaterialPropertyLib::density};
275
277
278 for (auto const& medium : media_map.media())
279 {
280 checkRequiredProperties(*medium, requiredMediumProperties);
281 checkRequiredProperties(fluidPhase(*medium), requiredFluidProperties);
282 checkRequiredProperties(medium->phase("Solid"),
283 requiredSolidProperties);
284 }
285
286 // Check whether fracture permeability is given as a scalar value.
287 for (auto const& element_id : mesh.getElements() | MeshLib::views::ids)
288 {
289 media_map.checkElementHasMedium(element_id);
290 auto const& medium = *media_map.getMedium(element_id);
291
292 // For fracture element
293 if (mesh.getElement(element_id)->getDimension() != DisplacementDim)
294 {
297 auto const permeability =
299 .value(variables, x_position, 0.0 /*t*/, 0.0 /*dt*/);
300 if (!std::holds_alternative<double>(permeability))
301 {
302 OGS_FATAL(
303 "The permeability model for the fracture must be "
304 "isotropic, and it must return a scalar value.");
305 }
306 }
307 }
308
310 materialIDs(mesh), std::move(solid_constitutive_relations),
311 std::move(media_map), specific_body_force,
312 std::move(fracture_model), std::move(fracture_properties),
313 initial_effective_stress, initial_fracture_effective_stress,
314 deactivate_matrix_in_flow, use_b_bar};
315
316 SecondaryVariableCollection secondary_variables;
317
318 ProcessLib::createSecondaryVariables(config, secondary_variables);
319
320 return std::make_unique<HydroMechanicsProcess<DisplacementDim>>(
321 std::move(name), mesh, std::move(jacobian_assembler), parameters,
322 integration_order, std::move(process_variables),
323 std::move(process_data), std::move(secondary_variables),
324 use_monolithic_scheme);
325}
326
327template std::unique_ptr<Process> createHydroMechanicsProcess<2>(
328 std::string const& name,
329 MeshLib::Mesh& mesh,
330 std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
331 std::vector<ProcessVariable> const& variables,
332 std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
333 std::optional<ParameterLib::CoordinateSystem> const&
334 local_coordinate_system,
335 unsigned const integration_order,
336 BaseLib::ConfigTree const& config,
337 std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media);
338
339template std::unique_ptr<Process> createHydroMechanicsProcess<3>(
340 std::string const& name,
341 MeshLib::Mesh& mesh,
342 std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
343 std::vector<ProcessVariable> const& variables,
344 std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
345 std::optional<ParameterLib::CoordinateSystem> const&
346 local_coordinate_system,
347 unsigned const integration_order,
348 BaseLib::ConfigTree const& config,
349 std::map<int, std::shared_ptr<MaterialPropertyLib::Medium>> const& media);
350
351} // namespace HydroMechanics
352} // namespace LIE
353} // namespace ProcessLib
#define OGS_FATAL(...)
Definition Error.h:19
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:22
std::optional< ConfigTree > getConfigSubtreeOptional(std::string const &root) const
std::optional< T > getConfigParameterOptional(std::string const &param) const
T getConfigParameter(std::string const &param) const
Range< SubtreeIterator > getConfigSubtreeList(std::string const &root) const
ConfigTree getConfigSubtree(std::string const &root) const
Range< ValueIterator< T > > getConfigParameterList(std::string const &param) const
void checkConfigParameter(std::string const &param, std::string_view const value) const
virtual constexpr unsigned getDimension() const =0
Get dimension of the mesh element.
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition Mesh.h:100
const Element * getElement(std::size_t idx) const
Get the element with the given index.
Definition Mesh.h:85
Handles configuration of several secondary variables from the project file.
std::unique_ptr< FractureModelBase< DisplacementDim > > createCohesiveZoneModeI(std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters, BaseLib::ConfigTree const &config)
std::unique_ptr< FractureModelBase< DisplacementDim > > createLinearElasticIsotropic(std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters, BaseLib::ConfigTree const &config)
std::unique_ptr< FractureModelBase< DisplacementDim > > createCoulomb(std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters, BaseLib::ConfigTree const &config)
std::map< int, std::shared_ptr< MaterialLib::Solids::MechanicsBase< DisplacementDim > > > createConstitutiveRelations(std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters, std::optional< ParameterLib::CoordinateSystem > const &local_coordinate_system, MeshLib::PropertyVector< int > const *const material_ids, BaseLib::ConfigTree const &config)
void checkMPLPhasesForSinglePhaseFlow(MeshLib::Mesh const &mesh, MaterialPropertyLib::MaterialSpatialDistributionMap const &media_map)
MaterialSpatialDistributionMap createMaterialSpatialDistributionMap(std::map< int, std::shared_ptr< Medium > > const &media, MeshLib::Mesh const &mesh)
constexpr int kelvin_vector_dimensions(int const displacement_dim)
Kelvin vector dimensions for given displacement dimension.
constexpr ranges::views::view_closure ids
For an element of a range view return its id.
Definition Mesh.h:216
OGS_NO_DANGLING Parameter< ParameterDataType > & findParameter(std::string const &parameter_name, std::vector< std::unique_ptr< ParameterBase > > const &parameters, int const num_components, MeshLib::Mesh const *const mesh=nullptr)
template std::unique_ptr< Process > createHydroMechanicsProcess< 2 >(std::string const &name, MeshLib::Mesh &mesh, std::unique_ptr< ProcessLib::AbstractJacobianAssembler > &&jacobian_assembler, std::vector< ProcessVariable > const &variables, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters, std::optional< ParameterLib::CoordinateSystem > const &local_coordinate_system, unsigned const integration_order, BaseLib::ConfigTree const &config, std::map< int, std::shared_ptr< MaterialPropertyLib::Medium > > const &media)
std::unique_ptr< Process > createHydroMechanicsProcess(std::string const &name, MeshLib::Mesh &mesh, std::unique_ptr< ProcessLib::AbstractJacobianAssembler > &&jacobian_assembler, std::vector< ProcessVariable > const &variables, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters, std::optional< ParameterLib::CoordinateSystem > const &local_coordinate_system, unsigned const integration_order, BaseLib::ConfigTree const &config, std::map< int, std::shared_ptr< MaterialPropertyLib::Medium > > const &media)
template std::unique_ptr< Process > createHydroMechanicsProcess< 3 >(std::string const &name, MeshLib::Mesh &mesh, std::unique_ptr< ProcessLib::AbstractJacobianAssembler > &&jacobian_assembler, std::vector< ProcessVariable > const &variables, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters, std::optional< ParameterLib::CoordinateSystem > const &local_coordinate_system, unsigned const integration_order, BaseLib::ConfigTree const &config, std::map< int, std::shared_ptr< MaterialPropertyLib::Medium > > const &media)
void createSecondaryVariables(BaseLib::ConfigTree const &config, SecondaryVariableCollection &secondary_variables)