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