diff --git a/src/common/aka_iterators.hh b/src/common/aka_iterators.hh index 30ae540eb..455b2eae3 100644 --- a/src/common/aka_iterators.hh +++ b/src/common/aka_iterators.hh @@ -1,285 +1,285 @@ /** * @file aka_iterators.hh * * @author Nicolas Richart * * @date creation Wed Jul 19 2017 * * @brief iterator interfaces * * @section LICENSE * * Copyright (©) 2010-2011 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <tuple> #include <utility> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_ITERATORS_HH__ #define __AKANTU_AKA_ITERATORS_HH__ namespace akantu { namespace tuple { /* ------------------------------------------------------------------------ */ namespace details { template <size_t N> struct Foreach { template <class Tuple> static inline bool not_equal(Tuple && a, Tuple && b) { if (std::get<N - 1>(std::forward<Tuple>(a)) == std::get<N - 1>(std::forward<Tuple>(b))) return false; return Foreach<N - 1>::not_equal(std::forward<Tuple>(a), std::forward<Tuple>(b)); } }; /* ---------------------------------------------------------------------- */ template <> struct Foreach<0> { template <class Tuple> static inline bool not_equal(Tuple && a, Tuple && b) { return std::get<0>(std::forward<Tuple>(a)) != std::get<0>(std::forward<Tuple>(b)); } }; template <typename... Ts> decltype(auto) make_tuple_no_decay(Ts &&... args) { return std::tuple<Ts...>(std::forward<Ts>(args)...); } template <class F, class Tuple, size_t... Is> void foreach_impl(F && func, Tuple && tuple, std::index_sequence<Is...> &&) { (void)std::initializer_list<int>{ (std::forward<F>(func)(std::get<Is>(std::forward<Tuple>(tuple))), 0)...}; } template <class F, class Tuple, size_t... Is> decltype(auto) transform_impl(F && func, Tuple && tuple, std::index_sequence<Is...> &&) { return make_tuple_no_decay( std::forward<F>(func)(std::get<Is>(std::forward<Tuple>(tuple)))...); } - }; // namespace details + } // namespace details /* ------------------------------------------------------------------------ */ template <class Tuple> bool are_not_equal(Tuple && a, Tuple && b) { return details::Foreach<std::tuple_size<std::decay_t<Tuple>>::value>:: not_equal(std::forward<Tuple>(a), std::forward<Tuple>(b)); } template <class F, class Tuple> void foreach (F && func, Tuple && tuple) { return details::foreach_impl( std::forward<F>(func), std::forward<Tuple>(tuple), std::make_index_sequence< std::tuple_size<std::decay_t<Tuple>>::value>{}); } template <class F, class Tuple> decltype(auto) transform(F && func, Tuple && tuple) { return details::transform_impl( std::forward<F>(func), std::forward<Tuple>(tuple), std::make_index_sequence< std::tuple_size<std::decay_t<Tuple>>::value>{}); } } // namespace tuple /* -------------------------------------------------------------------------- */ namespace iterators { template <class... Iterators> class ZipIterator { private: using tuple_t = std::tuple<Iterators...>; public: explicit ZipIterator(tuple_t iterators) : iterators(std::move(iterators)) {} decltype(auto) operator*() { return tuple::transform([] (auto && it) -> decltype(auto) {return *it;}, iterators); } ZipIterator & operator++() { tuple::foreach ([] (auto && it) { ++it; }, iterators); return *this; } bool operator==(const ZipIterator & other) const { return not tuple::are_not_equal(iterators, other.iterators); } bool operator!=(const ZipIterator & other) const { return tuple::are_not_equal(iterators, other.iterators); } private: tuple_t iterators; }; } // namespace iterators /* -------------------------------------------------------------------------- */ template <class... Iterators> decltype(auto) zip_iterator(std::tuple<Iterators...> && iterators_tuple) { auto zip = iterators::ZipIterator<Iterators...>( std::forward<decltype(iterators_tuple)>(iterators_tuple)); return zip; } /* -------------------------------------------------------------------------- */ namespace containers { template <class... Containers> class ZipContainer { using containers_t = std::tuple<Containers...>; public: explicit ZipContainer(Containers &&... containers) : containers(std::forward<Containers>(containers)...) {} decltype(auto) begin() const { return zip_iterator( tuple::transform([] (auto && c) { return c.begin(); }, std::forward<containers_t>(containers))); } decltype(auto) end() const { return zip_iterator( tuple::transform([] (auto && c) { return c.end(); }, std::forward<containers_t>(containers))); } decltype(auto) begin() { return zip_iterator( tuple::transform([] (auto && c) { return c.begin(); }, std::forward<containers_t>(containers))); } decltype(auto) end() { return zip_iterator( tuple::transform([] (auto && c) { return c.end(); }, std::forward<containers_t>(containers))); } private: containers_t containers; }; } // namespace containers /* -------------------------------------------------------------------------- */ template <class... Containers> decltype(auto) zip(Containers &&... conts) { return containers::ZipContainer<Containers...>( std::forward<Containers>(conts)...); } /* -------------------------------------------------------------------------- */ /* Arange */ /* -------------------------------------------------------------------------- */ namespace iterators { template <class T> class ArangeIterator { public: using value_type = T; using pointer = T *; using reference = T &; using iterator_category = std::input_iterator_tag; constexpr ArangeIterator(T value, T step) : value(value), step(step) {} constexpr ArangeIterator(const ArangeIterator &) = default; constexpr ArangeIterator & operator++() { value += step; return *this; } constexpr const T & operator*() const { return value; } constexpr bool operator==(const ArangeIterator & other) const { return (value == other.value) and (step == other.step); } constexpr bool operator!=(const ArangeIterator & other) const { return not operator==(other); } private: T value{0}; const T step{1}; }; } // namespace iterators namespace containers { template <class T> class ArangeContainer { public: using iterator = iterators::ArangeIterator<T>; constexpr ArangeContainer(T start, T stop, T step = 1) : start(start), stop((stop - start) % step == 0 ? stop : start + (1 + (stop - start) / step) * step), step(step) {} explicit constexpr ArangeContainer(T stop) : ArangeContainer(0, stop, 1) {} constexpr T operator[](size_t i) { T val = start + i * step; assert(val < stop && "i is out of range"); return val; } constexpr T size() { return (stop - start) / step; } constexpr iterator begin() { return iterator(start, step); } constexpr iterator end() { return iterator(stop, step); } private: const T start{0}, stop{0}, step{1}; }; } // namespace containers template <class T, typename = std::enable_if_t<std::is_integral<std::decay_t<T>>::value>> inline decltype(auto) arange(const T & stop) { return containers::ArangeContainer<T>(stop); } template <class T1, class T2, typename = std::enable_if_t< std::is_integral<std::common_type_t<T1, T2>>::value>> inline constexpr decltype(auto) arange(const T1 & start, const T2 & stop) { return containers::ArangeContainer<std::common_type_t<T1, T2>>(start, stop); } template <class T1, class T2, class T3, typename = std::enable_if_t< std::is_integral<std::common_type_t<T1, T2, T3>>::value>> inline constexpr decltype(auto) arange(const T1 & start, const T2 & stop, const T3 & step) { return containers::ArangeContainer<std::common_type_t<T1, T2, T3>>( start, stop, step); } /* -------------------------------------------------------------------------- */ template <class Container> inline constexpr decltype(auto) enumerate(Container && container, size_t start_ = 0) { auto stop = std::forward<Container>(container).size(); decltype(stop) start = start_; return zip(arange(start, stop), std::forward<Container>(container)); } } // namespace akantu #endif /* __AKANTU_AKA_ITERATORS_HH__ */ diff --git a/src/common/aka_named_argument.hh b/src/common/aka_named_argument.hh index b64400f38..0f90486bb 100644 --- a/src/common/aka_named_argument.hh +++ b/src/common/aka_named_argument.hh @@ -1,163 +1,164 @@ /** * @file aka_named_argument.hh * * @author Marco Arena * * @date creation Fri Jun 16 2017 * * @brief A Documented file. * * @section LICENSE * * Public Domain ? https://gist.github.com/ilpropheta/7576dce4c3249df89f85 * */ /* -------------------------------------------------------------------------- */ +#include "aka_compatibilty_with_cpp_standard.hh" #include <tuple> #include <type_traits> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_NAMED_ARGUMENT_HH__ #define __AKANTU_AKA_NAMED_ARGUMENT_HH__ namespace akantu { namespace named_argument { struct param_t_trait {}; /* -- Pack utils (proxy version) ------------------------------------------ */ /// Proxy containing [tag, value] template <typename tag, typename type> struct param_t : param_t_trait { using _tag = tag; using _type = type; template <typename T> explicit param_t(T && value) : _value(std::forward<T>(value)) {} type _value; }; /* * Tagged proxy that allows syntax _name = value * operator=(T&&) returns a param_t instance **/ template <typename tag> struct param_proxy { using _tag = tag; template <typename T> decltype(auto) operator=(T && value) { return param_t<tag, decltype(value)>{std::forward<T>(value)}; } }; /* Same as type_at but it's supposed to be used by passing a pack of param_t (_tag is looked for instead of a plain type). This and type_at should be refactored. */ template <typename T, typename head, typename... tail> struct type_at_p { enum { _tmp = (std::is_same<T, typename std::decay_t<head>::_tag>::value) ? 0 : type_at_p<T, tail...>::_pos }; enum { _pos = _tmp == -1 ? -1 : 1 + _tmp }; }; template <typename T, typename head> struct type_at_p<T, head> { enum { _pos = (std::is_same<T, typename std::decay<head>::type::_tag>::value ? 1 : -1) }; }; template <typename... Ts> struct type_at { enum { _pos = -1 }; }; template <typename T, typename head, typename... tail> struct type_at<T, head, tail...> { enum { _tmp = type_at_p<T, head, tail...>::_pos }; enum { _pos = _tmp == 1 ? 0 : (_tmp == -1 ? -1 : _tmp - 1) }; }; /* Same as get_at but it's supposed to be used by passing a pack of param_t (_type is retrieved instead) This and get_at should be refactored. */ template <int pos, int curr> struct get_at { static_assert(pos >= 0, "Required parameter"); template <typename head, typename... tail> static decltype(auto) get(head &&, tail &&... t) { return get_at<pos, curr + 1>::get(std::forward<tail>(t)...); } }; template <int pos> struct get_at<pos, pos> { static_assert(pos >= 0, "Required parameter"); template <typename head, typename... tail> static decltype(auto) get(head && h, tail &&...) { return std::forward<decltype(h._value)>(h._value); } }; // Optional version template <int pos, int curr> struct get_optional { template <typename T, typename... pack> static decltype(auto) get(T &&, pack &&... _pack) { return get_at<pos, curr>::get(std::forward<pack>(_pack)...); } }; template <int curr> struct get_optional<-1, curr> { template <typename T, typename... pack> static decltype(auto) get(T && _default, pack &&...) { return std::forward<T>(_default); } }; } // namespace named_argument // CONVENIENCE MACROS FOR CLASS DESIGNERS ========== #define TAG_OF_ARGUMENT(_name) p_##_name #define TAG_OF_ARGUMENT_WNS(_name) TAG_OF_ARGUMENT(_name) #define REQUIRED_NAMED_ARG(_name) \ named_argument::get_at< \ named_argument::type_at<TAG_OF_ARGUMENT_WNS(_name), pack...>::_pos, \ 0>::get(std::forward<pack>(_pack)...) #define REQUIRED_NAMED_ARG(_name) \ named_argument::get_at< \ named_argument::type_at<TAG_OF_ARGUMENT_WNS(_name), pack...>::_pos, \ 0>::get(std::forward<pack>(_pack)...) #define OPTIONAL_NAMED_ARG(_name, _defaultVal) \ named_argument::get_optional< \ named_argument::type_at<TAG_OF_ARGUMENT_WNS(_name), pack...>::_pos, \ 0>::get(_defaultVal, std::forward<pack>(_pack)...) #define DECLARE_NAMED_ARGUMENT(name) \ struct TAG_OF_ARGUMENT(name) {}; \ named_argument::param_proxy<TAG_OF_ARGUMENT_WNS(name)> _##name \ __attribute__((unused)) namespace { struct use_named_args_t {}; use_named_args_t use_named_args __attribute__((unused)); } // namespace template <typename T> struct is_named_argument : public std::false_type {}; template <typename... type> struct is_named_argument<named_argument::param_t<type...>> : public std::true_type {}; template <typename... pack> using are_named_argument = aka::conjunction<is_named_argument<std::decay_t<pack>>...>; } // namespace akantu #endif /* __AKANTU_AKA_NAMED_ARGUMENT_HH__ */ diff --git a/src/model/structural_mechanics/structural_mechanics_model_mass.cc b/src/model/structural_mechanics/structural_mechanics_model_mass.cc index d5d20a54d..82046c06e 100644 --- a/src/model/structural_mechanics/structural_mechanics_model_mass.cc +++ b/src/model/structural_mechanics/structural_mechanics_model_mass.cc @@ -1,77 +1,77 @@ /** * @file structural_mechanics_model_mass.cc * * @author Sébastien Hartmann <sebastien.hartmann@epfl.ch> * * @date creation: Mon Jul 07 2014 * @date last modification: Thu Oct 15 2015 * * @brief function handling mass computation * * @section LICENSE * * Copyright (©) 2014, 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "structural_mechanics_model.hh" #include "material.hh" #include "integrator_gauss.hh" #include "shape_structural.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class ComputeRhoFunctor { public: explicit ComputeRhoFunctor(const StructuralMechanicsModel & model) : model(model){}; void operator()(Matrix<Real> & rho, const Element & element) const { Real mat_rho = model.getMaterial(element).rho; rho.set(mat_rho); } private: const StructuralMechanicsModel & model; }; /* -------------------------------------------------------------------------- */ void StructuralMechanicsModel::assembleMass(){ AKANTU_DEBUG_IN(); assembleMass(_not_ghost); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void StructuralMechanicsModel::assembleMass(GhostType /*ghost_type*/) { +void StructuralMechanicsModel::assembleMass(GhostType ghost_type) { AKANTU_DEBUG_IN(); MyFEEngineType & fem = getFEEngineClass<MyFEEngineType>(); ComputeRhoFunctor compute_rho(*this); for (auto type : mesh.elementTypes(spatial_dimension, ghost_type, _ek_structural)) { fem.assembleFieldMatrix(compute_rho, "M", "displacement", this->getDOFManager(), type, ghost_type); } AKANTU_DEBUG_OUT(); } } // akantu