diff --git a/python/py_aka_common.cc b/python/py_aka_common.cc index 6a4de4fb3..9c026c292 100644 --- a/python/py_aka_common.cc +++ b/python/py_aka_common.cc @@ -1,134 +1,150 @@ /** * Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu * * 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 +#include /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ namespace py = pybind11; namespace akantu { /* -------------------------------------------------------------------------- */ #define PY_AKANTU_PP_VALUE(s, data, elem) \ .value(BOOST_PP_STRINGIZE(elem), BOOST_PP_CAT(data, elem)) #define PY_AKANTU_REGISTER_ENUM_(type_name, list, prefix, mod) \ py::enum_(mod, BOOST_PP_STRINGIZE(type_name)) \ BOOST_PP_SEQ_FOR_EACH(PY_AKANTU_PP_VALUE, \ prefix, list) \ .export_values() #define PY_AKANTU_REGISTER_CLASS_ENUM(type_name, list, mod) \ PY_AKANTU_REGISTER_ENUM_(type_name, list, type_name::_, mod) #define PY_AKANTU_REGISTER_ENUM(type_name, list, mod) \ PY_AKANTU_REGISTER_ENUM_(type_name, list, , mod) /* -------------------------------------------------------------------------- */ void register_initialize(py::module & mod) { mod.def("__initialize", []() { int nb_args = 0; char ** null = nullptr; initialize(nb_args, null); }); } void register_enums(py::module & mod) { py::enum_(mod, "SpatialDirection") .value("_x", _x) .value("_y", _y) .value("_z", _z) .export_values(); py::enum_(mod, "AnalysisMethod") .value("_static", _static) .value("_implicit_dynamic", _implicit_dynamic) .value("_explicit_lumped_mass", _explicit_lumped_mass) .value("_explicit_lumped_capacity", _explicit_lumped_capacity) .value("_explicit_consistent_mass", _explicit_consistent_mass) .value("_explicit_contact", _explicit_contact) .value("_implicit_contact", _implicit_contact) .export_values(); PY_AKANTU_REGISTER_CLASS_ENUM(ModelType, AKANTU_MODEL_TYPES, mod); PY_AKANTU_REGISTER_CLASS_ENUM(NonLinearSolverType, AKANTU_NON_LINEAR_SOLVER_TYPES, mod); PY_AKANTU_REGISTER_CLASS_ENUM(TimeStepSolverType, AKANTU_TIME_STEP_SOLVER_TYPE, mod); PY_AKANTU_REGISTER_CLASS_ENUM(IntegrationSchemeType, AKANTU_INTEGRATION_SCHEME_TYPE, mod); PY_AKANTU_REGISTER_CLASS_ENUM(SolveConvergenceCriteria, AKANTU_SOLVE_CONVERGENCE_CRITERIA, mod); py::enum_(mod, "CohesiveMethod") .value("_intrinsic", _intrinsic) .value("_extrinsic", _extrinsic) .export_values(); py::enum_(mod, "GhostType") .value("_not_ghost", _not_ghost) .value("_ghost", _ghost) .value("_casper", _casper) .export_values(); py::enum_(mod, "MeshIOType") .value("_miot_auto", _miot_auto) .value("_miot_gmsh", _miot_gmsh) .value("_miot_gmsh_struct", _miot_gmsh_struct) .value("_miot_diana", _miot_diana) .value("_miot_abaqus", _miot_abaqus) .export_values(); py::enum_(mod, "MatrixType") .value("_unsymmetric", _unsymmetric) .value("_symmetric", _symmetric) .export_values(); + py::module mod_rdt = mod.def_submodule("RandomDistributionType"); + py::enum_(mod_rdt, "RandomDistributionTypes") + .value("_uniform", RandomDistributionType::_uniform) + .value("_exponential", RandomDistributionType::_exponential) + .value("_gamma", RandomDistributionType::_gamma) + .value("_weibull", RandomDistributionType::_weibull) + .value("_extreme_value", RandomDistributionType::_extreme_value) + .value("_normal", RandomDistributionType::_normal) + .value("_lognormal", RandomDistributionType::_lognormal) + .value("_chi_squared", RandomDistributionType::_chi_squared) + .value("_cauchy", RandomDistributionType::_cauchy) + .value("_fisher_f", RandomDistributionType::_fisher_f) + .value("_student_t", RandomDistributionType::_student_t) + .export_values(); + PY_AKANTU_REGISTER_ENUM(ElementType, AKANTU_ALL_ELEMENT_TYPE(_not_defined), mod); PY_AKANTU_REGISTER_ENUM(ElementKind, AKANTU_ELEMENT_KIND(_ek_not_defined), mod); } /* -------------------------------------------------------------------------- */ #define AKANTU_PP_STR_TO_TYPE2(s, data, elem) ({BOOST_PP_STRINGIZE(elem), elem}) void register_functions(py::module & mod) { mod.def("getElementTypes", []() { std::map element_types{ BOOST_PP_SEQ_FOR_EACH_I( AKANTU_PP_ENUM, BOOST_PP_SEQ_SIZE(AKANTU_ek_regular_ELEMENT_TYPE), BOOST_PP_SEQ_TRANSFORM(AKANTU_PP_STR_TO_TYPE2, akantu, AKANTU_ek_regular_ELEMENT_TYPE))}; return element_types; }); } #undef AKANTU_PP_STR_TO_TYPE2 } // namespace akantu diff --git a/python/py_parser.cc b/python/py_parser.cc index 7b879aca8..1a519c942 100644 --- a/python/py_parser.cc +++ b/python/py_parser.cc @@ -1,119 +1,125 @@ /** * Copyright (©) 2020-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu * * 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 "py_aka_array.hh" /* -------------------------------------------------------------------------- */ #include #include #include #include /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ namespace py = pybind11; /* -------------------------------------------------------------------------- */ namespace akantu { std::map> map_params; void register_parser(py::module & mod) { py::enum_(mod, "ParameterAccessType", py::arithmetic()) .value("_pat_internal", _pat_internal) .value("_pat_writable", _pat_writable) .value("_pat_readable", _pat_readable) .value("_pat_modifiable", _pat_modifiable) .value("_pat_parsable", _pat_parsable) .value("_pat_parsmod", _pat_parsmod) .export_values(); py::class_(mod, "ParameterRegistry", py::multiple_inheritance()) .def("registerParamReal", [](ParameterRegistry & self, const std::string & name, UInt type, const std::string & description) { Real * p = new Real; map_params[&self][name] = p; self.registerParam(name, *p, ParameterAccessType(type), description); }) .def("registerParamReal", [](ParameterRegistry & self, const Real & _default, const std::string & name, UInt type, const std::string & description) { Real * p = new Real; map_params[&self][name] = p; self.registerParam(name, *p, _default, ParameterAccessType(type), description); }) .def("setReal", [](ParameterRegistry & self, const std::string & name, const Real value) { self.set(name, value); }) .def("getReal", [](ParameterRegistry & self, const std::string & name) -> Real { return self.get(name); }) + .def("setRandom", + [](ParameterRegistry & self, const std::string & name, Real value, + const RandomDistributionType & distribution, Real a, Real b) { + auto param = make_random_parameter(value, distribution, a, b); + self.set(name, value); + }) .def("setBool", [](ParameterRegistry & self, const std::string & name, const bool value) { self.set(name, value); }) .def("getBool", [](ParameterRegistry & self, const std::string & name) -> bool { return self.get(name); }) .def("setString", [](ParameterRegistry & self, const std::string & name, const std::string & value) { self.set(name, value); }) .def("getString", [](ParameterRegistry & self, const std::string & name) -> std::string { std::string tmp = self.get(name); return tmp; }) .def("setInt", [](ParameterRegistry & self, const std::string & name, const Int value) { self.set(name, value); }) .def("getInt", [](ParameterRegistry & self, const std::string & name) -> Int { return self.get(name); }) .def( "getMatrix", [](ParameterRegistry & self, const std::string & name) { const Matrix & res = static_cast &>(self.get(name)); return res; }, py::return_value_policy::copy); py::class_(mod, "Parsable", py::multiple_inheritance()) .def(py::init()); mod.def( "parseInput", [](const std::string & input_file) { getStaticParser().parse(input_file); }, "Parse an Akantu input file"); } } // namespace akantu diff --git a/src/common/aka_random_generator.hh b/src/common/aka_random_generator.hh index 27da8cf97..fc4f6a40b 100644 --- a/src/common/aka_random_generator.hh +++ b/src/common/aka_random_generator.hh @@ -1,274 +1,310 @@ /** * Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * This file is part of Akantu * * 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 "aka_array.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef AKANTU_AKA_RANDOM_GENERATOR_HH_ #define AKANTU_AKA_RANDOM_GENERATOR_HH_ namespace akantu { /* -------------------------------------------------------------------------- */ /* List of available distributions */ /* -------------------------------------------------------------------------- */ -// clang-format off -#define AKANTU_RANDOM_DISTRIBUTION_TYPES \ - ((uniform , std::uniform_real_distribution )) \ - ((exponential , std::exponential_distribution )) \ - ((gamma , std::gamma_distribution )) \ - ((weibull , std::weibull_distribution )) \ - ((extreme_value, std::extreme_value_distribution)) \ - ((normal , std::normal_distribution )) \ - ((lognormal , std::lognormal_distribution )) \ - ((chi_squared , std::chi_squared_distribution )) \ - ((cauchy , std::cauchy_distribution )) \ - ((fisher_f , std::fisher_f_distribution )) \ - ((student_t , std::student_t_distribution )) -// clang-format on - -#define AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX(elem) BOOST_PP_CAT(_rdt_, elem) -#define AKANTU_RANDOM_DISTRIBUTION_PREFIX(s, data, elem) \ - AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX(BOOST_PP_TUPLE_ELEM(2, 0, elem)) - -enum RandomDistributionType { - BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(AKANTU_RANDOM_DISTRIBUTION_PREFIX, _, - AKANTU_RANDOM_DISTRIBUTION_TYPES)), - _rdt_not_defined -}; +#define AKANTU_RANDOM_DISTRIBUTION_TYPES \ + (uniform)(exponential)( \ + gamma)(weibull)(extreme_value)(normal)(lognormal)(chi_squared)(cauchy)(fisher_f)(student_t)(not_defined) + +AKANTU_CLASS_ENUM_DECLARE(RandomDistributionType, + AKANTU_RANDOM_DISTRIBUTION_TYPES) +AKANTU_CLASS_ENUM_OUTPUT_STREAM(RandomDistributionType, + AKANTU_RANDOM_DISTRIBUTION_TYPES) +AKANTU_CLASS_ENUM_INPUT_STREAM(RandomDistributionType, + AKANTU_RANDOM_DISTRIBUTION_TYPES) /* -------------------------------------------------------------------------- */ /* Generator */ /* -------------------------------------------------------------------------- */ template class RandomGenerator { /* ------------------------------------------------------------------------ */ private: static long int _seed; // NOLINT static std::default_random_engine generator; // NOLINT /* ------------------------------------------------------------------------ */ public: inline T operator()() { return generator(); } /// function to print the contain of the class void printself(std::ostream & stream, int /* indent */) const { stream << "RandGenerator [seed=" << _seed << "]"; } /* ------------------------------------------------------------------------ */ public: static void seed(long int s) { _seed = s; generator.seed(_seed); } static long int seed() { return _seed; } static constexpr T min() { return std::default_random_engine::min(); } static constexpr T max() { return std::default_random_engine::max(); } }; #if defined(__clang__) template long int RandomGenerator::_seed; // NOLINT template std::default_random_engine RandomGenerator::generator; #endif -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ -#undef AKANTU_RANDOM_DISTRIBUTION_PREFIX - -#define AKANTU_RANDOM_DISTRIBUTION_TYPE_PRINT_CASE(r, data, elem) \ - case AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \ - BOOST_PP_TUPLE_ELEM(2, 0, elem)): { \ - stream << BOOST_PP_STRINGIZE(AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \ - BOOST_PP_TUPLE_ELEM(2, 0, elem))); \ - break; \ - } - -inline std::ostream & operator<<(std::ostream & stream, - RandomDistributionType type) { - switch (type) { - BOOST_PP_SEQ_FOR_EACH(AKANTU_RANDOM_DISTRIBUTION_TYPE_PRINT_CASE, _, - AKANTU_RANDOM_DISTRIBUTION_TYPES) - default: - stream << UInt(type) << " not a RandomDistributionType"; - break; - } - return stream; -} -#undef AKANTU_RANDOM_DISTRIBUTION_TYPE_PRINT_CASE - /* -------------------------------------------------------------------------- */ /* Some Helper */ /* -------------------------------------------------------------------------- */ -template class RandomDistributionTypeHelper { - enum { value = _rdt_not_defined }; +template struct RandomDistributionTypeHelper { + static constexpr RandomDistributionType value = + RandomDistributionType::_not_defined; }; -/* -------------------------------------------------------------------------- */ -#define AKANTU_RANDOM_DISTRIBUTION_TYPE_GET_TYPE(r, data, elem) \ - template \ - struct RandomDistributionTypeHelper > { \ - enum { \ - value = AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX( \ - BOOST_PP_TUPLE_ELEM(2, 0, elem)) \ - }; \ - \ - static void printself(std::ostream & stream) { \ - stream << BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, elem)); \ - } \ - }; - -BOOST_PP_SEQ_FOR_EACH(AKANTU_RANDOM_DISTRIBUTION_TYPE_GET_TYPE, _, - AKANTU_RANDOM_DISTRIBUTION_TYPES) - -#undef AKANTU_RANDOM_DISTRIBUTION_TYPE_GET_TYPE +template <> +struct RandomDistributionTypeHelper> { + static constexpr RandomDistributionType value = + RandomDistributionType::_uniform; +}; + +template <> +struct RandomDistributionTypeHelper> { + static constexpr RandomDistributionType value = + RandomDistributionType::_exponential; +}; +template <> +struct RandomDistributionTypeHelper> { + static constexpr RandomDistributionType value = + RandomDistributionType::_gamma; +}; +template <> +struct RandomDistributionTypeHelper> { + static constexpr RandomDistributionType value = + RandomDistributionType::_weibull; +}; +template <> +struct RandomDistributionTypeHelper> { + static constexpr RandomDistributionType value = + RandomDistributionType::_extreme_value; +}; +template <> +struct RandomDistributionTypeHelper> { + static constexpr RandomDistributionType value = + RandomDistributionType::_normal; +}; +template <> +struct RandomDistributionTypeHelper> { + static constexpr RandomDistributionType value = + RandomDistributionType::_lognormal; +}; +template <> +struct RandomDistributionTypeHelper> { + static constexpr RandomDistributionType value = + RandomDistributionType::_chi_squared; +}; +template <> +struct RandomDistributionTypeHelper> { + static constexpr RandomDistributionType value = + RandomDistributionType::_cauchy; +}; +template <> +struct RandomDistributionTypeHelper> { + static constexpr RandomDistributionType value = + RandomDistributionType::_fisher_f; +}; +template <> +struct RandomDistributionTypeHelper> { + static constexpr RandomDistributionType value = + RandomDistributionType::_student_t; +}; /* -------------------------------------------------------------------------- */ template class RandomDistribution { public: virtual ~RandomDistribution() = default; RandomDistribution() = default; RandomDistribution(const RandomDistribution & other) = default; RandomDistribution(RandomDistribution && other) noexcept = default; RandomDistribution & operator=(const RandomDistribution & other) = default; RandomDistribution & operator=(RandomDistribution && other) noexcept = default; virtual T operator()(RandomGenerator & gen) = 0; virtual std::unique_ptr> make_unique() const = 0; virtual void printself(std::ostream & stream, int = 0) const = 0; }; template class RandomDistributionProxy : public RandomDistribution { public: explicit RandomDistributionProxy(Distribution dist) : distribution(std::move(dist)) {} T operator()(RandomGenerator & gen) override { return distribution(gen); } std::unique_ptr> make_unique() const override { return std::make_unique>( distribution); } void printself(std::ostream & stream, int /* indent */ = 0) const override { - RandomDistributionTypeHelper::printself(stream); + stream << std::to_string( + RandomDistributionTypeHelper::value); stream << " [ " << distribution << " ]"; } private: Distribution distribution; }; /* -------------------------------------------------------------------------- */ /* RandomParameter */ /* -------------------------------------------------------------------------- */ template class RandomParameter { public: template explicit RandomParameter(T base_value, Distribution dist) : base_value(base_value), type(RandomDistributionType( RandomDistributionTypeHelper::value)), distribution_proxy( std::make_unique>( std::move(dist))) {} explicit RandomParameter(T base_value) : base_value(base_value), type(RandomDistributionType( RandomDistributionTypeHelper< T, std::uniform_real_distribution>::value)), distribution_proxy( std::make_unique< RandomDistributionProxy>>( std::uniform_real_distribution(0., 0.))) {} RandomParameter(const RandomParameter & other) : base_value(other.base_value), type(other.type), distribution_proxy(other.distribution_proxy->make_unique()) {} RandomParameter & operator=(const RandomParameter & other) { distribution_proxy = other.distribution_proxy->make_unique(); base_value = other.base_value; type = other.type; return *this; } RandomParameter(RandomParameter && other) noexcept = default; RandomParameter & operator=(RandomParameter && other) noexcept = default; virtual ~RandomParameter() = default; inline void setBaseValue(const T & value) { this->base_value = value; } inline T getBaseValue() const { return this->base_value; } template