OGS
CreateMFrontGeneric.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
4#ifndef _WIN32
5#include <dlfcn.h>
6#endif
7
8#include "BaseLib/FileTools.h"
10#include "ParameterLib/Utils.h"
11
12namespace
13{
14const char* btypeToString(int btype)
15{
16 using B = mgis::behaviour::Behaviour;
17 if (btype == B::GENERALBEHAVIOUR)
18 return "GENERALBEHAVIOUR";
19 if (btype == B::STANDARDSTRAINBASEDBEHAVIOUR)
20 return "STANDARDSTRAINBASEDBEHAVIOUR";
21 if (btype == B::STANDARDFINITESTRAINBEHAVIOUR)
22 return "STANDARDFINITESTRAINBEHAVIOUR";
23 if (btype == B::COHESIVEZONEMODEL)
24 return "COHESIVEZONEMODEL";
25
26 OGS_FATAL("Unknown behaviour type {}.", btype);
27}
28
29const char* toString(mgis::behaviour::Behaviour::Kinematic kin)
30{
31 using K = mgis::behaviour::Behaviour::Kinematic;
32 switch (kin)
33 {
34 case K::UNDEFINEDKINEMATIC:
35 return "UNDEFINEDKINEMATIC";
36 case K::SMALLSTRAINKINEMATIC:
37 return "SMALLSTRAINKINEMATIC";
38 case K::COHESIVEZONEKINEMATIC:
39 return "COHESIVEZONEKINEMATIC";
40 case K::FINITESTRAINKINEMATIC_F_CAUCHY:
41 return "FINITESTRAINKINEMATIC_F_CAUCHY";
42 case K::FINITESTRAINKINEMATIC_ETO_PK1:
43 return "FINITESTRAINKINEMATIC_ETO_PK1";
44 }
45
46 OGS_FATAL("Unknown kinematic {}.", BaseLib::to_underlying(kin));
47}
48
49const char* toString(mgis::behaviour::Behaviour::Symmetry sym)
50{
51 using S = mgis::behaviour::Behaviour::Symmetry;
52 switch (sym)
53 {
54 case S::ISOTROPIC:
55 return "ISOTROPIC";
56 case S::ORTHOTROPIC:
57 return "ORTHOTROPIC";
58 }
59
60 OGS_FATAL("Unknown symmetry {}.", BaseLib::to_underlying(sym));
61}
62
64void varInfo(std::string const& msg,
65 std::vector<mgis::behaviour::Variable> const& vars,
66 mgis::behaviour::Hypothesis hypothesis)
67{
68 INFO("#{:s}: {:d} (array size {:d}).",
69 msg,
70 vars.size(),
71 mgis::behaviour::getArraySize(vars, hypothesis));
72 for (auto const& var : vars)
73 {
74 INFO(" --> type `{:s}' with name `{:s}', size {:d}, offset {:d}.",
76 var.name,
77 mgis::behaviour::getVariableSize(var, hypothesis),
78 mgis::behaviour::getVariableOffset(vars, var.name, hypothesis));
79 }
80}
81
83void varInfo(std::string const& msg, std::vector<std::string> const& parameters)
84{
85 INFO("#{:s}: {:d}.", msg, parameters.size());
86 for (auto const& parameter : parameters)
87 {
88 INFO(" --> with name `{:s}'.", parameter);
89 }
90}
91
92std::vector<ParameterLib::Parameter<double> const*> readMaterialProperties(
93 mgis::behaviour::Behaviour const& behaviour,
94 mgis::behaviour::Hypothesis const& hypothesis,
95 std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
96 BaseLib::ConfigTree const& config)
97{
98 if (behaviour.mps.empty())
99 {
100 return {};
101 }
102
103 std::map<std::string, std::string> map_name_to_param;
104
105 // gather material properties from the prj file
107 auto const mps_config = config.getConfigSubtree("material_properties");
108 for (
109 auto const& mp_config :
111 mps_config.getConfigParameterList("material_property"))
112 {
114 auto name = mp_config.getConfigAttribute<std::string>("name");
115 auto param_name =
117 mp_config.getConfigAttribute<std::string>("parameter");
118
119 map_name_to_param.emplace(std::move(name), std::move(param_name));
120 }
121
122 std::vector<ParameterLib::Parameter<double> const*> material_properties;
123 for (auto const& mp : behaviour.mps)
124 {
125 auto const it = map_name_to_param.find(mp.name);
126 if (it == map_name_to_param.end())
127 OGS_FATAL(
128 "Material Property `{:s}' has not been configured in the "
129 "project file.",
130 mp.name);
131
132 auto const& param_name = it->second;
133 auto const num_comp = mgis::behaviour::getVariableSize(mp, hypothesis);
134 auto const* param = &ParameterLib::findParameter<double>(
135 param_name, parameters, num_comp);
136
137 INFO("Using OGS parameter `{:s}' for material property `{:s}'.",
138 param_name, mp.name);
139
140 using V = mgis::behaviour::Variable;
141 if (mp.type == V::STENSOR || mp.type == V::TENSOR)
142 {
143 WARN(
144 "Material property `{:s}' is a tensorial quantity. You, "
145 "the "
146 "user, have to make sure that the component order of "
147 "parameter `{:s}' matches the one required by MFront!",
148 mp.name, param_name);
149 }
150
151 material_properties.push_back(param);
152 map_name_to_param.erase(it);
153 }
154
155 if (!map_name_to_param.empty())
156 {
157 ERR("Some material parameters that were configured are not used by "
158 "the material model.");
159 ERR("These parameters are:");
160
161 for (auto const& e : map_name_to_param)
162 {
163 ERR(" name: `{:s}', parameter: `{:s}'.", e.first, e.second);
164 }
165
166 OGS_FATAL(
167 "Configuration errors occurred. Please fix the project file.");
168 }
169
170 return material_properties;
171}
172
173// Very similar to above readMaterialProperties but does not generalize because
174// of config specific strings for ogs_file_param and return type.
175std::map<std::string, ParameterLib::Parameter<double> const*>
177 mgis::behaviour::Behaviour const& behaviour,
178 mgis::behaviour::Hypothesis const& hypothesis,
179 std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
180 BaseLib::ConfigTree const& config)
181{
182 if (behaviour.isvs.empty())
183 {
184 return {};
185 }
186
187 // gather state variables from the prj file
188 auto const initial_values_config =
190 config.getConfigSubtreeOptional("initial_values");
191 if (!initial_values_config)
192 {
193 return {};
194 }
195
196 std::map<std::string, std::string> map_name_to_param;
197 for (
198 auto const c :
200 initial_values_config->getConfigParameterList("state_variable"))
201 {
203 auto name = c.getConfigAttribute<std::string>("name");
205 auto param_name = c.getConfigAttribute<std::string>("parameter");
206
207 map_name_to_param.emplace(std::move(name), std::move(param_name));
208 }
209
210 std::map<std::string, ParameterLib::Parameter<double> const*>
211 state_variables_initial_properties;
212 for (auto const& isv : behaviour.isvs)
213 {
214 auto const it = map_name_to_param.find(isv.name);
215
216 // Not all internal state variables might need initialization and are
217 // skipped.
218 if (it == map_name_to_param.end())
219 {
220 continue;
221 }
222
223 auto const& param_name = it->second;
224 auto const num_comp = mgis::behaviour::getVariableSize(isv, hypothesis);
225 auto const* param = &ParameterLib::findParameter<double>(
226 param_name, parameters, num_comp);
227
228 INFO(
229 "Using OGS parameter `{:s}' for initial value of internal "
230 "state variable `{:s}'.",
231 param_name, isv.name);
232
233 using V = mgis::behaviour::Variable;
234 if (isv.type == V::STENSOR || isv.type == V::TENSOR)
235 {
236 WARN(
237 "State variable `{:s}' is a tensorial quantity. You, the user, "
238 "have to make sure that the component order of parameter "
239 "`{:s}' matches the one required by MFront!",
240 isv.name, param_name);
241 }
242
243 state_variables_initial_properties[isv.name] = param;
244 map_name_to_param.erase(it);
245 }
246
247 if (!map_name_to_param.empty())
248 {
249 ERR("Some state variables initial value parameters that were "
250 "configured are not used by the material model.");
251 ERR("These parameters are:");
252
253 for (auto const& e : map_name_to_param)
254 {
255 ERR(" name: `{:s}', parameter: `{:s}'.", e.first, e.second);
256 }
257
258 OGS_FATAL(
259 "Configuration errors occurred. Please fix the project file.");
260 }
261
262 return state_variables_initial_properties;
263}
264
265mgis::behaviour::Behaviour loadBehaviour(
266 std::string const& lib_path, std::string behaviour_name,
267 mgis::behaviour::Hypothesis const hypothesis)
268{
269 // Fix for https://gitlab.opengeosys.org/ogs/ogs/-/issues/3073
270 // Pre-load dependencies of mfront lib
271#ifndef _WIN32
272 dlopen("libTFELNUMODIS.so", RTLD_NOW);
273 dlopen("libTFELUtilities.so", RTLD_NOW);
274 dlopen("libTFELException.so", RTLD_NOW);
275#endif
276
277 std::optional<std::runtime_error> small_strain_load_error;
278
279 // Try small strains first.
280 try
281 {
282 return mgis::behaviour::load(lib_path, behaviour_name, hypothesis);
283 }
284 catch (std::runtime_error const& e)
285 {
286 // Didn't work, store the exception and try finite strain.
287 small_strain_load_error = e;
288 }
289
290 try
291 {
292 auto o = mgis::behaviour::FiniteStrainBehaviourOptions{};
293 o.stress_measure = mgis::behaviour::FiniteStrainBehaviourOptions::PK2;
294 o.tangent_operator =
295 mgis::behaviour::FiniteStrainBehaviourOptions::DS_DEGL;
296
297 return mgis::behaviour::load(o, lib_path, behaviour_name, hypothesis);
298 }
299 catch (std::runtime_error const& e)
300 {
301 if (small_strain_load_error)
302 {
303 OGS_FATAL(
304 "Could not load the {} from {} neither for small strains "
305 "(error {}) nor for finite strains (error {}).",
306 behaviour_name, lib_path, small_strain_load_error->what(),
307 e.what());
308 }
309 }
310
311 OGS_FATAL("Could not load the {} from {}.", behaviour_name, lib_path);
312}
313} // namespace
314
316{
317
319 int const displacement_dim,
320 std::vector<std::unique_ptr<ParameterLib::ParameterBase>> const& parameters,
321 BaseLib::ConfigTree const& config)
322{
323 INFO("### MFRONT ########################################################");
324
326 config.checkConfigParameter("type", "MFront");
327
329 auto const library = config.getConfigSubtreeOptional("library");
330
331 bool const library_path_is_relative_to_prj_file =
332 library /* If no library tag is specified in the prj file, the lib
333 shipped with OGS is used, whose path is not relative to the
334 project file. */
335 &&
337 library->getConfigAttribute("path_is_relative_to_prj_file", true);
338
339 std::string const library_name =
340 library ? library->getValue<std::string>() : "libOgsMFrontBehaviour";
341
342 auto const lib_path =
343 library_path_is_relative_to_prj_file
344 ? BaseLib::joinPaths(config.projectDirectory(), library_name)
345 : library_name;
346
347 mgis::behaviour::Hypothesis hypothesis;
348 if (displacement_dim == 2)
349 {
350 // TODO support the axial symmetry modelling hypothesis.
351 WARN(
352 "The model is defined in 2D. On the material level currently a "
353 "plane strain setting is used. In particular it is not checked if "
354 "axial symmetry or plane stress are assumed. Special material "
355 "behaviour for these settings is currently not supported.");
356 hypothesis = mgis::behaviour::Hypothesis::PLANESTRAIN;
357 }
358 else if (displacement_dim == 3)
359 {
360 hypothesis = mgis::behaviour::Hypothesis::TRIDIMENSIONAL;
361 }
362 else
363 {
364 OGS_FATAL("Displacement dim {} is not supported.", displacement_dim);
365 }
366
367 auto behaviour = loadBehaviour(
368 lib_path,
370 config.getConfigParameter<std::string>("behaviour"),
371 hypothesis);
372
373 INFO("Behaviour: `{:s}'.", behaviour.behaviour);
374 INFO("Hypothesis: `{:s}'.", mgis::behaviour::toString(hypothesis));
375 INFO("Source: `{:s}'.", behaviour.source);
376 INFO("TFEL version: `{:s}'.", behaviour.tfel_version);
377 INFO("Behaviour type: `{:s}'.", btypeToString(behaviour.btype));
378 INFO("Kinematic: `{:s}'.", toString(behaviour.kinematic));
379 INFO("Symmetry: `{:s}'.", toString(behaviour.symmetry));
380
381 varInfo("Mat. props.", behaviour.mps, hypothesis);
382 varInfo("Gradients", behaviour.gradients, hypothesis);
383 varInfo("Thdyn. forces", behaviour.thermodynamic_forces, hypothesis);
384 varInfo("Int. StVars.", behaviour.isvs, hypothesis);
385 varInfo("Ext. StVars.", behaviour.esvs, hypothesis);
386
387 // TODO read parameters from prj file, not yet (2018-11-05) supported by
388 // MGIS library.
389 varInfo("Real-valued parameters", behaviour.params);
390 varInfo("Integer parameters", behaviour.iparams);
391 varInfo("Unsigned parameters", behaviour.usparams);
392
393 INFO("#Tangent operator blocks: {}.", behaviour.to_blocks.size());
394 for (auto const& [var1, var2] : behaviour.to_blocks)
395 {
396 INFO(" --> ({}, {}).", var1.name, var2.name);
397 }
398
399 std::vector<ParameterLib::Parameter<double> const*> material_properties =
400 readMaterialProperties(behaviour, hypothesis, parameters, config);
401
402 std::map<std::string, ParameterLib::Parameter<double> const*>
403 state_variables_initial_properties =
404 readStateVariablesInitialValueProperties(behaviour, hypothesis,
405 parameters, config);
406
407 INFO("### MFRONT END ####################################################");
408
409 return {std::move(behaviour), std::move(material_properties),
410 std::move(state_variables_initial_properties)};
411}
412
413} // namespace MaterialLib::Solids::MFront
#define OGS_FATAL(...)
Definition Error.h:19
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
std::optional< ConfigTree > getConfigSubtreeOptional(std::string const &root) const
std::filesystem::path projectDirectory() const
T getConfigParameter(std::string const &param) const
ConfigTree getConfigSubtree(std::string const &root) const
void checkConfigParameter(std::string const &param, std::string_view const value) const
constexpr auto to_underlying(E e) noexcept
Converts an enumeration to its underlying type.
Definition cpp23.h:22
std::string joinPaths(std::string const &pathA, std::string const &pathB)
MFrontConfig createMFrontConfig(int const displacement_dim, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters, BaseLib::ConfigTree const &config)
const char * varTypeToString(int v)
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)
std::vector< ParameterLib::Parameter< double > const * > readMaterialProperties(mgis::behaviour::Behaviour const &behaviour, mgis::behaviour::Hypothesis const &hypothesis, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters, BaseLib::ConfigTree const &config)
void varInfo(std::string const &msg, std::vector< mgis::behaviour::Variable > const &vars, mgis::behaviour::Hypothesis hypothesis)
Prints info about MFront variables.
const char * toString(mgis::behaviour::Behaviour::Kinematic kin)
std::map< std::string, ParameterLib::Parameter< double > const * > readStateVariablesInitialValueProperties(mgis::behaviour::Behaviour const &behaviour, mgis::behaviour::Hypothesis const &hypothesis, std::vector< std::unique_ptr< ParameterLib::ParameterBase > > const &parameters, BaseLib::ConfigTree const &config)
mgis::behaviour::Behaviour loadBehaviour(std::string const &lib_path, std::string behaviour_name, mgis::behaviour::Hypothesis const hypothesis)