From 573e2b426b0e61366252e3488d790e0124446fb6 Mon Sep 17 00:00:00 2001 From: Christoph Lehmann <christoph.lehmann@ufz.de> Date: Wed, 7 Nov 2018 10:44:09 +0100 Subject: [PATCH] [Mat] added a solid model interfacing with MFront --- MaterialLib/SolidModels/MFront/CMakeLists.txt | 26 ++ .../SolidModels/MFront/CreateMFront.cpp | 222 ++++++++++++ MaterialLib/SolidModels/MFront/CreateMFront.h | 38 ++ MaterialLib/SolidModels/MFront/MFront.cpp | 336 ++++++++++++++++++ MaterialLib/SolidModels/MFront/MFront.h | 116 ++++++ 5 files changed, 738 insertions(+) create mode 100644 MaterialLib/SolidModels/MFront/CMakeLists.txt create mode 100644 MaterialLib/SolidModels/MFront/CreateMFront.cpp create mode 100644 MaterialLib/SolidModels/MFront/CreateMFront.h create mode 100644 MaterialLib/SolidModels/MFront/MFront.cpp create mode 100644 MaterialLib/SolidModels/MFront/MFront.h diff --git a/MaterialLib/SolidModels/MFront/CMakeLists.txt b/MaterialLib/SolidModels/MFront/CMakeLists.txt new file mode 100644 index 00000000000..a693ff0a812 --- /dev/null +++ b/MaterialLib/SolidModels/MFront/CMakeLists.txt @@ -0,0 +1,26 @@ +set(SOURCES CreateMFront.cpp CreateMFront.h) + +if(OGS_USE_MFRONT) + list(APPEND SOURCES MFront.cpp MFront.h) +endif() + +add_library(MaterialLib_SolidModels_MFront ${SOURCES}) + +if(BUILD_SHARED_LIBS) + install(TARGETS MaterialLib_SolidModels_MFront LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif() + +target_link_libraries(MaterialLib_SolidModels_MFront + PUBLIC BaseLib NumLib logog + PRIVATE MathLib MeshLib +) + +if (OGS_USE_MFRONT) + target_include_directories(MaterialLib_SolidModels_MFront + PUBLIC ${MGIS_INCLUDE_DIR} + ) + target_link_libraries(MaterialLib_SolidModels_MFront + PUBLIC ${MGIS_LIBRARY} + ) + target_compile_definitions(MaterialLib_SolidModels_MFront PRIVATE OGS_USE_MFRONT) +endif() diff --git a/MaterialLib/SolidModels/MFront/CreateMFront.cpp b/MaterialLib/SolidModels/MFront/CreateMFront.cpp new file mode 100644 index 00000000000..0cc87c43b46 --- /dev/null +++ b/MaterialLib/SolidModels/MFront/CreateMFront.cpp @@ -0,0 +1,222 @@ +/** + * \copyright + * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#include "CreateMFront.h" + +#ifdef OGS_USE_MFRONT + +#include "MFront.h" + +#include "BaseLib/FileTools.h" +#include "ProcessLib/Utils/ProcessUtils.h" + +namespace +{ +/// Prints info about MFront variables. +void varInfo(std::string const& msg, + std::vector<mgis::behaviour::Variable> const& vars, + mgis::behaviour::Hypothesis hypothesis) +{ + INFO("#%s: %lu (array size %lu).", + msg.c_str(), + vars.size(), + mgis::behaviour::getArraySize(vars, hypothesis)); + for (auto& var : vars) + { + INFO(" --> type `%s' with name `%s', size %lu, offset %lu.", + MaterialLib::Solids::MFront::varTypeToString(var.type), + var.name.c_str(), + mgis::behaviour::getVariableSize(var, hypothesis), + mgis::behaviour::getVariableOffset(vars, var.name, hypothesis)); + } +} +} // anonymous namespace + +namespace MaterialLib +{ +namespace Solids +{ +namespace MFront +{ +template <int DisplacementDim> +std::unique_ptr<MechanicsBase<DisplacementDim>> createMFront( + std::vector<std::unique_ptr<ProcessLib::ParameterBase>> const& parameters, + BaseLib::ConfigTree const& config) +{ + INFO("### MFRONT ########################################################"); + + //! \ogs_file_param{material__solid__constitutive_relation__type} + config.checkConfigParameter("type", "MFront"); + + auto const lib_path = BaseLib::joinPaths( + BaseLib::getProjectDirectory(), + //! \ogs_file_param{material__solid__constitutive_relation__MFront__library} + config.getConfigParameter<std::string>("library")); + auto const behaviour_name = + //! \ogs_file_param{material__solid__constitutive_relation__MFront__behaviour} + config.getConfigParameter<std::string>("behaviour"); + + static_assert(DisplacementDim == 2 || DisplacementDim == 3, + "Given DisplacementDim not supported."); + + mgis::behaviour::Hypothesis hypothesis; + if (DisplacementDim == 2) + { + // TODO support the axial symmetry modelling hypothesis. + WARN( + "The model is defined in 2D. On the material level currently a " + "plane strain setting is used. In particular it is not checked if " + "axial symmetry or plane stress are assumed. Special material " + "behaviour for these settings is currently not supported."); + hypothesis = mgis::behaviour::Hypothesis::PLANESTRAIN; + } + else if (DisplacementDim == 3) + { + hypothesis = mgis::behaviour::Hypothesis::TRIDIMENSIONAL; + } + + auto behaviour = + mgis::behaviour::load(lib_path, behaviour_name, hypothesis); + + INFO("Behaviour: `%s'.", behaviour.behaviour.c_str()); + INFO("Hypothesis: `%s'.", mgis::behaviour::toString(hypothesis)); + INFO("Source: `%s'.", behaviour.source.c_str()); + INFO("TFEL version: `%s'.", behaviour.tfel_version.c_str()); + INFO("Behaviour type: `%s'.", btypeToString(behaviour.btype)); + INFO("Kinematic: `%s'.", toString(behaviour.kinematic)); + INFO("Symmetry: `%s'.", toString(behaviour.symmetry)); + + varInfo("Mat. props.", behaviour.mps, hypothesis); + varInfo("Gradients", behaviour.gradients, hypothesis); + varInfo("Thdyn. forces", behaviour.thermodynamic_forces, hypothesis); + varInfo("Int. StVars.", behaviour.isvs, hypothesis); + varInfo("Ext. StVars.", behaviour.esvs, hypothesis); + + // TODO read parameters from prj file, not yet (2018-11-05) supported by + // MGIS library. + varInfo("Parameters", behaviour.parameters, hypothesis); + + std::vector<ProcessLib::Parameter<double> const*> material_properties; + + if (!behaviour.mps.empty()) + { + std::map<std::string, std::string> map_name_to_param; + + // gather material properties from the prj file + //! \ogs_file_param{material__solid__constitutive_relation__MFront__material_properties} + auto const mps_config = config.getConfigSubtree("material_properties"); + for ( + auto const mp_config : + //! \ogs_file_param{material__solid__constitutive_relation__MFront__material_properties__material_property} + mps_config.getConfigParameterList("material_property")) + { + //! \ogs_file_attr{material__solid__constitutive_relation__MFront__material_properties__material_property__name} + auto name = mp_config.getConfigAttribute<std::string>("name"); + auto const param_name = + //! \ogs_file_attr{material__solid__constitutive_relation__MFront__material_properties__material_property__parameter} + mp_config.getConfigAttribute<std::string>("parameter"); + + map_name_to_param.emplace(std::move(name), std::move(param_name)); + } + + for (auto& mp : behaviour.mps) + { + auto const it = map_name_to_param.find(mp.name); + if (it == map_name_to_param.end()) + OGS_FATAL( + "Material Property `%s' has not been configured in the " + "project file.", + mp.name.c_str()); + + auto const param_name = it->second; + auto const num_comp = + mgis::behaviour::getVariableSize(mp, hypothesis); + auto const* param = &ProcessLib::findParameter<double>( + param_name, parameters, num_comp); + + INFO("Using OGS parameter `%s' for material property `%s'.", + param_name.c_str(), mp.name.c_str()); + + using V = mgis::behaviour::Variable; + if (mp.type == V::STENSOR || mp.type == V::TENSOR) + { + WARN( + "Material property `%s' is a tensorial quantity. You, the " + "user, have to make sure that the component order of " + "parameter `%s' matches the one required by MFront!", + mp.name.c_str(), param_name.c_str()); + } + + material_properties.push_back(param); + map_name_to_param.erase(it); + } + + if (!map_name_to_param.empty()) + { + ERR("Some material parameters that were configured are not used by " + "the material model."); + ERR("These parameters are:"); + + for (auto& e : map_name_to_param) + { + ERR(" name: `%s', parameter: `%s'.", e.first.c_str(), + e.second.c_str()); + } + + OGS_FATAL( + "Configuration errors occured. Please fix the project file."); + } + } + + INFO("### MFRONT END ####################################################"); + + return std::make_unique<MFront<DisplacementDim>>( + std::move(behaviour), std::move(material_properties)); +} +} // namespace MFront +} // namespace Solids +} // namespace MaterialLib + +#else // OGS_USE_MFRONT + +namespace MaterialLib +{ +namespace Solids +{ +namespace MFront +{ +template <int DisplacementDim> +std::unique_ptr<MechanicsBase<DisplacementDim>> createMFront( + std::vector< + std::unique_ptr<ProcessLib::ParameterBase>> const& /*parameters*/, + BaseLib::ConfigTree const& /*config*/) +{ + OGS_FATAL("OpenGeoSys has not been build with MFront support."); +} +} // namespace MFront +} // namespace Solids +} // namespace MaterialLib + +#endif // OGS_USE_MFRONT + +namespace MaterialLib +{ +namespace Solids +{ +namespace MFront +{ +template std::unique_ptr<MechanicsBase<2>> createMFront<2>( + std::vector<std::unique_ptr<ProcessLib::ParameterBase>> const& parameters, + BaseLib::ConfigTree const& config); +template std::unique_ptr<MechanicsBase<3>> createMFront<3>( + std::vector<std::unique_ptr<ProcessLib::ParameterBase>> const& parameters, + BaseLib::ConfigTree const& config); +} // namespace MFront +} // namespace Solids +} // namespace MaterialLib diff --git a/MaterialLib/SolidModels/MFront/CreateMFront.h b/MaterialLib/SolidModels/MFront/CreateMFront.h new file mode 100644 index 00000000000..4df0a9a8236 --- /dev/null +++ b/MaterialLib/SolidModels/MFront/CreateMFront.h @@ -0,0 +1,38 @@ +/** + * \copyright + * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#pragma once + +#include <memory> +#include <vector> + +#include "BaseLib/ConfigTree.h" +#include "MaterialLib/SolidModels/MechanicsBase.h" +#include "ProcessLib/Parameter/Parameter.h" + +namespace MaterialLib +{ +namespace Solids +{ +namespace MFront +{ +template <int DisplacementDim> +std::unique_ptr<MechanicsBase<DisplacementDim>> createMFront( + std::vector<std::unique_ptr<ProcessLib::ParameterBase>> const& parameters, + BaseLib::ConfigTree const& config); + +extern template std::unique_ptr<MechanicsBase<2>> createMFront<2>( + std::vector<std::unique_ptr<ProcessLib::ParameterBase>> const& parameters, + BaseLib::ConfigTree const& config); +extern template std::unique_ptr<MechanicsBase<3>> createMFront<3>( + std::vector<std::unique_ptr<ProcessLib::ParameterBase>> const& parameters, + BaseLib::ConfigTree const& config); +} // namespace MFront +} // namespace Solids +} // namespace MaterialLib diff --git a/MaterialLib/SolidModels/MFront/MFront.cpp b/MaterialLib/SolidModels/MFront/MFront.cpp new file mode 100644 index 00000000000..a6c15cdbcf8 --- /dev/null +++ b/MaterialLib/SolidModels/MFront/MFront.cpp @@ -0,0 +1,336 @@ +/** + * \copyright + * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#include "MFront.h" + +#include <MGIS/Behaviour/Integrate.hxx> + +namespace +{ +/// Converts between OGSes and MFront's Kelvin vector indices. +constexpr std::ptrdiff_t OGSToMFront(std::ptrdiff_t i) +{ + // MFront: 11 22 33 12 13 23 + // OGS: 11 22 33 12 23 13 + if (i < 4) + return i; + if (i == 4) + return 5; + return 4; +} +/// Converts between OGSes and MFront's Kelvin vector indices. +constexpr std::ptrdiff_t MFrontToOGS(std::ptrdiff_t i) +{ + // MFront: 11 22 33 12 13 23 + // OGS: 11 22 33 12 23 13 + return OGSToMFront(i); // Same algorithm: indices 4 and 5 swapped. +} + +/// Converts between OGSes and MFront's Kelvin vectors and matrices. +template <typename Derived> +typename Derived::PlainObject OGSToMFront(Eigen::DenseBase<Derived> const& m) +{ + static_assert(Derived::RowsAtCompileTime != Eigen::Dynamic, "Error"); + static_assert(Derived::ColsAtCompileTime != Eigen::Dynamic, "Error"); + + typename Derived::PlainObject n; + + // optimal for row-major storage order + for (std::ptrdiff_t r = 0; r < Eigen::DenseBase<Derived>::RowsAtCompileTime; + ++r) + { + auto const R = OGSToMFront(r); + for (std::ptrdiff_t c = 0; + c < Eigen::DenseBase<Derived>::ColsAtCompileTime; + ++c) + { + auto const C = OGSToMFront(c); + n(R, C) = m(r, c); + } + } + + return n; +} + +/// Converts between OGSes and MFront's Kelvin vectors and matrices. +template <typename Derived> +typename Derived::PlainObject MFrontToOGS(Eigen::DenseBase<Derived> const& m) +{ + static_assert(Derived::RowsAtCompileTime != Eigen::Dynamic, "Error"); + static_assert(Derived::ColsAtCompileTime != Eigen::Dynamic, "Error"); + + typename Derived::PlainObject n; + + // optimal for row-major storage order + for (std::ptrdiff_t r = 0; r < Eigen::DenseBase<Derived>::RowsAtCompileTime; + ++r) + { + auto const R = MFrontToOGS(r); + for (std::ptrdiff_t c = 0; + c < Eigen::DenseBase<Derived>::ColsAtCompileTime; + ++c) + { + auto const C = MFrontToOGS(c); + n(R, C) = m(r, c); + } + } + + return n; +} + +} // namespace + +namespace MaterialLib +{ +namespace Solids +{ +namespace MFront +{ +const char* toString(mgis::behaviour::Behaviour::Kinematic kin) +{ + using K = mgis::behaviour::Behaviour::Kinematic; + switch (kin) + { + case K::UNDEFINEDKINEMATIC: + return "UNDEFINEDKINEMATIC"; + case K::SMALLSTRAINKINEMATIC: + return "SMALLSTRAINKINEMATIC"; + case K::COHESIVEZONEKINEMATIC: + return "COHESIVEZONEKINEMATIC"; + case K::FINITESTRAINKINEMATIC_F_CAUCHY: + return "FINITESTRAINKINEMATIC_F_CAUCHY"; + case K::FINITESTRAINKINEMATIC_ETO_PK1: + return "FINITESTRAINKINEMATIC_ETO_PK1"; + } + + OGS_FATAL("Unknown kinematic %d.", kin); +} + +const char* toString(mgis::behaviour::Behaviour::Symmetry sym) +{ + using S = mgis::behaviour::Behaviour::Symmetry; + switch (sym) + { + case S::ISOTROPIC: + return "ISOTROPIC"; + case S::ORTHOTROPIC: + return "ORTHOTROPIC"; + } + + OGS_FATAL("Unknown symmetry %d.", sym); +} +const char* btypeToString(int btype) +{ + using B = mgis::behaviour::Behaviour; + if (btype == B::GENERALBEHAVIOUR) + return "GENERALBEHAVIOUR"; + if (btype == B::STANDARDSTRAINBASEDBEHAVIOUR) + return "STANDARDSTRAINBASEDBEHAVIOUR"; + if (btype == B::STANDARDFINITESTRAINBEHAVIOUR) + return "STANDARDFINITESTRAINBEHAVIOUR"; + if (btype == B::COHESIVEZONEMODEL) + return "COHESIVEZONEMODEL"; + + OGS_FATAL("Unknown behaviour type %d.", btype); +} +const char* varTypeToString(int v) +{ + using V = mgis::behaviour::Variable; + if (v == V::SCALAR) + return "SCALAR"; + if (v == V::VECTOR) + return "VECTOR"; + if (v == V::STENSOR) + return "STENSOR"; + if (v == V::TENSOR) + return "TENSOR"; + + OGS_FATAL("Unknown variable type %d.", v); +} + +template <int DisplacementDim> +MFront<DisplacementDim>::MFront( + mgis::behaviour::Behaviour&& behaviour, + std::vector<ProcessLib::Parameter<double> const*>&& material_properties) + : _behaviour(std::move(behaviour)), + _material_properties(std::move(material_properties)) +{ + auto const hypothesis = behaviour.hypothesis; + + if (_behaviour.symmetry != mgis::behaviour::Behaviour::Symmetry::ISOTROPIC) + OGS_FATAL( + "The storage order of the stiffness matrix is not tested, yet. " + "Thus, we cannot be sure if we compute the behaviour of " + "anisotropic materials correctly. Therefore, currently only " + "isotropic materials are allowed."); + + if (_behaviour.gradients.size() != 1) + OGS_FATAL( + "The behaviour must have exactly a single gradient as input."); + + if (_behaviour.gradients[0].name != "Strain") + OGS_FATAL("The behaviour must be driven by strain."); + + if (_behaviour.gradients[0].type != mgis::behaviour::Variable::STENSOR) + OGS_FATAL("Strain must be a symmetric tensor."); + + if (mgis::behaviour::getVariableSize(_behaviour.gradients[0], hypothesis) != + MFront<DisplacementDim>::KelvinVector::SizeAtCompileTime) + OGS_FATAL("Strain must have %ld components instead of %lu.", + MFront<DisplacementDim>::KelvinVector::SizeAtCompileTime, + mgis::behaviour::getVariableSize(_behaviour.gradients[0], + hypothesis)); + + if (_behaviour.thermodynamic_forces.size() != 1) + OGS_FATAL( + "The behaviour must compute exactly one thermodynamic force."); + + if (_behaviour.thermodynamic_forces[0].name != "Stress") + OGS_FATAL("The behaviour must compute stress."); + + if (_behaviour.thermodynamic_forces[0].type != + mgis::behaviour::Variable::STENSOR) + OGS_FATAL("Stress must be a symmetric tensor."); + + if (mgis::behaviour::getVariableSize(_behaviour.thermodynamic_forces[0], + hypothesis) != + MFront<DisplacementDim>::KelvinVector::SizeAtCompileTime) + OGS_FATAL("Stress must have %ld components instead of %lu.", + MFront<DisplacementDim>::KelvinVector::SizeAtCompileTime, + mgis::behaviour::getVariableSize( + _behaviour.thermodynamic_forces[0], hypothesis)); + + if (!_behaviour.esvs.empty()) + { + if (_behaviour.esvs[0].name != "Temperature") + { + OGS_FATAL( + "Only temperature is supported as external state variable."); + } + + if (mgis::behaviour::getVariableSize(_behaviour.esvs[0], hypothesis) != + 1) + OGS_FATAL( + "Temperature must be a scalar instead of having %lu " + "components.", + mgis::behaviour::getVariableSize( + _behaviour.thermodynamic_forces[0], hypothesis)); + } +} + +template <int DisplacementDim> +std::unique_ptr<typename MechanicsBase<DisplacementDim>::MaterialStateVariables> +MFront<DisplacementDim>::createMaterialStateVariables() const +{ + return std::make_unique<MaterialStateVariables>(_behaviour); +} + +template <int DisplacementDim> +boost::optional<std::tuple<typename MFront<DisplacementDim>::KelvinVector, + std::unique_ptr<typename MechanicsBase< + DisplacementDim>::MaterialStateVariables>, + typename MFront<DisplacementDim>::KelvinMatrix>> +MFront<DisplacementDim>::integrateStress( + double const t, + ProcessLib::SpatialPosition const& x, + double const dt, + KelvinVector const& /*eps_prev*/, + KelvinVector const& eps, + KelvinVector const& /*sigma_prev*/, + typename MechanicsBase<DisplacementDim>::MaterialStateVariables const& + material_state_variables, + double const T) const +{ + assert( + dynamic_cast<MaterialStateVariables const*>(&material_state_variables)); + auto& d = + static_cast<MaterialStateVariables const&>(material_state_variables) + ._data; + + // TODO add a test of material behaviour where the value of dt matters. + d.dt = dt; + d.rdt = 1.0; + d.K[0] = 4.0; // if K[0] is greater than 3.5, the consistent tangent + // operator must be computed. + + // evaluate parameters at (t, x) + { + auto out = d.s1.material_properties.begin(); + for (auto* param : _material_properties) + { + auto const& vals = (*param)(t, x); + out = std::copy(vals.begin(), vals.end(), out); + } + } + + if (!d.s1.external_state_variables.empty()) + { + // assuming that there is only temperature + d.s1.external_state_variables[0] = T; + } + + auto v = mgis::behaviour::make_view(d); + + auto const eps_MFront = OGSToMFront(eps); + for (auto i = 0; i < KelvinVector::SizeAtCompileTime; ++i) + { + v.s1.gradients[i] = eps_MFront[i]; + } + + auto const status = mgis::behaviour::integrate(v, _behaviour); + if (status != 1) + { + OGS_FATAL("Integration failed with status %i.", status); + } + + KelvinVector sigma; + for (auto i = 0; i < KelvinVector::SizeAtCompileTime; ++i) + { + sigma[i] = d.s1.thermodynamic_forces[i]; + } + sigma = MFrontToOGS(sigma); + + // TODO row- vs. column-major storage order. This should only matter for + // anisotropic materials. + if (d.K.size() != + KelvinMatrix::RowsAtCompileTime * KelvinMatrix::ColsAtCompileTime) + OGS_FATAL("Stiffness matrix has wrong size."); + + KelvinMatrix C = MFrontToOGS(Eigen::Map<KelvinMatrix>(d.K.data())); + + // TODO avoid copying the state + auto state_copy = std::make_unique<MaterialStateVariables>( + static_cast<MaterialStateVariables const&>(material_state_variables)); + std::unique_ptr< + typename MechanicsBase<DisplacementDim>::MaterialStateVariables> + state_upcast(state_copy.release()); + + return {{std::move(sigma), std::move(state_upcast), std::move(C)}}; +} + +template <int DisplacementDim> +double MFront<DisplacementDim>::computeFreeEnergyDensity( + double const /*t*/, + ProcessLib::SpatialPosition const& /*x*/, + double const /*dt*/, + KelvinVector const& /*eps*/, + KelvinVector const& /*sigma*/, + typename MechanicsBase<DisplacementDim>::MaterialStateVariables const& + /*material_state_variables*/) const +{ + // TODO implement + return std::numeric_limits<double>::quiet_NaN(); +} + +template class MFront<2>; +template class MFront<3>; + +} // namespace MFront +} // namespace Solids +} // namespace MaterialLib diff --git a/MaterialLib/SolidModels/MFront/MFront.h b/MaterialLib/SolidModels/MFront/MFront.h new file mode 100644 index 00000000000..85d26a25c42 --- /dev/null +++ b/MaterialLib/SolidModels/MFront/MFront.h @@ -0,0 +1,116 @@ +/** + * \copyright + * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/project/license + * + */ + +#pragma once + +#include "MaterialLib/SolidModels/MechanicsBase.h" + +#include <MGIS/Behaviour/Behaviour.hxx> +#include <MGIS/Behaviour/BehaviourData.hxx> + +#include "ProcessLib/Parameter/Parameter.h" + +namespace MaterialLib +{ +namespace Solids +{ +namespace MFront +{ +/// Converts MGIS kinematic to a string representation. +const char* toString(mgis::behaviour::Behaviour::Kinematic); + +/// Converts MGIS symmetry to a string representation. +const char* toString(mgis::behaviour::Behaviour::Symmetry); + +/// Converts MGIS behaviour type to a string representation. +const char* btypeToString(int); + +/// Converts MGIS variable type to a string representation. +const char* varTypeToString(int); + +/// Uses a material model provided by MFront (via MFront's generic interface and +/// the MGIS library). +template <int DisplacementDim> +class MFront : public MechanicsBase<DisplacementDim> +{ +public: + struct MaterialStateVariables + : public MechanicsBase<DisplacementDim>::MaterialStateVariables + { + explicit MaterialStateVariables(mgis::behaviour::Behaviour const& b) + : _data{b} + { + } + + MaterialStateVariables(MaterialStateVariables const&) = default; + + void pushBackState() override { mgis::behaviour::update(_data); } + + MaterialStateVariables& operator=(MaterialStateVariables const&) = + default; + + typename MechanicsBase<DisplacementDim>::MaterialStateVariables& + operator=(typename MechanicsBase<DisplacementDim>:: + MaterialStateVariables const& state) noexcept override + { + return operator=(static_cast<MaterialStateVariables const&>(state)); + } + + // TODO fix: this has to be mutable. + mutable mgis::behaviour::BehaviourData _data; + }; + + using KelvinVector = + MathLib::KelvinVector::KelvinVectorType<DisplacementDim>; + using KelvinMatrix = + MathLib::KelvinVector::KelvinMatrixType<DisplacementDim>; + + MFront(mgis::behaviour::Behaviour&& behaviour, + std::vector<ProcessLib::Parameter<double> const*>&& + material_properties); + + std::unique_ptr< + typename MechanicsBase<DisplacementDim>::MaterialStateVariables> + createMaterialStateVariables() const override; + + boost::optional<std::tuple<KelvinVector, + std::unique_ptr<typename MechanicsBase< + DisplacementDim>::MaterialStateVariables>, + KelvinMatrix>> + integrateStress( + double const t, + ProcessLib::SpatialPosition const& x, + double const dt, + KelvinVector const& eps_prev, + KelvinVector const& eps, + KelvinVector const& sigma_prev, + typename MechanicsBase<DisplacementDim>::MaterialStateVariables const& + material_state_variables, + double const T) const override; + + double computeFreeEnergyDensity( + double const t, + ProcessLib::SpatialPosition const& x, + double const dt, + KelvinVector const& eps, + KelvinVector const& sigma, + typename MechanicsBase<DisplacementDim>::MaterialStateVariables const& + material_state_variables) const override; + +private: + mgis::behaviour::Behaviour _behaviour; + std::vector<ProcessLib::Parameter<double> const*> _material_properties; +}; + +extern template class MFront<2>; +extern template class MFront<3>; + +} // namespace MFront +} // namespace Solids +} // namespace MaterialLib -- GitLab