diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index b734d35e0..c4ef70381 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,132 +1,133 @@ #=============================================================================== # @file CMakeLists.txt # # @author Nicolas Richart # # @date creation: Fri Dec 12 2014 # @date last modification: Mon Jan 18 2016 # # @brief CMake file for the python wrapping of akantu # # @section LICENSE # # Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory # (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # #=============================================================================== if(NOT SKBUILD) package_get_all_include_directories( AKANTU_LIBRARY_INCLUDE_DIRS ) package_get_all_external_informations( PRIVATE_INCLUDE AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR INTERFACE_INCLUDE AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR LIBRARIES AKANTU_EXTERNAL_LIBRARIES ) endif() set(PYAKANTU_SRCS py_aka_common.cc py_aka_error.cc py_akantu.cc py_boundary_conditions.cc py_fe_engine.cc py_group_manager.cc py_mesh.cc py_model.cc py_parser.cc py_solver.cc ) package_is_activated(iohelper _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_dumpable.cc ) endif() package_is_activated(solid_mechanics _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_solid_mechanics_model.cc py_material.cc + py_material_selector.cc ) endif() package_is_activated(cohesive_element _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_solid_mechanics_model_cohesive.cc py_fragment_manager.cc ) endif() package_is_activated(heat_transfer _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_heat_transfer_model.cc ) endif() package_is_activated(phase_field _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_phase_field_model.cc ) endif() package_is_activated(structural_mechanics _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_structural_mechanics_model.cc ) endif() pybind11_add_module(py11_akantu ${PYAKANTU_SRCS}) # to avoid compilation warnings from pybind11 target_include_directories(py11_akantu SYSTEM BEFORE PRIVATE ${PYBIND11_INCLUDE_DIR} PRIVATE ${pybind11_INCLUDE_DIR} PRIVATE ${PYTHON_INCLUDE_DIRS}) target_link_libraries(py11_akantu PUBLIC akantu) set_target_properties(py11_akantu PROPERTIES DEBUG_POSTFIX "" LIBRARY_OUTPUT_DIRECTORY akantu) file(COPY akantu DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) if(NOT SKBUILD) set(_python_install_dir ${CMAKE_INSTALL_LIBDIR}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages) else() set(_python_install_dir .) endif() install(TARGETS py11_akantu LIBRARY DESTINATION ${_python_install_dir}) if(NOT SKBUILD) install(DIRECTORY akantu DESTINATION ${_python_install_dir} FILES_MATCHING PATTERN "*.py") endif() diff --git a/python/py_akantu.cc b/python/py_akantu.cc index cf425a9d9..614751c8c 100644 --- a/python/py_akantu.cc +++ b/python/py_akantu.cc @@ -1,125 +1,127 @@ /* -------------------------------------------------------------------------- */ #include "aka_config.hh" /* -------------------------------------------------------------------------- */ #include "py_aka_common.hh" #include "py_aka_error.hh" #include "py_boundary_conditions.hh" #include "py_fe_engine.hh" #include "py_group_manager.hh" #include "py_mesh.hh" #include "py_model.hh" #include "py_parser.hh" #include "py_solver.hh" #if defined(AKANTU_USE_IOHELPER) #include "py_dumpable.hh" #endif #if defined(AKANTU_SOLID_MECHANICS) #include "py_material.hh" +#include "py_material_selector.hh" #include "py_solid_mechanics_model.hh" #endif #if defined(AKANTU_HEAT_TRANSFER) #include "py_heat_transfer_model.hh" #endif #if defined(AKANTU_COHESIVE_ELEMENT) #include "py_fragment_manager.hh" #include "py_solid_mechanics_model_cohesive.hh" #endif #if defined(AKANTU_PHASE_FIELD) #include "py_phase_field_model.hh" #endif #if defined(AKANTU_STRUCTURAL_MECHANICS) #include "py_structural_mechanics_model.hh" #endif /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ namespace py = pybind11; namespace akantu { void register_all(pybind11::module & mod) { register_initialize(mod); register_enums(mod); register_error(mod); register_functions(mod); register_parser(mod); register_solvers(mod); register_group_manager(mod); #if defined(AKANTU_USE_IOHELPER) register_dumpable(mod); #endif register_mesh(mod); register_fe_engine(mod); register_boundary_conditions(mod); register_model(mod); #if defined(AKANTU_HEAT_TRANSFER) register_heat_transfer_model(mod); #endif #if defined(AKANTU_SOLID_MECHANICS) register_solid_mechanics_model(mod); register_material(mod); + register_material_selector(mod); #endif #if defined(AKANTU_COHESIVE_ELEMENT) register_solid_mechanics_model_cohesive(mod); register_fragment_manager(mod); #endif #if defined(AKANTU_STRUCTURAL_MECHANICS) register_structural_mechanics_model(mod); #endif #if defined(AKANTU_PHASE_FIELD) register_phase_field_model(mod); register_phase_field_coupler(mod); #endif } } // namespace akantu /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ PYBIND11_MODULE(py11_akantu, mod) { mod.doc() = "Akantu python interface"; static py::exception akantu_exception(mod, "Exception"); py::register_exception_translator([](std::exception_ptr ptr) { try { if (ptr) { std::rethrow_exception(ptr); } } catch (akantu::debug::Exception & e) { if (akantu::debug::debugger.printBacktrace()) { akantu::debug::printBacktrace(); } akantu_exception(e.info().c_str()); } }); akantu::register_all(mod); mod.def("has_mpi", []() { #if defined(AKANTU_USE_MPI) return true; #else return false; #endif }); } // Module akantu diff --git a/python/py_boundary_conditions.cc b/python/py_boundary_conditions.cc index 97ef1ac6a..892ec0b84 100644 --- a/python/py_boundary_conditions.cc +++ b/python/py_boundary_conditions.cc @@ -1,98 +1,97 @@ /* -------------------------------------------------------------------------- */ #include "py_boundary_conditions.hh" #include "py_aka_array.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ //#include #include //#include /* -------------------------------------------------------------------------- */ namespace py = pybind11; namespace akantu { /* -------------------------------------------------------------------------- */ template class PyDirichletFunctor : public daughter { public: /* Inherit the constructors */ using daughter::daughter; /* Trampoline (need one for each virtual function) */ void operator()(UInt node, Vector & flags, Vector & primal, const Vector & coord) const override { - + // NOLINTNEXTLINE PYBIND11_OVERLOAD_NAME(void, daughter, "__call__", operator(), node, flags, primal, coord); } }; /* -------------------------------------------------------------------------- */ template class PyNeumannFunctor : public daughter { public: /* Inherit the constructors */ using daughter::daughter; /* Trampoline (need one for each virtual function) */ void operator()(const IntegrationPoint & quad_point, Vector & dual, const Vector & coord, const Vector & normals) const override { - + // NOLINTNEXTLINE PYBIND11_OVERLOAD_PURE_NAME(void, daughter, "__call__", operator(), quad_point, dual, coord, normals); } }; /* -------------------------------------------------------------------------- */ template -decltype(auto) declareDirichletFunctor(py::module mod, const char * name, - Constructor && cons) { +decltype(auto) register_dirichlet_functor(py::module mod, const char * name, + Constructor && cons) { py::class_, BC::Dirichlet::DirichletFunctor>(mod, name) .def(cons); } template -decltype(auto) declareNeumannFunctor(py::module mod, const char * name, - Constructor && cons) { +decltype(auto) register_neumann_functor(py::module mod, const char * name, + Constructor && cons) { py::class_, BC::Neumann::NeumannFunctor>( mod, name) .def(cons); } /* -------------------------------------------------------------------------- */ -__attribute__((visibility("default"))) void -register_boundary_conditions(py::module & mod) { +void register_boundary_conditions(py::module & mod) { py::class_(mod, "BCFunctor"); py::class_, BC::Functor>(mod, "DirichletFunctor") .def(py::init()) .def(py::init()); py::class_, BC::Functor>( mod, "NeumannFunctor") .def(py::init()); - declareDirichletFunctor( + register_dirichlet_functor( mod, "FixedValue", py::init()); - declareDirichletFunctor( + register_dirichlet_functor( mod, "IncrementValue", py::init()); - declareDirichletFunctor(mod, "Increment", - py::init &>()); + register_dirichlet_functor( + mod, "Increment", py::init &>()); - declareNeumannFunctor(mod, "FromHigherDim", - py::init &>()); + register_neumann_functor( + mod, "FromHigherDim", py::init &>()); - declareNeumannFunctor(mod, "FromSameDim", - py::init &>()); + register_neumann_functor( + mod, "FromSameDim", py::init &>()); - declareNeumannFunctor(mod, "FreeBoundary", - py::init()); + register_neumann_functor(mod, "FreeBoundary", + py::init()); } } // namespace akantu diff --git a/python/py_fe_engine.cc b/python/py_fe_engine.cc index 70955c252..0f0119fda 100644 --- a/python/py_fe_engine.cc +++ b/python/py_fe_engine.cc @@ -1,110 +1,122 @@ /* -------------------------------------------------------------------------- */ #include "py_aka_array.hh" #include "py_aka_common.hh" /* -------------------------------------------------------------------------- */ +#include #include #include /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ namespace py = pybind11; /* -------------------------------------------------------------------------- */ namespace akantu { __attribute__((visibility("default"))) void register_fe_engine(py::module & mod) { - py::class_(mod, "Element"); + py::class_(mod, "Element") + .def(py::init([](ElementType type, UInt id) { + return new Element{type, id, _not_ghost}; + })) + .def(py::init([](ElementType type, UInt id, GhostType ghost_type) { + return new Element{type, id, ghost_type}; + })) + .def("__lt__", + [](Element & self, const Element & other) { return (self < other); }) + .def("__repr__", [](Element & self) { return std::to_string(self); }); + + mod.attr("ElementNull") = ElementNull; py::class_(mod, "FEEngine") .def( "getNbIntegrationPoints", [](FEEngine & fem, const ElementType & type, const GhostType & ghost_type) { return fem.getNbIntegrationPoints(type, ghost_type); }, py::arg("type"), py::arg("ghost_type") = _not_ghost) .def( "gradientOnIntegrationPoints", [](FEEngine & fem, const Array & u, Array & nablauq, - UInt nb_degree_of_freedom, ElementType type, - GhostType ghost_type, const Array * filter_elements) { + UInt nb_degree_of_freedom, ElementType type, GhostType ghost_type, + const Array * filter_elements) { if (filter_elements == nullptr) { // This is due to the ArrayProxy that looses the // empty_filter information filter_elements = &empty_filter; } fem.gradientOnIntegrationPoints(u, nablauq, nb_degree_of_freedom, type, ghost_type, *filter_elements); }, py::arg("u"), py::arg("nablauq"), py::arg("nb_degree_of_freedom"), py::arg("type"), py::arg("ghost_type") = _not_ghost, py::arg("filter_elements") = nullptr) .def( "interpolateOnIntegrationPoints", [](FEEngine & self, const Array & u, Array & uq, - UInt nb_degree_of_freedom, ElementType type, - GhostType ghost_type, const Array * filter_elements) { + UInt nb_degree_of_freedom, ElementType type, GhostType ghost_type, + const Array * filter_elements) { if (filter_elements == nullptr) { // This is due to the ArrayProxy that looses the // empty_filter information filter_elements = &empty_filter; } self.interpolateOnIntegrationPoints(u, uq, nb_degree_of_freedom, type, ghost_type, *filter_elements); }, py::arg("u"), py::arg("uq"), py::arg("nb_degree_of_freedom"), py::arg("type"), py::arg("ghost_type") = _not_ghost, py::arg("filter_elements") = nullptr) .def( "interpolateOnIntegrationPoints", [](FEEngine & self, const Array & u, ElementTypeMapArray & uq, const ElementTypeMapArray * filter_elements) { self.interpolateOnIntegrationPoints(u, uq, filter_elements); }, py::arg("u"), py::arg("uq"), py::arg("filter_elements") = nullptr) .def( "computeIntegrationPointsCoordinates", [](FEEngine & self, ElementTypeMapArray & coordinates, const ElementTypeMapArray * filter_elements) -> decltype(auto) { return self.computeIntegrationPointsCoordinates(coordinates, filter_elements); }, py::arg("coordinates"), py::arg("filter_elements") = nullptr) .def( "assembleFieldLumped", [](FEEngine & fem, const std::function &, const Element &)> & field_funct, const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager, ElementType type, GhostType ghost_type) { fem.assembleFieldLumped(field_funct, matrix_id, dof_id, dof_manager, type, ghost_type); }, py::arg("field_funct"), py::arg("matrix_id"), py::arg("dof_id"), py::arg("dof_manager"), py::arg("type"), py::arg("ghost_type") = _not_ghost) .def( "assembleFieldMatrix", [](FEEngine & fem, const std::function &, const Element &)> & field_funct, const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager, ElementType type, GhostType ghost_type = _not_ghost) { fem.assembleFieldMatrix(field_funct, matrix_id, dof_id, dof_manager, type, ghost_type); }, py::arg("field_funct"), py::arg("matrix_id"), py::arg("dof_id"), py::arg("dof_manager"), py::arg("type"), py::arg("ghost_type") = _not_ghost); py::class_(mod, "IntegrationPoint"); } } // namespace akantu diff --git a/python/py_material.cc b/python/py_material.cc index f2b545fb5..e374fe7d9 100644 --- a/python/py_material.cc +++ b/python/py_material.cc @@ -1,207 +1,182 @@ /* -------------------------------------------------------------------------- */ #include "py_aka_array.hh" /* -------------------------------------------------------------------------- */ #include #if defined(AKANTU_COHESIVE_ELEMENT) #include #endif +#include /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ namespace py = pybind11; /* -------------------------------------------------------------------------- */ #if not defined(PYBIND11_OVERRIDE) #define PYBIND11_OVERRIDE PYBIND11_OVERLOAD #define PYBIND11_OVERRIDE_PURE PYBIND11_OVERLOAD_PURE #endif namespace akantu { -template class PyMaterial : public _Material { - -public: - /* Inherit the constructors */ - using _Material::_Material; - - ~PyMaterial() override = default; - - void initMaterial() override { - PYBIND11_OVERRIDE(void, _Material, initMaterial, ); // NOLINT +namespace { + template class PyMaterial : public _Material { + public: + /* Inherit the constructors */ + using _Material::_Material; + + ~PyMaterial() override = default; + + void initMaterial() override { + // NOLINTNEXTLINE + PYBIND11_OVERRIDE(void, _Material, initMaterial, ); + }; + void computeStress(ElementType el_type, + GhostType ghost_type = _not_ghost) override { + // NOLINTNEXTLINE + PYBIND11_OVERRIDE_PURE(void, _Material, computeStress, el_type, + ghost_type); + } + void computeTangentModuli(ElementType el_type, Array & tangent_matrix, + GhostType ghost_type = _not_ghost) override { + // NOLINTNEXTLINE + PYBIND11_OVERRIDE(void, _Material, computeTangentModuli, el_type, + tangent_matrix, ghost_type); + } + + void computePotentialEnergy(ElementType el_type) override { + // NOLINTNEXTLINE + PYBIND11_OVERRIDE(void, _Material, computePotentialEnergy, el_type); + } + + Real getPushWaveSpeed(const Element & element) const override { + // NOLINTNEXTLINE + PYBIND11_OVERRIDE(Real, _Material, getPushWaveSpeed, element); + } + + Real getShearWaveSpeed(const Element & element) const override { + // NOLINTNEXTLINE + PYBIND11_OVERRIDE(Real, _Material, getShearWaveSpeed, element); + } + + template + void registerInternal(const std::string & name, UInt nb_component) { + auto && internal = std::make_shared>(name, *this); + AKANTU_DEBUG_INFO("alloc internal " << name << " " + << &this->internals[name]); + + internal->initialize(nb_component); + this->internals[name] = internal; + } + + protected: + std::map> internals; }; - void computeStress(ElementType el_type, - GhostType ghost_type = _not_ghost) override { - PYBIND11_OVERRIDE_PURE(void, _Material, computeStress, el_type, ghost_type); - } - void computeTangentModuli(ElementType el_type, Array & tangent_matrix, - GhostType ghost_type = _not_ghost) override { - PYBIND11_OVERRIDE(void, _Material, computeTangentModuli, el_type, - tangent_matrix, ghost_type); - } - void computePotentialEnergy(ElementType el_type) override { - PYBIND11_OVERRIDE(void, _Material, computePotentialEnergy, el_type); - } - - Real getPushWaveSpeed(const Element & element) const override { - PYBIND11_OVERRIDE(Real, _Material, getPushWaveSpeed, element); + /* ------------------------------------------------------------------------ */ + template + void register_internal_field(py::module & mod, const std::string & name) { + py::class_, ElementTypeMapArray, + std::shared_ptr>>( + mod, ("InternalField" + name).c_str()); } - Real getShearWaveSpeed(const Element & element) const override { - PYBIND11_OVERRIDE(Real, _Material, getShearWaveSpeed, element); + /* ------------------------------------------------------------------------ */ + template + decltype(auto) register_material_classes(py::module & mod, + const std::string & name) { + return py::class_<_Material, Material, Parsable, PyMaterial<_Material>>( + mod, name.c_str(), py::multiple_inheritance()) + .def(py::init()); } +} // namespace - template - void registerInternal(const std::string & name, UInt nb_component) { - auto && internal = std::make_shared>(name, *this); - AKANTU_DEBUG_INFO("alloc internal " << name << " " - << &this->internals[name]); - - internal->initialize(nb_component); - this->internals[name] = internal; - } +/* -------------------------------------------------------------------------- */ +void register_material(py::module & mod) { + py::class_(mod, "MaterialFactory") + .def_static( + "getInstance", + []() -> MaterialFactory & { return Material::getFactory(); }, + py::return_value_policy::reference) + .def("registerAllocator", + [](MaterialFactory & self, const std::string id, py::function func) { + self.registerAllocator( + id, + [func, id](UInt dim, const ID & /*unused*/, + SolidMechanicsModel & model, + const ID & option) -> std::unique_ptr { + py::object obj = func(dim, id, model, option); + auto & ptr = py::cast(obj); -protected: - std::map> internals; -}; + obj.release(); + return std::unique_ptr(&ptr); + }); + }) + .def("getPossibleAllocators", &MaterialFactory::getPossibleAllocators); -/* -------------------------------------------------------------------------- */ -template -void register_internal_field(py::module & mod, const std::string & name) { - py::class_, ElementTypeMapArray, - std::shared_ptr>>( - mod, ("InternalField" + name).c_str()); -} + register_internal_field(mod, "Real"); + register_internal_field(mod, "UInt"); -/* -------------------------------------------------------------------------- */ -template -void define_material(py::module & mod, const std::string & name) { - py::class_<_Material, PyMaterial<_Material>, Parsable>( - mod, name.c_str(), py::multiple_inheritance()) + py::class_>( + mod, "Material", py::multiple_inheritance()) .def(py::init()) .def( "getGradU", [](Material & self, ElementType el_type, GhostType ghost_type = _not_ghost) -> decltype(auto) { return self.getGradU(el_type, ghost_type); }, py::arg("el_type"), py::arg("ghost_type") = _not_ghost, py::return_value_policy::reference) .def( "getStress", [](Material & self, ElementType el_type, GhostType ghost_type = _not_ghost) -> decltype(auto) { return self.getStress(el_type, ghost_type); }, py::arg("el_type"), py::arg("ghost_type") = _not_ghost, py::return_value_policy::reference) .def( "getPotentialEnergy", [](Material & self, ElementType el_type) -> decltype(auto) { return self.getPotentialEnergy(el_type); }, py::return_value_policy::reference) .def("initMaterial", &Material::initMaterial) .def("getModel", &Material::getModel) .def("registerInternalReal", [](Material & self, const std::string & name, UInt nb_component) { return dynamic_cast &>(self) .registerInternal(name, nb_component); }) .def("registerInternalUInt", [](Material & self, const std::string & name, UInt nb_component) { return dynamic_cast &>(self) .registerInternal(name, nb_component); }) .def( "getInternalReal", [](Material & self, const ID & id) -> decltype(auto) { return self.getInternal(id); }, py::arg("id"), py::return_value_policy::reference) .def( "getInternalUInt", [](Material & self, const ID & id) -> decltype(auto) { return self.getInternal(id); }, py::arg("id"), py::return_value_policy::reference) .def( "getElementFilter", [](Material & self) -> decltype(auto) { return self.getElementFilter(); }, py::return_value_policy::reference); -} -/* -------------------------------------------------------------------------- */ -void register_material(py::module & mod) { - py::class_(mod, "MaterialFactory") - .def_static( - "getInstance", - []() -> MaterialFactory & { return Material::getFactory(); }, - py::return_value_policy::reference) - .def("registerAllocator", - [](MaterialFactory & self, const std::string id, py::function func) { - self.registerAllocator( - id, - [func, id](UInt dim, const ID & /*unused*/, - SolidMechanicsModel & model, - const ID & option) -> std::unique_ptr { - py::object obj = func(dim, id, model, option); - auto & ptr = py::cast(obj); - - obj.release(); - return std::unique_ptr(&ptr); - }); - }) - .def("getPossibleAllocators", &MaterialFactory::getPossibleAllocators); - - register_internal_field(mod, "Real"); - register_internal_field(mod, "UInt"); - - define_material(mod, "Material"); - - py::class_>( - mod, "MaterialSelector") - .def("setFallback", - [](MaterialSelector & self, UInt f) { self.setFallback(f); }) - .def("setFallback", - [](MaterialSelector & self, - const std::shared_ptr & fallback_selector) { - self.setFallback(fallback_selector); - }) - .def("setFallback", - [](MaterialSelector & self, MaterialSelector & fallback_selector) { - self.setFallback(fallback_selector); - }); - - py::class_, MaterialSelector, - std::shared_ptr>>( - mod, "MeshDataMaterialSelectorString") - .def(py::init(), - py::arg("name"), py::arg("model"), py::arg("first_index") = 1); - -#if defined(AKANTU_COHESIVE_ELEMENT) - py::class_>( - mod, "DefaultMaterialCohesiveSelector") - .def(py::init()); - - py::class_>( - mod, "MeshDataMaterialCohesiveSelector") - .def(py::init()); - - py::class_>( - mod, "MaterialCohesiveRulesSelector") - .def(py::init(), - py::arg("model"), py::arg("rules"), - py::arg("mesh_data_id") = "physical_names"); -#endif + register_material_classes>(mod, "MaterialElastic2D"); + register_material_classes>(mod, "MaterialElastic3D"); } } // namespace akantu diff --git a/python/py_material_selector.cc b/python/py_material_selector.cc new file mode 100644 index 000000000..f05d1d244 --- /dev/null +++ b/python/py_material_selector.cc @@ -0,0 +1,85 @@ +#include "py_material_selector.hh" + +/* -------------------------------------------------------------------------- */ +#include +#include +#if defined(AKANTU_COHESIVE_ELEMENT) +#include +#include +#endif +/* -------------------------------------------------------------------------- */ +#include +#include +#include +/* -------------------------------------------------------------------------- */ +namespace py = pybind11; +/* -------------------------------------------------------------------------- */ + +namespace akantu { + +namespace { + template + class PyMaterialSelector : public Base { + public: + /* Inherit the constructors */ + using Base::Base; + + ~PyMaterialSelector() override = default; + + UInt operator()(const Element & element) override { + // NOLINTNEXTLINE + PYBIND11_OVERRIDE_NAME(UInt, MaterialSelector, "__call__", operator(), + element); + } + }; + + template + decltype(auto) register_material_selectors(py::module & mod, + const std::string & class_name) { + return py::class_, + std::shared_ptr>( + mod, class_name.c_str()); + } +} // namespace + +void register_material_selector(py::module & mod) { + py::class_, + std::shared_ptr>(mod, "MaterialSelector") + .def(py::init()) + .def("setFallback", + [](MaterialSelector & self, UInt f) { self.setFallback(f); }) + .def("setFallback", + [](MaterialSelector & self, + const std::shared_ptr & fallback_selector) { + self.setFallback(fallback_selector); + }) + .def("__call__", &MaterialSelector::operator()); + + register_material_selectors( + mod, "DefaultMaterialSelector") + .def(py::init>()); + + register_material_selectors>( + mod, "MeshDataMaterialSelectorString") + .def(py::init(), + py::arg("name"), py::arg("model"), py::arg("first_index") = 1); + +#if defined(AKANTU_COHESIVE_ELEMENT) + register_material_selectors( + mod, "DefaultMaterialCohesiveSelector") + .def(py::init()); + + register_material_selectors( + mod, "MeshDataMaterialCohesiveSelector") + .def(py::init()); + + register_material_selectors( + mod, "MaterialCohesiveRulesSelector") + .def(py::init(), + py::arg("model"), py::arg("rules"), + py::arg("mesh_data_id") = "physical_names"); +#endif +} +} // namespace akantu diff --git a/python/py_material_selector.hh b/python/py_material_selector.hh new file mode 100644 index 000000000..e4fcde441 --- /dev/null +++ b/python/py_material_selector.hh @@ -0,0 +1,12 @@ +#include + +#ifndef AKANTU_PY_MATERIAL_SELECTOR_HH_ +#define AKANTU_PY_MATERIAL_SELECTOR_HH_ + +namespace akantu { + +void register_material_selector(pybind11::module & mod); + +} // namespace akantu + +#endif // AKANTU_PY_MATERIAL_SELECTOR_HH_ diff --git a/python/py_mesh.cc b/python/py_mesh.cc index c7fae603c..f73aeb8fd 100644 --- a/python/py_mesh.cc +++ b/python/py_mesh.cc @@ -1,148 +1,150 @@ /* -------------------------------------------------------------------------- */ #include "aka_config.hh" /* -------------------------------------------------------------------------- */ #include "py_aka_array.hh" /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ namespace py = pybind11; /* -------------------------------------------------------------------------- */ namespace akantu { -/* -------------------------------------------------------------------------- */ -template -void register_element_type_map_array(py::module & mod, - const std::string & name) { - py::class_, std::shared_ptr>>( - mod, ("ElementTypeMapArray" + name).c_str()) - .def( - "__call__", - [](ElementTypeMapArray & self, ElementType type, - GhostType ghost_type) -> decltype(auto) { - return self(type, ghost_type); - }, - py::arg("type"), py::arg("ghost_type") = _not_ghost, - py::return_value_policy::reference) - .def( - "elementTypes", - [](ElementTypeMapArray & self, UInt _dim, GhostType _ghost_type, - ElementKind _kind) -> std::vector { - auto types = self.elementTypes(_dim, _ghost_type, _kind); - std::vector _types; - for (auto && t : types) { - _types.push_back(t); - } - return _types; - }, - py::arg("dim") = _all_dimensions, py::arg("ghost_type") = _not_ghost, - py::arg("kind") = _ek_regular); -} - +namespace { + /* ------------------------------------------------------------------------ */ + template + void register_element_type_map_array(py::module & mod, + const std::string & name) { + py::class_, std::shared_ptr>>( + mod, ("ElementTypeMapArray" + name).c_str()) + .def( + "__call__", + [](ElementTypeMapArray & self, ElementType type, + GhostType ghost_type) -> decltype(auto) { + return self(type, ghost_type); + }, + py::arg("type"), py::arg("ghost_type") = _not_ghost, + py::return_value_policy::reference) + .def( + "elementTypes", + [](ElementTypeMapArray & self, UInt _dim, GhostType _ghost_type, + ElementKind _kind) -> std::vector { + auto types = self.elementTypes(_dim, _ghost_type, _kind); + std::vector _types; + for (auto && t : types) { + _types.push_back(t); + } + return _types; + }, + py::arg("dim") = _all_dimensions, + py::arg("ghost_type") = _not_ghost, py::arg("kind") = _ek_regular); + } +} // namespace /* -------------------------------------------------------------------------- */ void register_mesh(py::module & mod) { register_element_type_map_array(mod, "Real"); register_element_type_map_array(mod, "UInt"); + //register_element_type_map_array(mod, "String"); py::class_(mod, "MeshData") .def( "getElementalDataUInt", [](MeshData & _this, const ID & name) -> decltype(auto) { return _this.getElementalData(name); }, py::return_value_policy::reference) .def( "getElementalDataReal", [](MeshData & _this, const ID & name) -> decltype(auto) { return _this.getElementalData(name); }, py::return_value_policy::reference); py::class_(mod, "Mesh", py::multiple_inheritance()) - .def(py::init(), - py::arg("spatial_dimension"), py::arg("id") = "mesh") + .def(py::init(), py::arg("spatial_dimension"), + py::arg("id") = "mesh") .def("read", &Mesh::read, py::arg("filename"), py::arg("mesh_io_type") = _miot_auto, "read the mesh from a file") .def( "getNodes", [](Mesh & self) -> decltype(auto) { return self.getNodes(); }, py::return_value_policy::reference) .def("getNbNodes", &Mesh::getNbNodes) .def( "getConnectivity", [](Mesh & self, ElementType type) -> decltype(auto) { return self.getConnectivity(type); }, py::return_value_policy::reference) .def( "addConnectivityType", [](Mesh & self, ElementType type, GhostType ghost_type) -> void { self.addConnectivityType(type, ghost_type); }, py::arg("type"), py::arg("ghost_type") = _not_ghost) .def("distribute", [](Mesh & self) { self.distribute(); }) .def("makePeriodic", [](Mesh & self, const SpatialDirection & direction) { self.makePeriodic(direction); }) .def( "getNbElement", [](Mesh & self, const UInt spatial_dimension, GhostType ghost_type, ElementKind kind) { return self.getNbElement(spatial_dimension, ghost_type, kind); }, py::arg("spatial_dimension") = _all_dimensions, py::arg("ghost_type") = _not_ghost, py::arg("kind") = _ek_not_defined) .def( "getNbElement", [](Mesh & self, ElementType type, GhostType ghost_type) { return self.getNbElement(type, ghost_type); }, py::arg("type"), py::arg("ghost_type") = _not_ghost) .def_static( "getSpatialDimension", [](ElementType & type) { return Mesh::getSpatialDimension(type); }) .def( "getDataReal", [](Mesh & _this, const ID & name, ElementType type, GhostType ghost_type) -> decltype(auto) { return _this.getData(name, type, ghost_type); }, py::arg("name"), py::arg("type"), py::arg("ghost_type") = _not_ghost, py::return_value_policy::reference) .def( "hasDataReal", [](Mesh & _this, const ID & name, ElementType type, GhostType ghost_type) -> bool { return _this.hasData(name, type, ghost_type); }, py::arg("name"), py::arg("type"), py::arg("ghost_type") = _not_ghost); /* ------------------------------------------------------------------------ */ py::class_(mod, "MeshUtils") .def_static("buildFacets", &MeshUtils::buildFacets); py::class_(mod, "MeshAccessor") .def(py::init(), py::arg("mesh")) .def( "resizeConnectivity", [](MeshAccessor & self, UInt new_size, ElementType type, GhostType gt) -> void { self.resizeConnectivity(new_size, type, gt); }, py::arg("new_size"), py::arg("type"), py::arg("ghost_type") = _not_ghost) .def( "resizeNodes", [](MeshAccessor & self, UInt new_size) -> void { self.resizeNodes(new_size); }, py::arg("new_size")) .def("makeReady", &MeshAccessor::makeReady); } } // namespace akantu diff --git a/python/py_solid_mechanics_model.cc b/python/py_solid_mechanics_model.cc index e5f6d28b2..2fdf2adae 100644 --- a/python/py_solid_mechanics_model.cc +++ b/python/py_solid_mechanics_model.cc @@ -1,110 +1,120 @@ /* -------------------------------------------------------------------------- */ #include "py_aka_array.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ namespace py = pybind11; /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ #define def_deprecated(func_name, mesg) \ def(func_name, [](py::args, py::kwargs) { AKANTU_ERROR(mesg); }) #define def_function_nocopy(func_name) \ def( \ #func_name, \ [](SolidMechanicsModel & self) -> decltype(auto) { \ return self.func_name(); \ }, \ py::return_value_policy::reference) #define def_function(func_name) \ def(#func_name, [](SolidMechanicsModel & self) -> decltype(auto) { \ return self.func_name(); \ }) /* -------------------------------------------------------------------------- */ void register_solid_mechanics_model(py::module & mod) { py::class_(mod, "SolidMechanicsModelOptions") .def(py::init(), py::arg("_analysis_method") = _explicit_lumped_mass); py::class_(mod, "SolidMechanicsModel", py::multiple_inheritance()) - .def(py::init(), + .def(py::init(), py::arg("mesh"), py::arg("spatial_dimension") = _all_dimensions, py::arg("id") = "solid_mechanics_model", py::arg("model_type") = ModelType::_solid_mechanics_model) .def( "initFull", [](SolidMechanicsModel & self, const SolidMechanicsModelOptions & options) { self.initFull(options); }, py::arg("option") = SolidMechanicsModelOptions()) .def( "initFull", [](SolidMechanicsModel & self, const AnalysisMethod & analysis_method) { self.initFull(_analysis_method = analysis_method); }, py::arg("_analysis_method")) .def_deprecated("applyDirichletBC", "Deprecated: use applyBC") .def("applyBC", [](SolidMechanicsModel & self, BC::Dirichlet::DirichletFunctor & func, const std::string & element_group) { self.applyBC(func, element_group); }) .def("applyBC", [](SolidMechanicsModel & self, BC::Neumann::NeumannFunctor & func, const std::string & element_group) { self.applyBC(func, element_group); }) .def("setTimeStep", &SolidMechanicsModel::setTimeStep, py::arg("time_step"), py::arg("solver_id") = "") .def("getEnergy", py::overload_cast( &SolidMechanicsModel::getEnergy), py::arg("energy_id")) .def("getEnergy", py::overload_cast( &SolidMechanicsModel::getEnergy), py::arg("energy_id"), py::arg("group_id")) .def_function(assembleStiffnessMatrix) .def_function(assembleInternalForces) .def_function(assembleMass) .def_function(assembleMassLumped) .def_function(getStableTimeStep) .def_function_nocopy(getExternalForce) .def_function_nocopy(getDisplacement) .def_function_nocopy(getPreviousDisplacement) .def_function_nocopy(getIncrement) .def_function_nocopy(getInternalForce) .def_function_nocopy(getMass) .def_function_nocopy(getVelocity) .def_function_nocopy(getAcceleration) .def_function_nocopy(getInternalForce) .def_function_nocopy(getBlockedDOFs) .def_function_nocopy(getMesh) .def("getMaterial", py::overload_cast(&SolidMechanicsModel::getMaterial), py::return_value_policy::reference) .def("getMaterial", py::overload_cast( &SolidMechanicsModel::getMaterial), py::return_value_policy::reference) .def("getMaterialIndex", &SolidMechanicsModel::getMaterialIndex) - .def("setMaterialSelector", &SolidMechanicsModel::setMaterialSelector) + // .def( + // "setMaterialSelector", + // [](SolidMechanicsModel & self, MaterialSelector & + // material_selector) { + // self.setMaterialSelector(material_selector.shared_from_this()); + // }) + .def("setMaterialSelector", + [](SolidMechanicsModel & self, + std::shared_ptr material_selector) { + std::cout << (*material_selector)(ElementNull) << std::endl; + self.setMaterialSelector(material_selector); + }) .def("getMaterialSelector", &SolidMechanicsModel::getMaterialSelector); } } // namespace akantu diff --git a/src/model/solid_mechanics/material_selector.hh b/src/model/solid_mechanics/material_selector.hh index 311c72adb..40d05bbb2 100644 --- a/src/model/solid_mechanics/material_selector.hh +++ b/src/model/solid_mechanics/material_selector.hh @@ -1,163 +1,157 @@ /** * @file material_selector.hh * * @author Lucas Frerot * @author Nicolas Richart * * @date creation: Wed Nov 13 2013 * @date last modification: Mon Dec 18 2017 * * @brief class describing how to choose a material for a given element * * * Copyright (©) 2014-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "element.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_SELECTOR_HH_ #define AKANTU_MATERIAL_SELECTOR_HH_ /* -------------------------------------------------------------------------- */ namespace akantu { class SolidMechanicsModel; /** * main class to assign same or different materials for different * elements */ -class MaterialSelector : public std::enable_shared_from_this { +class MaterialSelector { public: MaterialSelector() = default; virtual ~MaterialSelector() = default; virtual inline UInt operator()(const Element & element) { if (fallback_selector) { return (*fallback_selector)(element); } return fallback_value; } inline void setFallback(UInt f) { fallback_value = f; } inline void setFallback(const std::shared_ptr & fallback_selector) { this->fallback_selector = fallback_selector; } - inline void setFallback(MaterialSelector & fallback_selector) { - this->fallback_selector = fallback_selector.shared_from_this(); - } - inline std::shared_ptr & getFallbackSelector() { return this->fallback_selector; } inline UInt getFallbackValue() const { return this->fallback_value; } protected: UInt fallback_value{0}; std::shared_ptr fallback_selector; }; /* -------------------------------------------------------------------------- */ /** * class that assigns the first material to regular elements by default */ class DefaultMaterialSelector : public MaterialSelector { public: explicit DefaultMaterialSelector( const ElementTypeMapArray & material_index) : material_index(material_index) {} UInt operator()(const Element & element) override { if (not material_index.exists(element.type, element.ghost_type)) { return MaterialSelector::operator()(element); } const auto & mat_indexes = material_index(element.type, element.ghost_type); if (element.element < mat_indexes.size()) { auto && tmp_mat = mat_indexes(element.element); if (tmp_mat != UInt(-1)) { return tmp_mat; } } return MaterialSelector::operator()(element); } private: const ElementTypeMapArray & material_index; }; /* -------------------------------------------------------------------------- */ /** * Use elemental data to assign materials */ template class ElementDataMaterialSelector : public MaterialSelector { public: ElementDataMaterialSelector(const ElementTypeMapArray & element_data, const SolidMechanicsModel & model, UInt first_index = 1) : element_data(element_data), model(model), first_index(first_index) {} inline T elementData(const Element & element) { DebugLevel dbl = debug::getDebugLevel(); debug::setDebugLevel(dblError); T data = element_data(element.type, element.ghost_type)(element.element); debug::setDebugLevel(dbl); return data; } - inline UInt operator()(const Element & element) override { - return MaterialSelector::operator()(element); - } + inline UInt operator()(const Element & element) override; protected: /// list of element with the specified data (i.e. tag value) const ElementTypeMapArray & element_data; /// the model that the materials belong const SolidMechanicsModel & model; /// first material index: equal to 1 if none specified UInt first_index; }; /* -------------------------------------------------------------------------- */ /** * class to use mesh data information to assign different materials * where name is the tag value: tag_0, tag_1 */ template class MeshDataMaterialSelector : public ElementDataMaterialSelector { public: MeshDataMaterialSelector(const std::string & name, const SolidMechanicsModel & model, UInt first_index = 1); }; } // namespace akantu #endif /* AKANTU_MATERIAL_SELECTOR_HH_ */ diff --git a/src/model/solid_mechanics/material_selector_tmpl.hh b/src/model/solid_mechanics/material_selector_tmpl.hh index 6ff23cb5b..10815691e 100644 --- a/src/model/solid_mechanics/material_selector_tmpl.hh +++ b/src/model/solid_mechanics/material_selector_tmpl.hh @@ -1,73 +1,80 @@ /** * @file material_selector_tmpl.hh * * @author Lucas Frerot * @author Nicolas Richart * * @date creation: Wed Nov 13 2013 * @date last modification: Tue Nov 07 2017 * * @brief Implementation of the template MaterialSelector * * * Copyright (©) 2014-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "material_selector.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_MATERIAL_SELECTOR_TMPL_HH_ #define AKANTU_MATERIAL_SELECTOR_TMPL_HH_ namespace akantu { /* -------------------------------------------------------------------------- */ template <> -inline UInt ElementDataMaterialSelector:: -operator()(const Element & element) { +inline UInt +ElementDataMaterialSelector::operator()(const Element & element) { try { std::string material_name = this->elementData(element); return model.getMaterialIndex(material_name); - } catch (...) { + } catch (std::exception & e) { return MaterialSelector::operator()(element); } } /* -------------------------------------------------------------------------- */ template <> -inline UInt ElementDataMaterialSelector:: -operator()(const Element & element) { +inline UInt +ElementDataMaterialSelector::operator()(const Element & element) { try { return this->elementData(element) - first_index; } catch (...) { return MaterialSelector::operator()(element); } } +/* -------------------------------------------------------------------------- */ +template +inline UInt +ElementDataMaterialSelector::operator()(const Element & element) { + return MaterialSelector::operator()(element); +} + /* -------------------------------------------------------------------------- */ template MeshDataMaterialSelector::MeshDataMaterialSelector( const std::string & name, const SolidMechanicsModel & model, UInt first_index) : ElementDataMaterialSelector(model.getMesh().getData(name), model, first_index) {} } // namespace akantu #endif /* AKANTU_MATERIAL_SELECTOR_TMPL_HH_ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model.hh b/src/model/solid_mechanics/solid_mechanics_model.hh index e2c1ebab1..2e235e6c4 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.hh +++ b/src/model/solid_mechanics/solid_mechanics_model.hh @@ -1,592 +1,592 @@ /** * @file solid_mechanics_model.hh * * @author Guillaume Anciaux * @author Daniel Pino Muñoz * @author Nicolas Richart * * @date creation: Tue Jul 27 2010 * @date last modification: Wed Feb 21 2018 * * @brief Model of Solid Mechanics * * * Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "boundary_condition.hh" #include "data_accessor.hh" #include "fe_engine.hh" #include "model.hh" #include "non_local_manager_callback.hh" #include "solid_mechanics_model_event_handler.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_SOLID_MECHANICS_MODEL_HH_ #define AKANTU_SOLID_MECHANICS_MODEL_HH_ namespace akantu { class Material; class MaterialSelector; class DumperIOHelper; class NonLocalManager; template class IntegratorGauss; template class ShapeLagrange; } // namespace akantu /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ class SolidMechanicsModel : public Model, public DataAccessor, public DataAccessor, public BoundaryCondition, public NonLocalManagerCallback, public EventHandlerManager { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: class NewMaterialElementsEvent : public NewElementsEvent { public: AKANTU_GET_MACRO_NOT_CONST(MaterialList, material, Array &); AKANTU_GET_MACRO(MaterialList, material, const Array &); protected: Array material; }; using MyFEEngineType = FEEngineTemplate; protected: using EventManager = EventHandlerManager; public: SolidMechanicsModel(Mesh & mesh, UInt dim = _all_dimensions, const ID & id = "solid_mechanics_model", ModelType model_type = ModelType::_solid_mechanics_model); ~SolidMechanicsModel() override; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ protected: /// initialize completely the model void initFullImpl( const ModelOptions & options = SolidMechanicsModelOptions()) override; public: /// initialize all internal arrays for materials virtual void initMaterials(); protected: /// initialize the model void initModel() override; /// function to print the containt of the class void printself(std::ostream & stream, int indent = 0) const override; /// get some default values for derived classes std::tuple getDefaultSolverID(const AnalysisMethod & method) override; /* ------------------------------------------------------------------------ */ /* Solver interface */ /* ------------------------------------------------------------------------ */ public: /// assembles the stiffness matrix, virtual void assembleStiffnessMatrix(); /// assembles the internal forces in the array internal_forces virtual void assembleInternalForces(); protected: /// callback for the solver, this adds f_{ext} - f_{int} to the residual void assembleResidual() override; /// callback for the solver, this adds f_{ext} or f_{int} to the residual void assembleResidual(const ID & residual_part) override; bool canSplitResidual() override { return true; } /// get the type of matrix needed MatrixType getMatrixType(const ID & matrix_id) override; /// callback for the solver, this assembles different matrices void assembleMatrix(const ID & matrix_id) override; /// callback for the solver, this assembles the stiffness matrix void assembleLumpedMatrix(const ID & matrix_id) override; /// callback for the solver, this is called at beginning of solve void predictor() override; /// callback for the solver, this is called at end of solve void corrector() override; /// callback for the solver, this is called at beginning of solve void beforeSolveStep() override; /// callback for the solver, this is called at end of solve void afterSolveStep(bool converged = true) override; /// Callback for the model to instantiate the matricees when needed void initSolver(TimeStepSolverType time_step_solver_type, NonLinearSolverType non_linear_solver_type) override; protected: /* ------------------------------------------------------------------------ */ TimeStepSolverType getDefaultSolverType() const override; /* ------------------------------------------------------------------------ */ ModelSolverOptions getDefaultSolverOptions(const TimeStepSolverType & type) const override; public: bool isDefaultSolverExplicit() { return method == _explicit_lumped_mass || method == _explicit_consistent_mass; } protected: /// update the current position vector void updateCurrentPosition(); /* ------------------------------------------------------------------------ */ /* Materials (solid_mechanics_model_material.cc) */ /* ------------------------------------------------------------------------ */ public: /// register an empty material of a given type Material & registerNewMaterial(const ID & mat_name, const ID & mat_type, const ID & opt_param); /// reassigns materials depending on the material selector virtual void reassignMaterial(); /// apply a constant eigen_grad_u on all quadrature points of a given material virtual void applyEigenGradU(const Matrix & prescribed_eigen_grad_u, const ID & material_name, GhostType ghost_type = _not_ghost); protected: /// register a material in the dynamic database Material & registerNewMaterial(const ParserSection & mat_section); /// read the material files to instantiate all the materials void instantiateMaterials(); /// set the element_id_by_material and add the elements to the good materials virtual void assignMaterialToElements(const ElementTypeMapArray * filter = nullptr); /* ------------------------------------------------------------------------ */ /* Mass (solid_mechanics_model_mass.cc) */ /* ------------------------------------------------------------------------ */ public: /// assemble the lumped mass matrix void assembleMassLumped(); /// assemble the mass matrix for consistent mass resolutions void assembleMass(); public: /// assemble the lumped mass matrix for local and ghost elements void assembleMassLumped(GhostType ghost_type); /// assemble the mass matrix for either _ghost or _not_ghost elements void assembleMass(GhostType ghost_type); protected: /// fill a vector of rho void computeRho(Array & rho, ElementType type, GhostType ghost_type); /// compute the kinetic energy Real getKineticEnergy(); Real getKineticEnergy(ElementType type, UInt index); /// compute the external work (for impose displacement, the velocity should be /// given too) Real getExternalWork(); /* ------------------------------------------------------------------------ */ /* NonLocalManager inherited members */ /* ------------------------------------------------------------------------ */ protected: void initializeNonLocal() override; void updateDataForNonLocalCriterion(ElementTypeMapReal & criterion) override; void computeNonLocalStresses(GhostType ghost_type) override; void insertIntegrationPointsInNeighborhoods(GhostType ghost_type) override; /// update the values of the non local internal void updateLocalInternal(ElementTypeMapReal & internal_flat, GhostType ghost_type, ElementKind kind) override; /// copy the results of the averaging in the materials void updateNonLocalInternal(ElementTypeMapReal & internal_flat, GhostType ghost_type, ElementKind kind) override; /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ public: UInt getNbData(const Array & elements, const SynchronizationTag & tag) const override; void packData(CommunicationBuffer & buffer, const Array & elements, const SynchronizationTag & tag) const override; void unpackData(CommunicationBuffer & buffer, const Array & elements, const SynchronizationTag & tag) override; UInt getNbData(const Array & dofs, const SynchronizationTag & tag) const override; void packData(CommunicationBuffer & buffer, const Array & dofs, const SynchronizationTag & tag) const override; void unpackData(CommunicationBuffer & buffer, const Array & dofs, const SynchronizationTag & tag) override; protected: void splitElementByMaterial(const Array & elements, std::vector> & elements_per_mat) const; template void splitByMaterial(const Array & elements, Operation && op) const; /* ------------------------------------------------------------------------ */ /* Mesh Event Handler inherited members */ /* ------------------------------------------------------------------------ */ protected: void onNodesAdded(const Array & nodes_list, const NewNodesEvent & event) override; void onNodesRemoved(const Array & element_list, const Array & new_numbering, const RemovedNodesEvent & event) override; void onElementsAdded(const Array & element_list, const NewElementsEvent & event) override; void onElementsRemoved(const Array & element_list, const ElementTypeMapArray & new_numbering, const RemovedElementsEvent & event) override; void onElementsChanged(const Array & /*unused*/, const Array & /*unused*/, const ElementTypeMapArray & /*unused*/, const ChangedElementsEvent & /*unused*/) override{}; /* ------------------------------------------------------------------------ */ /* Dumpable interface (kept for convenience) and dumper relative functions */ /* ------------------------------------------------------------------------ */ public: virtual void onDump(); //! decide wether a field is a material internal or not bool isInternal(const std::string & field_name, ElementKind element_kind); //! give the amount of data per element virtual ElementTypeMap getInternalDataPerElem(const std::string & field_name, ElementKind kind); //! flatten a given material internal field ElementTypeMapArray & flattenInternal(const std::string & field_name, ElementKind kind, GhostType ghost_type = _not_ghost); //! flatten all the registered material internals void flattenAllRegisteredInternals(ElementKind kind); std::shared_ptr createNodalFieldReal(const std::string & field_name, const std::string & group_name, bool padding_flag) override; std::shared_ptr createNodalFieldBool(const std::string & field_name, const std::string & group_name, bool padding_flag) override; std::shared_ptr createElementalField(const std::string & field_name, const std::string & group_name, bool padding_flag, UInt spatial_dimension, ElementKind kind) override; void dump(const std::string & dumper_name) override; void dump(const std::string & dumper_name, UInt step) override; void dump(const std::string & dumper_name, Real time, UInt step) override; void dump() override; void dump(UInt step) override; void dump(Real time, UInt step) override; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// return the dimension of the system space AKANTU_GET_MACRO(SpatialDimension, Model::spatial_dimension, UInt); /// set the value of the time step void setTimeStep(Real time_step, const ID & solver_id = "") override; /// get the value of the conversion from forces/ mass to acceleration AKANTU_GET_MACRO(F_M2A, f_m2a, Real); /// set the value of the conversion from forces/ mass to acceleration AKANTU_SET_MACRO(F_M2A, f_m2a, Real); /// get the SolidMechanicsModel::displacement array AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Displacement, displacement); /// get the SolidMechanicsModel::displacement array AKANTU_GET_MACRO_DEREF_PTR(Displacement, displacement); /// get the SolidMechanicsModel::previous_displacement array AKANTU_GET_MACRO_DEREF_PTR(PreviousDisplacement, previous_displacement); /// get the SolidMechanicsModel::current_position array const Array & getCurrentPosition(); /// get the SolidMechanicsModel::displacement_increment array AKANTU_GET_MACRO_DEREF_PTR(Increment, displacement_increment); /// get the SolidMechanicsModel::displacement_increment array AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Increment, displacement_increment); /// get the lumped SolidMechanicsModel::mass array AKANTU_GET_MACRO_DEREF_PTR(Mass, mass); /// get the SolidMechanicsModel::velocity array AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Velocity, velocity); /// get the SolidMechanicsModel::velocity array AKANTU_GET_MACRO_DEREF_PTR(Velocity, velocity); /// get the SolidMechanicsModel::acceleration array AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Acceleration, acceleration); /// get the SolidMechanicsModel::acceleration array AKANTU_GET_MACRO_DEREF_PTR(Acceleration, acceleration); /// get the SolidMechanicsModel::external_force array AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(ExternalForce, external_force); /// get the SolidMechanicsModel::external_force array AKANTU_GET_MACRO_DEREF_PTR(ExternalForce, external_force); /// get the SolidMechanicsModel::force array (external forces) [[deprecated("Use getExternalForce instead of this function")]] Array & getForce() { return getExternalForce(); } /// get the SolidMechanicsModel::internal_force array (internal forces) AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(InternalForce, internal_force); /// get the SolidMechanicsModel::internal_force array (internal forces) AKANTU_GET_MACRO_DEREF_PTR(InternalForce, internal_force); /// get the SolidMechanicsModel::blocked_dofs array AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(BlockedDOFs, blocked_dofs); /// get the SolidMechanicsModel::blocked_dofs array AKANTU_GET_MACRO_DEREF_PTR(BlockedDOFs, blocked_dofs); /// get an iterable on the materials inline decltype(auto) getMaterials(); /// get an iterable on the materials inline decltype(auto) getMaterials() const; /// get a particular material (by numerical material index) inline Material & getMaterial(UInt mat_index); /// get a particular material (by numerical material index) inline const Material & getMaterial(UInt mat_index) const; /// get a particular material (by material name) inline Material & getMaterial(const std::string & name); /// get a particular material (by material name) inline const Material & getMaterial(const std::string & name) const; /// get a particular material id from is name inline UInt getMaterialIndex(const std::string & name) const; /// give the number of materials inline UInt getNbMaterials() const { return materials.size(); } /// give the material internal index from its id Int getInternalIndexFromID(const ID & id) const; /// compute the stable time step Real getStableTimeStep(); /** * @brief Returns the total energy for a given energy type * * Energy types of SolidMechanicsModel expected as argument are: * - `kinetic` * - `external work` * * Other energy types are passed on to the materials. All materials should * define a `potential` energy type. For additional energy types, see material * documentation. */ Real getEnergy(const std::string & energy_id); /// Compute energy for an element type and material index Real getEnergy(const std::string & energy_id, ElementType type, UInt index); /// Compute energy for an individual element Real getEnergy(const std::string & energy_id, const Element & element) { return getEnergy(energy_id, element.type, element.element); } /// Compute energy for an element group Real getEnergy(const ID & energy_id, const ID & group_id); AKANTU_GET_MACRO(MaterialByElement, material_index, const ElementTypeMapArray &); AKANTU_GET_MACRO(MaterialLocalNumbering, material_local_numbering, const ElementTypeMapArray &); /// vectors containing local material element index for each global element /// index AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialByElement, material_index, UInt); // AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialByElement, material_index, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialLocalNumbering, material_local_numbering, UInt); // AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialLocalNumbering, // material_local_numbering, UInt); - AKANTU_GET_MACRO_NOT_CONST(MaterialSelector, *material_selector, - MaterialSelector &); + AKANTU_GET_MACRO_NOT_CONST(MaterialSelector, material_selector, + std::shared_ptr); void setMaterialSelector(std::shared_ptr material_selector) { this->material_selector = std::move(material_selector); } /// Access the non_local_manager interface AKANTU_GET_MACRO(NonLocalManager, *non_local_manager, NonLocalManager &); /// get the FEEngine object to integrate or interpolate on the boundary FEEngine & getFEEngineBoundary(const ID & name = "") override; protected: /// compute the stable time step Real getStableTimeStep(GhostType ghost_type); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// release version of the displacement array UInt displacement_release{0}; /// release version of the current_position array UInt current_position_release{0}; /// Check if materials need to recompute the mass array bool need_to_reassemble_lumped_mass{true}; /// Check if materials need to recompute the mass matrix bool need_to_reassemble_mass{true}; /// mapping between material name and material internal id std::map materials_names_to_id; protected: /// conversion coefficient form force/mass to acceleration Real f_m2a{1.0}; /// displacements array std::unique_ptr> displacement; /// displacements array at the previous time step (used in finite deformation) std::unique_ptr> previous_displacement; /// increment of displacement std::unique_ptr> displacement_increment; /// lumped mass array std::unique_ptr> mass; /// velocities array std::unique_ptr> velocity; /// accelerations array std::unique_ptr> acceleration; /// external forces array std::unique_ptr> external_force; /// internal forces array std::unique_ptr> internal_force; /// array specifing if a degree of freedom is blocked or not std::unique_ptr> blocked_dofs; /// array of current position used during update residual std::unique_ptr> current_position; /// Arrays containing the material index for each element ElementTypeMapArray material_index; /// Arrays containing the position in the element filter of the material /// (material's local numbering) ElementTypeMapArray material_local_numbering; /// list of used materials std::vector> materials; /// class defining of to choose a material std::shared_ptr material_selector; using flatten_internal_map = std::map, std::unique_ptr>>; /// map a registered internals to be flattened for dump purposes flatten_internal_map registered_internals; /// non local manager std::unique_ptr non_local_manager; /// tells if the material are instantiated bool are_materials_instantiated{false}; friend class Material; }; /* -------------------------------------------------------------------------- */ namespace BC { namespace Neumann { using FromStress = FromHigherDim; using FromTraction = FromSameDim; } // namespace Neumann } // namespace BC } // namespace akantu /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material.hh" #include "parser.hh" #include "solid_mechanics_model_inline_impl.hh" #include "solid_mechanics_model_tmpl.hh" /* -------------------------------------------------------------------------- */ #endif /* AKANTU_SOLID_MECHANICS_MODEL_HH_ */