diff --git a/packages/core.cmake b/packages/core.cmake index d57a5ef5a..e173bc0d6 100644 --- a/packages/core.cmake +++ b/packages/core.cmake @@ -1,593 +1,594 @@ #=============================================================================== # @file core.cmake # # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @author Nicolas Richart <nicolas.richart@epfl.ch> # # @date creation: Mon Nov 21 2011 # @date last modification: Mon Jan 18 2016 # # @brief package description for core # # @section LICENSE # # Copyright (©) 2010-2012, 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/>. # #=============================================================================== package_declare(core NOT_OPTIONAL DESCRIPTION "core package for Akantu" FEATURES_PUBLIC cxx_strong_enums cxx_defaulted_functions cxx_deleted_functions cxx_auto_type cxx_decltype_auto FEATURES_PRIVATE cxx_lambdas cxx_nullptr cxx_delegated_constructors cxx_range_for ) package_declare_sources(core common/aka_array.cc common/aka_array.hh common/aka_array_tmpl.hh common/aka_blas_lapack.hh common/aka_circular_array.hh common/aka_circular_array_inline_impl.cc common/aka_common.cc common/aka_common.hh common/aka_common_inline_impl.cc common/aka_csr.hh common/aka_element_classes_info_inline_impl.cc common/aka_error.cc common/aka_error.hh common/aka_event_handler_manager.hh common/aka_extern.cc common/aka_factory.hh common/aka_fwd.hh common/aka_grid_dynamic.hh common/aka_math.cc common/aka_math.hh common/aka_math_tmpl.hh common/aka_memory.cc common/aka_memory.hh common/aka_memory_inline_impl.cc common/aka_named_argument.hh common/aka_random_generator.hh common/aka_safe_enum.hh common/aka_static_memory.cc common/aka_static_memory.hh common/aka_static_memory_inline_impl.cc common/aka_static_memory_tmpl.hh common/aka_typelist.hh common/aka_types.hh common/aka_visitor.hh common/aka_voigthelper.hh common/aka_voigthelper_tmpl.hh common/aka_voigthelper.cc common/aka_warning.hh common/aka_warning_restore.hh common/aka_iterators.hh common/aka_static_if.hh + common/aka_compatibilty_with_cpp_standard.hh fe_engine/element_class.cc fe_engine/element_class.hh fe_engine/element_class_tmpl.hh fe_engine/element_classes/element_class_hexahedron_8_inline_impl.cc fe_engine/element_classes/element_class_hexahedron_20_inline_impl.cc fe_engine/element_classes/element_class_pentahedron_6_inline_impl.cc fe_engine/element_classes/element_class_pentahedron_15_inline_impl.cc fe_engine/element_classes/element_class_point_1_inline_impl.cc fe_engine/element_classes/element_class_quadrangle_4_inline_impl.cc fe_engine/element_classes/element_class_quadrangle_8_inline_impl.cc fe_engine/element_classes/element_class_segment_2_inline_impl.cc fe_engine/element_classes/element_class_segment_3_inline_impl.cc fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.cc fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.cc fe_engine/element_classes/element_class_triangle_3_inline_impl.cc fe_engine/element_classes/element_class_triangle_6_inline_impl.cc fe_engine/element_type_conversion.hh fe_engine/fe_engine.cc fe_engine/fe_engine.hh fe_engine/fe_engine_inline_impl.cc fe_engine/fe_engine_template.hh fe_engine/fe_engine_template_tmpl_field.hh fe_engine/fe_engine_template_tmpl.hh fe_engine/geometrical_element.cc fe_engine/gauss_integration.cc fe_engine/gauss_integration_tmpl.hh fe_engine/integrator.hh fe_engine/integrator_gauss.hh fe_engine/integrator_gauss_inline_impl.cc fe_engine/interpolation_element.cc fe_engine/interpolation_element_tmpl.hh fe_engine/integration_point.hh fe_engine/shape_functions.hh fe_engine/shape_functions.cc fe_engine/shape_functions_inline_impl.cc fe_engine/shape_lagrange_base.cc fe_engine/shape_lagrange_base.hh fe_engine/shape_lagrange_base_inline_impl.cc fe_engine/shape_lagrange.cc fe_engine/shape_lagrange.hh fe_engine/shape_lagrange_inline_impl.cc fe_engine/element.hh io/dumper/dumpable.hh io/dumper/dumpable.cc io/dumper/dumpable_dummy.hh io/dumper/dumpable_inline_impl.hh io/dumper/dumper_field.hh io/dumper/dumper_material_padders.hh io/dumper/dumper_filtered_connectivity.hh io/dumper/dumper_element_partition.hh io/mesh_io.cc io/mesh_io.hh io/mesh_io/mesh_io_abaqus.cc io/mesh_io/mesh_io_abaqus.hh io/mesh_io/mesh_io_diana.cc io/mesh_io/mesh_io_diana.hh io/mesh_io/mesh_io_msh.cc io/mesh_io/mesh_io_msh.hh #io/model_io.cc #io/model_io.hh io/parser/algebraic_parser.hh io/parser/input_file_parser.hh io/parser/parsable.cc io/parser/parsable.hh io/parser/parsable_tmpl.hh io/parser/parser.cc io/parser/parser_real.cc io/parser/parser_random.cc io/parser/parser_types.cc io/parser/parser_input_files.cc io/parser/parser.hh io/parser/parser_tmpl.hh io/parser/parser_grammar_tmpl.hh io/parser/cppargparse/cppargparse.hh io/parser/cppargparse/cppargparse.cc io/parser/cppargparse/cppargparse_tmpl.hh io/parser/parameter_registry.cc io/parser/parameter_registry.hh io/parser/parameter_registry_tmpl.hh mesh/element_group.cc mesh/element_group.hh mesh/element_group_inline_impl.cc mesh/element_type_map.cc mesh/element_type_map.hh mesh/element_type_map_tmpl.hh mesh/element_type_map_filter.hh mesh/group_manager.cc mesh/group_manager.hh mesh/group_manager_inline_impl.cc mesh/mesh.cc mesh/mesh.hh mesh/mesh_accessor.hh mesh/mesh_accessor.cc mesh/mesh_events.hh mesh/mesh_filter.hh mesh/mesh_data.cc mesh/mesh_data.hh mesh/mesh_data_tmpl.hh mesh/mesh_inline_impl.cc mesh/node_group.cc mesh/node_group.hh mesh/node_group_inline_impl.cc mesh/mesh_iterators.hh mesh_utils/mesh_partition.cc mesh_utils/mesh_partition.hh mesh_utils/mesh_partition/mesh_partition_mesh_data.cc mesh_utils/mesh_partition/mesh_partition_mesh_data.hh mesh_utils/mesh_partition/mesh_partition_scotch.hh mesh_utils/mesh_utils_pbc.cc mesh_utils/mesh_utils.cc mesh_utils/mesh_utils.hh mesh_utils/mesh_utils_distribution.cc mesh_utils/mesh_utils_distribution.hh mesh_utils/mesh_utils.hh mesh_utils/mesh_utils_inline_impl.cc mesh_utils/global_ids_updater.hh mesh_utils/global_ids_updater.cc mesh_utils/global_ids_updater_inline_impl.cc model/boundary_condition.hh model/boundary_condition_functor.hh model/boundary_condition_functor_inline_impl.cc model/boundary_condition_tmpl.hh model/common/neighborhood_base.hh model/common/neighborhood_base.cc model/common/neighborhood_base_inline_impl.cc model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.cc model/common/non_local_toolbox/non_local_manager.hh model/common/non_local_toolbox/non_local_manager.cc model/common/non_local_toolbox/non_local_manager_inline_impl.cc model/common/non_local_toolbox/non_local_manager_callback.hh model/common/non_local_toolbox/non_local_neighborhood_base.hh model/common/non_local_toolbox/non_local_neighborhood_base.cc model/common/non_local_toolbox/non_local_neighborhood.hh model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh model/common/non_local_toolbox/non_local_neighborhood_inline_impl.cc model/common/non_local_toolbox/base_weight_function.hh model/common/non_local_toolbox/base_weight_function_inline_impl.cc model/dof_manager.cc model/dof_manager.hh model/dof_manager_default.cc model/dof_manager_default.hh model/dof_manager_default_inline_impl.cc model/dof_manager_inline_impl.cc model/model_solver.cc model/model_solver.hh model/model_solver_tmpl.hh model/non_linear_solver.cc model/non_linear_solver.hh model/non_linear_solver_default.hh model/non_linear_solver_lumped.cc model/non_linear_solver_lumped.hh model/solver_callback.hh model/solver_callback.cc model/time_step_solver.hh model/time_step_solvers/time_step_solver.cc model/time_step_solvers/time_step_solver_default.cc model/time_step_solvers/time_step_solver_default.hh model/time_step_solvers/time_step_solver_default_explicit.hh model/non_linear_solver_callback.hh model/time_step_solvers/time_step_solver_default_solver_callback.hh model/integration_scheme/generalized_trapezoidal.cc model/integration_scheme/generalized_trapezoidal.hh model/integration_scheme/integration_scheme.cc model/integration_scheme/integration_scheme.hh model/integration_scheme/integration_scheme_1st_order.cc model/integration_scheme/integration_scheme_1st_order.hh model/integration_scheme/integration_scheme_2nd_order.cc model/integration_scheme/integration_scheme_2nd_order.hh model/integration_scheme/newmark-beta.cc model/integration_scheme/newmark-beta.hh model/integration_scheme/pseudo_time.cc model/integration_scheme/pseudo_time.hh model/model.cc model/model.hh model/model_inline_impl.cc model/solid_mechanics/material.cc model/solid_mechanics/material.hh model/solid_mechanics/material_inline_impl.cc model/solid_mechanics/material_selector.hh model/solid_mechanics/material_selector_tmpl.hh model/solid_mechanics/materials/internal_field.hh model/solid_mechanics/materials/internal_field_tmpl.hh model/solid_mechanics/materials/random_internal_field.hh model/solid_mechanics/materials/random_internal_field_tmpl.hh model/solid_mechanics/solid_mechanics_model.cc model/solid_mechanics/solid_mechanics_model.hh model/solid_mechanics/solid_mechanics_model_inline_impl.cc model/solid_mechanics/solid_mechanics_model_io.cc model/solid_mechanics/solid_mechanics_model_mass.cc model/solid_mechanics/solid_mechanics_model_material.cc model/solid_mechanics/solid_mechanics_model_tmpl.hh model/solid_mechanics/solid_mechanics_model_event_handler.hh model/solid_mechanics/materials/plane_stress_toolbox.hh model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh model/solid_mechanics/materials/material_core_includes.hh model/solid_mechanics/materials/material_elastic.cc model/solid_mechanics/materials/material_elastic.hh model/solid_mechanics/materials/material_elastic_inline_impl.cc model/solid_mechanics/materials/material_thermal.cc model/solid_mechanics/materials/material_thermal.hh model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh model/solid_mechanics/materials/material_elastic_orthotropic.cc model/solid_mechanics/materials/material_elastic_orthotropic.hh model/solid_mechanics/materials/material_damage/material_damage.hh model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh model/solid_mechanics/materials/material_damage/material_marigo.cc model/solid_mechanics/materials/material_damage/material_marigo.hh model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.cc model/solid_mechanics/materials/material_damage/material_mazars.cc model/solid_mechanics/materials/material_damage/material_mazars.hh model/solid_mechanics/materials/material_damage/material_mazars_inline_impl.cc model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh model/solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.cc model/solid_mechanics/materials/material_plastic/material_plastic.cc model/solid_mechanics/materials/material_plastic/material_plastic.hh model/solid_mechanics/materials/material_plastic/material_plastic_inline_impl.cc model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.cc model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh model/solid_mechanics/materials/material_non_local.hh model/solid_mechanics/materials/material_non_local_tmpl.hh model/solid_mechanics/materials/material_non_local_includes.hh model/solid_mechanics/materials/material_non_local_inline_impl.cc solver/sparse_solver.cc solver/sparse_solver.hh solver/sparse_solver_inline_impl.cc solver/sparse_matrix.cc solver/sparse_matrix.hh solver/sparse_matrix_inline_impl.cc solver/sparse_matrix_aij.cc solver/sparse_matrix_aij.hh solver/sparse_matrix_aij_inline_impl.cc solver/terms_to_assemble.hh synchronizer/communication_descriptor_tmpl.hh synchronizer/communications_tmpl.hh synchronizer/communication_buffer.hh synchronizer/communication_buffer_inline_impl.cc synchronizer/communication_descriptor.hh synchronizer/communication_tag.hh synchronizer/communications.hh synchronizer/data_accessor.cc synchronizer/data_accessor.hh synchronizer/element_synchronizer.cc synchronizer/element_synchronizer.hh synchronizer/node_synchronizer.cc synchronizer/node_synchronizer.hh synchronizer/dof_synchronizer.cc synchronizer/dof_synchronizer.hh synchronizer/dof_synchronizer_inline_impl.cc synchronizer/element_info_per_processor.cc synchronizer/element_info_per_processor.hh synchronizer/element_info_per_processor_tmpl.hh synchronizer/filtered_synchronizer.cc synchronizer/filtered_synchronizer.hh synchronizer/grid_synchronizer.cc synchronizer/grid_synchronizer.hh synchronizer/grid_synchronizer_tmpl.hh synchronizer/master_element_info_per_processor.cc synchronizer/node_info_per_processor.cc synchronizer/node_info_per_processor.hh synchronizer/real_static_communicator.hh synchronizer/slave_element_info_per_processor.cc synchronizer/static_communicator.cc synchronizer/static_communicator.hh synchronizer/static_communicator_dummy.hh synchronizer/static_communicator_inline_impl.hh synchronizer/synchronizer.cc synchronizer/synchronizer.hh synchronizer/synchronizer_impl.hh synchronizer/synchronizer_impl_tmpl.hh synchronizer/synchronizer_registry.cc synchronizer/synchronizer_registry.hh synchronizer/synchronizer_tmpl.hh ) package_declare_elements(core ELEMENT_TYPES _point_1 _segment_2 _segment_3 _triangle_3 _triangle_6 _quadrangle_4 _quadrangle_8 _tetrahedron_4 _tetrahedron_10 _pentahedron_6 _pentahedron_15 _hexahedron_8 _hexahedron_20 KIND regular GEOMETRICAL_TYPES _gt_point _gt_segment_2 _gt_segment_3 _gt_triangle_3 _gt_triangle_6 _gt_quadrangle_4 _gt_quadrangle_8 _gt_tetrahedron_4 _gt_tetrahedron_10 _gt_hexahedron_8 _gt_hexahedron_20 _gt_pentahedron_6 _gt_pentahedron_15 INTERPOLATION_TYPES _itp_lagrange_point_1 _itp_lagrange_segment_2 _itp_lagrange_segment_3 _itp_lagrange_triangle_3 _itp_lagrange_triangle_6 _itp_lagrange_quadrangle_4 _itp_serendip_quadrangle_8 _itp_lagrange_tetrahedron_4 _itp_lagrange_tetrahedron_10 _itp_lagrange_hexahedron_8 _itp_serendip_hexahedron_20 _itp_lagrange_pentahedron_6 _itp_lagrange_pentahedron_15 GEOMETRICAL_SHAPES _gst_point _gst_triangle _gst_square _gst_prism GAUSS_INTEGRATION_TYPES _git_point _git_segment _git_triangle _git_tetrahedron _git_pentahedron INTERPOLATION_KIND _itk_lagrangian FE_ENGINE_LISTS gradient_on_integration_points interpolate_on_integration_points interpolate compute_normals_on_integration_points inverse_map contains compute_shapes compute_shapes_derivatives get_shapes_derivatives lagrange_base ) package_declare_material_infos(core LIST AKANTU_CORE_MATERIAL_LIST INCLUDE material_core_includes.hh ) package_declare_documentation_files(core manual.sty manual.cls manual.tex manual-macros.sty manual-titlepages.tex manual-authors.tex manual-introduction.tex manual-gettingstarted.tex manual-io.tex manual-feengine.tex manual-solidmechanicsmodel.tex manual-constitutive-laws.tex manual-lumping.tex manual-elements.tex manual-appendix-elements.tex manual-appendix-materials.tex manual-appendix-packages.tex manual-backmatter.tex manual-bibliography.bib manual-bibliographystyle.bst figures/bc_and_ic_example.pdf figures/boundary.pdf figures/boundary.svg figures/dirichlet.pdf figures/dirichlet.svg figures/doc_wheel.pdf figures/doc_wheel.svg figures/dynamic_analysis.png figures/explicit_dynamic.pdf figures/explicit_dynamic.svg figures/static.pdf figures/static.svg figures/hooke_law.pdf figures/hot-point-1.png figures/hot-point-2.png figures/implicit_dynamic.pdf figures/implicit_dynamic.svg figures/insertion.pdf figures/interpolate.pdf figures/interpolate.svg figures/problemDomain.pdf_tex figures/problemDomain.pdf figures/static_analysis.png figures/stress_strain_el.pdf figures/tangent.pdf figures/tangent.svg figures/vectors.pdf figures/vectors.svg figures/stress_strain_neo.pdf figures/visco_elastic_law.pdf figures/isotropic_hardening_plasticity.pdf figures/stress_strain_visco.pdf figures/elements/hexahedron_8.pdf figures/elements/hexahedron_8.svg figures/elements/quadrangle_4.pdf figures/elements/quadrangle_4.svg figures/elements/quadrangle_8.pdf figures/elements/quadrangle_8.svg figures/elements/segment_2.pdf figures/elements/segment_2.svg figures/elements/segment_3.pdf figures/elements/segment_3.svg figures/elements/tetrahedron_10.pdf figures/elements/tetrahedron_10.svg figures/elements/tetrahedron_4.pdf figures/elements/tetrahedron_4.svg figures/elements/triangle_3.pdf figures/elements/triangle_3.svg figures/elements/triangle_6.pdf figures/elements/triangle_6.svg figures/elements/xtemp.pdf ) package_declare_documentation(core "This package is the core engine of \\akantu. It depends on:" "\\begin{itemize}" "\\item A C++ compiler (\\href{http://gcc.gnu.org/}{GCC} >= 4, or \\href{https://software.intel.com/en-us/intel-compilers}{Intel})." "\\item The cross-platform, open-source \\href{http://www.cmake.org/}{CMake} build system." "\\item The \\href{http://www.boost.org/}{Boost} C++ portable libraries." "\\item The \\href{http://www.zlib.net/}{zlib} compression library." "\\end{itemize}" "" "Under Ubuntu (14.04 LTS) the installation can be performed using the commands:" "\\begin{command}" " > sudo apt-get install cmake libboost-dev zlib1g-dev g++" "\\end{command}" "" "Under Mac OS X the installation requires the following steps:" "\\begin{itemize}" "\\item Install Xcode" "\\item Install the command line tools." "\\item Install the MacPorts project which allows to automatically" "download and install opensource packages." "\\end{itemize}" "Then the following commands should be typed in a terminal:" "\\begin{command}" " > sudo port install cmake gcc48 boost" "\\end{command}" ) find_program(READLINK_COMMAND readlink) find_program(ADDR2LINE_COMMAND addr2line) find_program(PATCH_COMMAND patch) mark_as_advanced(READLINK_COMMAND) mark_as_advanced(ADDR2LINE_COMMAND) package_declare_extra_files_to_package(core SOURCES common/aka_element_classes_info.hh.in common/aka_config.hh.in model/solid_mechanics/material_list.hh.in ) if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.9)) package_set_compile_flags(core CXX "-Wno-undefined-var-template") endif() if(DEFINED AKANTU_CXX11_FLAGS) package_declare(core_cxx11 NOT_OPTIONAL DESCRIPTION "C++ 11 additions for Akantu core" COMPILE_FLAGS CXX "${AKANTU_CXX11_FLAGS}") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.6") set(AKANTU_CORE_CXX11 OFF CACHE BOOL "C++ 11 additions for Akantu core - not supported by the selected compiler" FORCE) endif() endif() package_declare_documentation(core_cxx11 "This option activates some features of the C++11 standard. This is usable with GCC>=4.7 or Intel>=13.") else() if(CMAKE_VERSION VERSION_LESS 3.1) message(FATAL_ERROR "Since version 3.0 Akantu requires at least c++11 capable compiler") endif() endif() diff --git a/src/common/aka_array.hh b/src/common/aka_array.hh index a2523289d..d2b6f4e38 100644 --- a/src/common/aka_array.hh +++ b/src/common/aka_array.hh @@ -1,363 +1,363 @@ /** * @file aka_array.hh * * @author Till Junge <till.junge@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Jan 22 2016 * * @brief Array container for Akantu * This container differs from the std::vector from the fact it as 2 dimensions * a main dimension and the size stored per entries * * @section LICENSE * * Copyright (©) 2010-2012, 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/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_VECTOR_HH__ #define __AKANTU_VECTOR_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #include <typeinfo> #include <vector> /* -------------------------------------------------------------------------- */ namespace akantu { /// class that afford to store vectors in static memory class ArrayBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: explicit ArrayBase(ID id = ""); virtual ~ArrayBase(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// get the amount of space allocated in bytes inline UInt getMemorySize() const; /// set the size to zero without freeing the allocated space inline void empty(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// Get the real size allocated in memory AKANTU_GET_MACRO(AllocatedSize, allocated_size, UInt); /// Get the Size of the Array UInt getsize() const __attribute__((deprecated)) { return size_; } UInt size() const { return size_; } /// Get the number of components AKANTU_GET_MACRO(NbComponent, nb_component, UInt); /// Get the name of th array AKANTU_GET_MACRO(ID, id, const ID &); /// Set the name of th array AKANTU_SET_MACRO(ID, id, const ID &); // AKANTU_GET_MACRO(Tag, tag, const std::string &); // AKANTU_SET_MACRO(Tag, tag, const std::string &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the vector ID id; /// the size allocated UInt allocated_size{0}; /// the size used UInt size_{0}; /// number of components UInt nb_component{1}; /// size of the stored type UInt size_of_type{0}; }; /* -------------------------------------------------------------------------- */ namespace { template <std::size_t dim, typename T> struct IteratorHelper {}; template <typename T> struct IteratorHelper<0, T> { using type = T; }; template <typename T> struct IteratorHelper<1, T> { using type = Vector<T>; }; template <typename T> struct IteratorHelper<2, T> { using type = Matrix<T>; }; template <typename T> struct IteratorHelper<3, T> { using type = Tensor3<T>; }; template <std::size_t dim, typename T> using IteratorHelper_t = typename IteratorHelper<dim, T>::type; } // namespace /* -------------------------------------------------------------------------- */ template <typename T, bool is_scal> class Array : public ArrayBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: using value_type = T; using reference = value_type &; using pointer_type = value_type *; using const_reference = const value_type &; /// Allocation of a new vector explicit inline Array(UInt size = 0, UInt nb_component = 1, const ID & id = ""); /// Allocation of a new vector with a default value Array(UInt size, UInt nb_component, const value_type def_values[], const ID & id = ""); /// Allocation of a new vector with a default value Array(UInt size, UInt nb_component, const_reference value, const ID & id = ""); /// Copy constructor (deep copy if deep=true) Array(const Array<value_type, is_scal> & vect, bool deep = true, const ID & id = ""); #ifndef SWIG /// Copy constructor (deep copy) explicit Array(const std::vector<value_type> & vect); #endif inline ~Array() override; Array & operator=(const Array & a) { /// this is to let STL allocate and copy arrays in the case of /// std::vector::resize AKANTU_DEBUG_ASSERT(this->size == 0, "Cannot copy akantu::Array"); return const_cast<Array &>(a); } /* ------------------------------------------------------------------------ */ /* Iterator */ /* ------------------------------------------------------------------------ */ /// \todo protected: does not compile with intel check why public: - template <class R, class IR = R, bool issame = is_same<IR, T>::value> + template <class R, class IR = R, bool issame = std::is_same<IR, T>::value> class iterator_internal; public: /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ template <typename R = T> class const_iterator; template <typename R = T> class iterator; /* ------------------------------------------------------------------------ */ /// iterator for Array of nb_component = 1 using scalar_iterator = iterator<T>; /// const_iterator for Array of nb_component = 1 using const_scalar_iterator = const_iterator<T>; /// iterator returning Vectors of size n on entries of Array with /// nb_component = n using vector_iterator = iterator<Vector<T>>; /// const_iterator returning Vectors of n size on entries of Array with /// nb_component = n using const_vector_iterator = const_iterator<Vector<T>>; /// iterator returning Matrices of size (m, n) on entries of Array with /// nb_component = m*n using matrix_iterator = iterator<Matrix<T>>; /// const iterator returning Matrices of size (m, n) on entries of Array with /// nb_component = m*n using const_matrix_iterator = const_iterator<Matrix<T>>; /// iterator returning Tensor3 of size (m, n, k) on entries of Array with /// nb_component = m*n*k using tensor3_iterator = iterator<Tensor3<T>>; /// const iterator returning Tensor3 of size (m, n, k) on entries of Array /// with nb_component = m*n*k using const_tensor3_iterator = const_iterator<Tensor3<T>>; /* ------------------------------------------------------------------------ */ template <typename... Ns> inline decltype(auto) begin(Ns... n); template <typename... Ns> inline decltype(auto) end(Ns... n); template <typename... Ns> inline decltype(auto) begin(Ns... n) const; template <typename... Ns> inline decltype(auto) end(Ns... n) const; template <typename... Ns> inline decltype(auto) begin_reinterpret(Ns... n); template <typename... Ns> inline decltype(auto) end_reinterpret(Ns... n); template <typename... Ns> inline decltype(auto) begin_reinterpret(Ns... n) const; template <typename... Ns> inline decltype(auto) end_reinterpret(Ns... n) const; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// append a tuple of size nb_component containing value inline void push_back(const_reference value); /// append a vector // inline void push_back(const value_type new_elem[]); /// append a Vector or a Matrix template <template <typename> class C> inline void push_back(const C<T> & new_elem); /// append the value of the iterator template <typename Ret> inline void push_back(const iterator<Ret> & it); /// erase the value at position i inline void erase(UInt i); /// ask Nico, clarify template <typename R> inline iterator<R> erase(const iterator<R> & it); /// changes the allocated size but not the size virtual void reserve(UInt size); /// change the size of the Array virtual void resize(UInt size); /// change the size of the Array and initialize the values virtual void resize(UInt size, const T & val); /// change the number of components by interlacing data /// @param multiplicator number of interlaced components add /// @param block_size blocks of data in the array /// Examaple for block_size = 2, multiplicator = 2 /// array = oo oo oo -> new array = oo nn nn oo nn nn oo nn nn void extendComponentsInterlaced(UInt multiplicator, UInt stride); /// search elem in the vector, return the position of the first occurrence or /// -1 if not found UInt find(const_reference elem) const; /// @see Array::find(const_reference elem) const UInt find(T elem[]) const; /// @see Array::find(const_reference elem) const template <template <typename> class C> inline UInt find(const C<T> & elem); /// set all entries of the array to 0 inline void clear() { std::fill_n(values, size_ * nb_component, T()); } /// set all entries of the array to the value t /// @param t value to fill the array with inline void set(T t) { std::fill_n(values, size_ * nb_component, t); } /// set all tuples of the array to a given vector or matrix /// @param vm Matrix or Vector to fill the array with template <template <typename> class C> inline void set(const C<T> & vm); /// Append the content of the other array to the current one void append(const Array<T> & other); /// copy another Array in the current Array, the no_sanity_check allows you to /// force the copy in cases where you know what you do with two non matching /// Arrays in terms of n void copy(const Array<T, is_scal> & other, bool no_sanity_check = false); /// give the address of the memory allocated for this vector T * storage() const { return values; }; /// function to print the containt of the class void printself(std::ostream & stream, int indent = 0) const override; protected: /// perform the allocation for the constructors void allocate(UInt size, UInt nb_component = 1); /// resize initializing with uninitialized_fill if fill is set void resizeUnitialized(UInt new_size, bool fill, const T & val = T()); /* ------------------------------------------------------------------------ */ /* Operators */ /* ------------------------------------------------------------------------ */ public: /// substraction entry-wise Array<T, is_scal> & operator-=(const Array<T, is_scal> & other); /// addition entry-wise Array<T, is_scal> & operator+=(const Array<T, is_scal> & other); /// multiply evry entry by alpha Array<T, is_scal> & operator*=(const T & alpha); /// check if the array are identical entry-wise bool operator==(const Array<T, is_scal> & other) const; /// @see Array::operator==(const Array<T, is_scal> & other) const bool operator!=(const Array<T, is_scal> & other) const; /// return a reference to the j-th entry of the i-th tuple inline reference operator()(UInt i, UInt j = 0); /// return a const reference to the j-th entry of the i-th tuple inline const_reference operator()(UInt i, UInt j = 0) const; /// return a reference to the ith component of the 1D array inline reference operator[](UInt i); /// return a const reference to the ith component of the 1D array inline const_reference operator[](UInt i) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// array of values T * values; // /!\ very dangerous }; /* -------------------------------------------------------------------------- */ /* Inline Functions Array<T, is_scal> */ /* -------------------------------------------------------------------------- */ template <typename T, bool is_scal> inline std::ostream & operator<<(std::ostream & stream, const Array<T, is_scal> & _this) { _this.printself(stream); return stream; } /* -------------------------------------------------------------------------- */ /* Inline Functions ArrayBase */ /* -------------------------------------------------------------------------- */ inline std::ostream & operator<<(std::ostream & stream, const ArrayBase & _this) { _this.printself(stream); return stream; } } // namespace akantu #include "aka_array_tmpl.hh" #include "aka_types.hh" #endif /* __AKANTU_VECTOR_HH__ */ diff --git a/src/common/aka_array_tmpl.hh b/src/common/aka_array_tmpl.hh index ed5c40a47..41c10a307 100644 --- a/src/common/aka_array_tmpl.hh +++ b/src/common/aka_array_tmpl.hh @@ -1,1251 +1,1251 @@ /** * @file aka_array_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Jul 15 2010 * @date last modification: Fri Jan 22 2016 * * @brief Inline functions of the classes Array<T> and ArrayBase * * @section LICENSE * * Copyright (©) 2010-2012, 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/>. * */ /* -------------------------------------------------------------------------- */ /* Inline Functions Array<T> */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" /* -------------------------------------------------------------------------- */ #include <memory> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_ARRAY_TMPL_HH__ #define __AKANTU_AKA_ARRAY_TMPL_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> inline T & Array<T, is_scal>::operator()(UInt i, UInt j) { AKANTU_DEBUG_ASSERT(size_ > 0, "The array \"" << id << "\" is empty"); AKANTU_DEBUG_ASSERT((i < size_) && (j < nb_component), "The value at position [" << i << "," << j << "] is out of range in array \"" << id << "\""); return values[i * nb_component + j]; } /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> inline const T & Array<T, is_scal>::operator()(UInt i, UInt j) const { AKANTU_DEBUG_ASSERT(size_ > 0, "The array \"" << id << "\" is empty"); AKANTU_DEBUG_ASSERT((i < size_) && (j < nb_component), "The value at position [" << i << "," << j << "] is out of range in array \"" << id << "\""); return values[i * nb_component + j]; } template <class T, bool is_scal> inline T & Array<T, is_scal>::operator[](UInt i) { AKANTU_DEBUG_ASSERT(size_ > 0, "The array \"" << id << "\" is empty"); AKANTU_DEBUG_ASSERT((i < size_ * nb_component), "The value at position [" << i << "] is out of range in array \"" << id << "\""); return values[i]; } /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> inline const T & Array<T, is_scal>::operator[](UInt i) const { AKANTU_DEBUG_ASSERT(size_ > 0, "The array \"" << id << "\" is empty"); AKANTU_DEBUG_ASSERT((i < size_ * nb_component), "The value at position [" << i << "] is out of range in array \"" << id << "\""); return values[i]; } /* -------------------------------------------------------------------------- */ /** * append a tuple to the array with the value value for all components * @param value the new last tuple or the array will contain nb_component copies * of value */ template <class T, bool is_scal> inline void Array<T, is_scal>::push_back(const T & value) { resizeUnitialized(size_ + 1, true, value); } /* -------------------------------------------------------------------------- */ /** * append a tuple to the array * @param new_elem a C-array containing the values to be copied to the end of * the array */ // template <class T, bool is_scal> // inline void Array<T, is_scal>::push_back(const T new_elem[]) { // UInt pos = size_; // resizeUnitialized(size_ + 1, false); // T * tmp = values + nb_component * pos; // std::uninitialized_copy(new_elem, new_elem + nb_component, tmp); // } /* -------------------------------------------------------------------------- */ /** * append a matrix or a vector to the array * @param new_elem a reference to a Matrix<T> or Vector<T> */ template <class T, bool is_scal> template <template <typename> class C> inline void Array<T, is_scal>::push_back(const C<T> & new_elem) { AKANTU_DEBUG_ASSERT( nb_component == new_elem.size(), "The vector(" << new_elem.size() << ") as not a size compatible with the Array (nb_component=" << nb_component << ")."); UInt pos = size_; resizeUnitialized(size_ + 1, false); T * tmp = values + nb_component * pos; std::uninitialized_copy(new_elem.storage(), new_elem.storage() + nb_component, tmp); } /* -------------------------------------------------------------------------- */ /** * append a tuple to the array * @param it an iterator to the tuple to be copied to the end of the array */ template <class T, bool is_scal> template <class Ret> inline void Array<T, is_scal>::push_back(const Array<T, is_scal>::iterator<Ret> & it) { UInt pos = size_; resizeUnitialized(size_ + 1, false); T * tmp = values + nb_component * pos; T * new_elem = it.data(); std::uninitialized_copy(new_elem, new_elem + nb_component, tmp); } /* -------------------------------------------------------------------------- */ /** * erase an element. If the erased element is not the last of the array, the * last element is moved into the hole in order to maintain contiguity. This * may invalidate existing iterators (For instance an iterator obtained by * Array::end() is no longer correct) and will change the order of the * elements. * @param i index of element to erase */ template <class T, bool is_scal> inline void Array<T, is_scal>::erase(UInt i) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT((size_ > 0), "The array is empty"); AKANTU_DEBUG_ASSERT((i < size_), "The element at position [" << i << "] is out of range (" << i << ">=" << size_ << ")"); if (i != (size_ - 1)) { for (UInt j = 0; j < nb_component; ++j) { values[i * nb_component + j] = values[(size_ - 1) * nb_component + j]; } } resize(size_ - 1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Subtract another array entry by entry from this array in place. Both arrays * must * have the same size and nb_component. If the arrays have different shapes, * code compiled in debug mode will throw an expeption and optimised code * will behave in an unpredicted manner * @param other array to subtract from this * @return reference to modified this */ template <class T, bool is_scal> Array<T, is_scal> & Array<T, is_scal>:: operator-=(const Array<T, is_scal> & vect) { AKANTU_DEBUG_ASSERT((size_ == vect.size_) && (nb_component == vect.nb_component), "The too array don't have the same sizes"); T * a = values; T * b = vect.storage(); for (UInt i = 0; i < size_ * nb_component; ++i) { *a -= *b; ++a; ++b; } return *this; } /* -------------------------------------------------------------------------- */ /** * Add another array entry by entry to this array in place. Both arrays must * have the same size and nb_component. If the arrays have different shapes, * code compiled in debug mode will throw an expeption and optimised code * will behave in an unpredicted manner * @param other array to add to this * @return reference to modified this */ template <class T, bool is_scal> Array<T, is_scal> & Array<T, is_scal>:: operator+=(const Array<T, is_scal> & vect) { AKANTU_DEBUG_ASSERT((size_ == vect.size) && (nb_component == vect.nb_component), "The too array don't have the same sizes"); T * a = values; T * b = vect.storage(); for (UInt i = 0; i < size_ * nb_component; ++i) { *a++ += *b++; } return *this; } /* -------------------------------------------------------------------------- */ /** * Multiply all entries of this array by a scalar in place * @param alpha scalar multiplicant * @return reference to modified this */ template <class T, bool is_scal> Array<T, is_scal> & Array<T, is_scal>::operator*=(const T & alpha) { T * a = values; for (UInt i = 0; i < size_ * nb_component; ++i) { *a++ *= alpha; } return *this; } /* -------------------------------------------------------------------------- */ /** * Compare this array element by element to another. * @param other array to compare to * @return true it all element are equal and arrays have the same shape, else * false */ template <class T, bool is_scal> bool Array<T, is_scal>::operator==(const Array<T, is_scal> & array) const { bool equal = nb_component == array.nb_component && size_ == array.size_ && id == array.id; if (!equal) return false; if (values == array.storage()) return true; else return std::equal(values, values + size_ * nb_component, array.storage()); } /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> bool Array<T, is_scal>::operator!=(const Array<T, is_scal> & array) const { return !operator==(array); } /* -------------------------------------------------------------------------- */ /** * set all tuples of the array to a given vector or matrix * @param vm Matrix or Vector to fill the array with */ template <class T, bool is_scal> template <template <typename> class C> inline void Array<T, is_scal>::set(const C<T> & vm) { AKANTU_DEBUG_ASSERT( nb_component == vm.size(), "The size of the object does not match the number of components"); for (T * it = values; it < values + nb_component * size_; it += nb_component) { std::copy(vm.storage(), vm.storage() + nb_component, it); } } /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> void Array<T, is_scal>::append(const Array<T> & other) { AKANTU_DEBUG_ASSERT( nb_component == other.nb_component, "Cannot append an array with a different number of component"); UInt old_size = this->size_; this->resizeUnitialized(this->size_ + other.size(), false); T * tmp = values + nb_component * old_size; std::uninitialized_copy(other.storage(), other.storage() + other.size() * nb_component, tmp); } /* -------------------------------------------------------------------------- */ /* Functions Array<T, is_scal> */ /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> Array<T, is_scal>::Array(UInt size, UInt nb_component, const ID & id) : ArrayBase(id), values(NULL) { AKANTU_DEBUG_IN(); allocate(size, nb_component); if (!is_scal) { T val = T(); std::uninitialized_fill(values, values + size * nb_component, val); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> Array<T, is_scal>::Array(UInt size, UInt nb_component, const T def_values[], const ID & id) : ArrayBase(id), values(NULL) { AKANTU_DEBUG_IN(); allocate(size, nb_component); T * tmp = values; for (UInt i = 0; i < size; ++i) { tmp = values + nb_component * i; std::uninitialized_copy(def_values, def_values + nb_component, tmp); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> Array<T, is_scal>::Array(UInt size, UInt nb_component, const T & value, const ID & id) : ArrayBase(id), values(NULL) { AKANTU_DEBUG_IN(); allocate(size, nb_component); std::uninitialized_fill_n(values, size * nb_component, value); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> Array<T, is_scal>::Array(const Array<T, is_scal> & vect, bool deep, const ID & id) : ArrayBase(vect) { AKANTU_DEBUG_IN(); this->id = (id == "") ? vect.id : id; if (deep) { allocate(vect.size_, vect.nb_component); T * tmp = values; std::uninitialized_copy(vect.storage(), vect.storage() + size_ * nb_component, tmp); } else { this->values = vect.storage(); this->size_ = vect.size_; this->nb_component = vect.nb_component; this->allocated_size = vect.allocated_size; this->size_of_type = vect.size_of_type; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ #ifndef SWIG template <class T, bool is_scal> Array<T, is_scal>::Array(const std::vector<T> & vect) { AKANTU_DEBUG_IN(); this->id = ""; allocate(vect.size(), 1); T * tmp = values; std::uninitialized_copy(&(vect[0]), &(vect[size_ - 1]), tmp); AKANTU_DEBUG_OUT(); } #endif /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> Array<T, is_scal>::~Array() { AKANTU_DEBUG_IN(); AKANTU_DEBUG(dblAccessory, "Freeing " << printMemorySize<T>(allocated_size * nb_component) << " (" << id << ")"); if (values) { if (!is_scal) for (UInt i = 0; i < size_ * nb_component; ++i) { T * obj = values + i; obj->~T(); } free(values); } size_ = allocated_size = 0; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * perform the allocation for the constructors * @param size is the size of the array * @param nb_component is the number of component of the array */ template <class T, bool is_scal> void Array<T, is_scal>::allocate(UInt size, UInt nb_component) { AKANTU_DEBUG_IN(); if (size == 0) { values = nullptr; } else { values = static_cast<T *>(malloc(nb_component * size * sizeof(T))); AKANTU_DEBUG_ASSERT(values != nullptr, "Cannot allocate " << printMemorySize<T>(size * nb_component) << " (" << id << ")"); } if (values == NULL) { this->size_ = this->allocated_size = 0; } else { AKANTU_DEBUG(dblAccessory, "Allocated " << printMemorySize<T>(size * nb_component) << " (" << id << ")"); this->size_ = this->allocated_size = size; } this->size_of_type = sizeof(T); this->nb_component = nb_component; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> void Array<T, is_scal>::reserve(UInt new_size) { UInt tmp_size = this->size_; resizeUnitialized(new_size, false); this->size_ = tmp_size; } /* -------------------------------------------------------------------------- */ /** * change the size of the array and allocate or free memory if needed. If the * size increases, the new tuples are filled with zeros * @param new_size new number of tuples contained in the array */ template <class T, bool is_scal> void Array<T, is_scal>::resize(UInt new_size) { resizeUnitialized(new_size, !is_scal); } /* -------------------------------------------------------------------------- */ /** * change the size of the array and allocate or free memory if needed. If the * size increases, the new tuples are filled with zeros * @param new_size new number of tuples contained in the array */ template <class T, bool is_scal> void Array<T, is_scal>::resize(UInt new_size, const T & val) { this->resizeUnitialized(new_size, true, val); } /* -------------------------------------------------------------------------- */ /** * change the size of the array and allocate or free memory if needed. * @param new_size new number of tuples contained in the array */ template <class T, bool is_scal> void Array<T, is_scal>::resizeUnitialized(UInt new_size, bool fill, const T & val) { // AKANTU_DEBUG_IN(); // free some memory if (new_size <= allocated_size) { if (!is_scal) { T * old_values = values; if (new_size < size_) { for (UInt i = new_size * nb_component; i < size_ * nb_component; ++i) { T * obj = old_values + i; obj->~T(); } } } if (allocated_size - new_size > AKANTU_MIN_ALLOCATION) { AKANTU_DEBUG(dblAccessory, "Freeing " << printMemorySize<T>((allocated_size - size_) * nb_component) << " (" << id << ")"); // Normally there are no allocation problem when reducing an array if (new_size == 0) { free(values); values = NULL; } else { auto * tmp_ptr = static_cast<T *>( realloc(values, new_size * nb_component * sizeof(T))); if (tmp_ptr == NULL) { AKANTU_EXCEPTION("Cannot free data (" << id << ")" << " [current allocated size : " << allocated_size << " | " << "requested size : " << new_size << "]"); } values = tmp_ptr; } allocated_size = new_size; } } else { // allocate more memory UInt size_to_alloc = (new_size - allocated_size < AKANTU_MIN_ALLOCATION) ? allocated_size + AKANTU_MIN_ALLOCATION : new_size; auto * tmp_ptr = static_cast<T *>( realloc(values, size_to_alloc * nb_component * sizeof(T))); AKANTU_DEBUG_ASSERT( tmp_ptr != NULL, "Cannot allocate " << printMemorySize<T>(size_to_alloc * nb_component)); if (tmp_ptr == NULL) { AKANTU_DEBUG_ERROR("Cannot allocate more data (" << id << ")" << " [current allocated size : " << allocated_size << " | " << "requested size : " << new_size << "]"); } AKANTU_DEBUG(dblAccessory, "Allocating " << printMemorySize<T>( (size_to_alloc - allocated_size) * nb_component)); allocated_size = size_to_alloc; values = tmp_ptr; } if (fill && this->size_ < new_size) { std::uninitialized_fill(values + size_ * nb_component, values + new_size * nb_component, val); } size_ = new_size; // AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * change the number of components by interlacing data * @param multiplicator number of interlaced components add * @param block_size blocks of data in the array * Examaple for block_size = 2, multiplicator = 2 * array = oo oo oo -> new array = oo nn nn oo nn nn oo nn nn */ template <class T, bool is_scal> void Array<T, is_scal>::extendComponentsInterlaced(UInt multiplicator, UInt block_size) { AKANTU_DEBUG_IN(); if (multiplicator == 1) return; AKANTU_DEBUG_ASSERT(multiplicator > 1, "invalid multiplicator"); AKANTU_DEBUG_ASSERT(nb_component % block_size == 0, "stride must divide actual number of components"); values = static_cast<T *>( realloc(values, nb_component * multiplicator * size_ * sizeof(T))); UInt new_component = nb_component / block_size * multiplicator; for (UInt i = 0, k = size_ - 1; i < size_; ++i, --k) { for (UInt j = 0; j < new_component; ++j) { UInt m = new_component - j - 1; UInt n = m / multiplicator; for (UInt l = 0, p = block_size - 1; l < block_size; ++l, --p) { values[k * nb_component * multiplicator + m * block_size + p] = values[k * nb_component + n * block_size + p]; } } } nb_component = nb_component * multiplicator; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * search elem in the array, return the position of the first occurrence or * -1 if not found * @param elem the element to look for * @return index of the first occurrence of elem or -1 if elem is not present */ template <class T, bool is_scal> UInt Array<T, is_scal>::find(const T & elem) const { AKANTU_DEBUG_IN(); auto begin = this->begin(); auto end = this->end(); auto it = std::find(begin, end, elem); AKANTU_DEBUG_OUT(); return (it != end) ? it - begin : UInt(-1); } /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> UInt Array<T, is_scal>::find(T elem[]) const { AKANTU_DEBUG_IN(); T * it = values; UInt i = 0; for (; i < size_; ++i) { if (*it == elem[0]) { T * cit = it; UInt c = 0; for (; (c < nb_component) && (*cit == elem[c]); ++c, ++cit) ; if (c == nb_component) { AKANTU_DEBUG_OUT(); return i; } } it += nb_component; } return UInt(-1); } /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> template <template <typename> class C> inline UInt Array<T, is_scal>::find(const C<T> & elem) { AKANTU_DEBUG_ASSERT(elem.size() == nb_component, "Cannot find an element with a wrong size (" << elem.size() << ") != " << nb_component); return this->find(elem.storage()); } /* -------------------------------------------------------------------------- */ /** * copy the content of another array. This overwrites the current content. * @param other Array to copy into this array. It has to have the same * nb_component as this. If compiled in debug mode, an incorrect other will * result in an exception being thrown. Optimised code may result in * unpredicted behaviour. */ template <class T, bool is_scal> void Array<T, is_scal>::copy(const Array<T, is_scal> & vect, bool no_sanity_check) { AKANTU_DEBUG_IN(); if (!no_sanity_check) if (vect.nb_component != nb_component) AKANTU_DEBUG_ERROR( "The two arrays do not have the same number of components"); resize((vect.size_ * vect.nb_component) / nb_component); T * tmp = values; std::uninitialized_copy(vect.storage(), vect.storage() + size_ * nb_component, tmp); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <bool is_scal> class ArrayPrintHelper { public: template <typename T> static void print_content(const Array<T> & vect, std::ostream & stream, int indent) { if (AKANTU_DEBUG_TEST(dblDump) || AKANTU_DEBUG_LEVEL_IS_TEST()) { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << " + values : {"; for (UInt i = 0; i < vect.size(); ++i) { stream << "{"; for (UInt j = 0; j < vect.getNbComponent(); ++j) { stream << vect(i, j); if (j != vect.getNbComponent() - 1) stream << ", "; } stream << "}"; if (i != vect.size() - 1) stream << ", "; } stream << "}" << std::endl; } } }; template <> class ArrayPrintHelper<false> { public: template <typename T> static void print_content(__attribute__((unused)) const Array<T> & vect, __attribute__((unused)) std::ostream & stream, __attribute__((unused)) int indent) {} }; /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> void Array<T, is_scal>::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; std::streamsize prec = stream.precision(); std::ios_base::fmtflags ff = stream.flags(); stream.setf(std::ios_base::showbase); stream.precision(2); stream << space << "Array<" << debug::demangle(typeid(T).name()) << "> [" << std::endl; stream << space << " + id : " << this->id << std::endl; stream << space << " + size : " << this->size_ << std::endl; stream << space << " + nb_component : " << this->nb_component << std::endl; stream << space << " + allocated size : " << this->allocated_size << std::endl; stream << space << " + memory size : " << printMemorySize<T>(allocated_size * nb_component) << std::endl; if (!AKANTU_DEBUG_LEVEL_IS_TEST()) stream << space << " + address : " << std::hex << this->values << std::dec << std::endl; stream.precision(prec); stream.flags(ff); ArrayPrintHelper<is_scal>::print_content(*this, stream, indent); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ /* Inline Functions ArrayBase */ /* -------------------------------------------------------------------------- */ inline UInt ArrayBase::getMemorySize() const { return allocated_size * nb_component * size_of_type; } inline void ArrayBase::empty() { size_ = 0; } /* -------------------------------------------------------------------------- */ /* Iterators */ /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> template <class R, class IR, bool is_r_scal> class Array<T, is_scal>::iterator_internal { public: using value_type = R; using pointer = R *; using reference = R &; using proxy = typename R::proxy; using const_proxy = const typename R::proxy; using const_reference = const R &; using internal_value_type = IR; using internal_pointer = IR *; using difference_type = std::ptrdiff_t; using iterator_category = std::random_access_iterator_tag; public: iterator_internal() : initial(NULL), ret(NULL), ret_ptr(NULL){}; iterator_internal(pointer_type data, UInt _offset) : _offset(_offset), initial(data), ret(NULL), ret_ptr(data) { AKANTU_DEBUG_ERROR( "The constructor should never be called it is just an ugly trick..."); } iterator_internal(pointer wrapped) : _offset(wrapped->size()), initial(wrapped->storage()), ret(const_cast<internal_pointer>(wrapped)), ret_ptr(wrapped->storage()) {} iterator_internal(const iterator_internal & it) { if (this != &it) { this->_offset = it._offset; this->initial = it.initial; this->ret_ptr = it.ret_ptr; this->ret = new internal_value_type(*it.ret, false); } } virtual ~iterator_internal() { delete ret; }; inline iterator_internal & operator=(const iterator_internal & it) { if (this != &it) { this->_offset = it._offset; this->initial = it.initial; this->ret_ptr = it.ret_ptr; if (this->ret) this->ret->shallowCopy(*it.ret); else this->ret = new internal_value_type(*it.ret, false); } return *this; } UInt getCurrentIndex() { return (this->ret_ptr - this->initial) / this->_offset; }; inline reference operator*() { ret->values = ret_ptr; return *ret; }; inline const_reference operator*() const { ret->values = ret_ptr; return *ret; }; inline pointer operator->() { ret->values = ret_ptr; return ret; }; inline iterator_internal & operator++() { ret_ptr += _offset; return *this; }; inline iterator_internal & operator--() { ret_ptr -= _offset; return *this; }; inline iterator_internal & operator+=(const UInt n) { ret_ptr += _offset * n; return *this; } inline iterator_internal & operator-=(const UInt n) { ret_ptr -= _offset * n; return *this; } inline proxy operator[](const UInt n) { ret->values = ret_ptr + n * _offset; return proxy(*ret); } inline const_proxy operator[](const UInt n) const { ret->values = ret_ptr + n * _offset; return const_proxy(*ret); } inline bool operator==(const iterator_internal & other) const { return this->ret_ptr == other.ret_ptr; } inline bool operator!=(const iterator_internal & other) const { return this->ret_ptr != other.ret_ptr; } inline bool operator<(const iterator_internal & other) const { return this->ret_ptr < other.ret_ptr; } inline bool operator<=(const iterator_internal & other) const { return this->ret_ptr <= other.ret_ptr; } inline bool operator>(const iterator_internal & other) const { return this->ret_ptr > other.ret_ptr; } inline bool operator>=(const iterator_internal & other) const { return this->ret_ptr >= other.ret_ptr; } inline iterator_internal operator+(difference_type n) { iterator_internal tmp(*this); tmp += n; return tmp; } inline iterator_internal operator-(difference_type n) { iterator_internal tmp(*this); tmp -= n; return tmp; } inline difference_type operator-(const iterator_internal & b) { return (this->ret_ptr - b.ret_ptr) / _offset; } inline pointer_type data() const { return ret_ptr; } inline difference_type offset() const { return _offset; } protected: UInt _offset{0}; pointer_type initial; internal_pointer ret; pointer_type ret_ptr; }; /* -------------------------------------------------------------------------- */ /** * Specialization for scalar types */ template <class T, bool is_scal> template <class R, class IR> class Array<T, is_scal>::iterator_internal<R, IR, true> { public: using value_type = R; using pointer = R *; using reference = R &; using const_reference = const R &; using internal_value_type = IR; using internal_pointer = IR *; using difference_type = std::ptrdiff_t; using iterator_category = std::random_access_iterator_tag; public: iterator_internal(pointer data = nullptr, UInt _offset = 1) : _offset(_offset), ret(data), initial(data){}; iterator_internal(const iterator_internal & it) = default; iterator_internal(iterator_internal && it) = default; virtual ~iterator_internal() = default; inline iterator_internal & operator=(const iterator_internal & it) = default; UInt getCurrentIndex() { return (this->ret - this->initial) / this->_offset; }; inline reference operator*() { return *ret; }; inline const_reference operator*() const { return *ret; }; inline pointer operator->() { return ret; }; inline iterator_internal & operator++() { ++ret; return *this; }; inline iterator_internal & operator--() { --ret; return *this; }; inline iterator_internal & operator+=(const UInt n) { ret += n; return *this; } inline iterator_internal & operator-=(const UInt n) { ret -= n; return *this; } inline reference operator[](const UInt n) { return ret[n]; } inline bool operator==(const iterator_internal & other) const { return ret == other.ret; } inline bool operator!=(const iterator_internal & other) const { return ret != other.ret; } inline bool operator<(const iterator_internal & other) const { return ret < other.ret; } inline bool operator<=(const iterator_internal & other) const { return ret <= other.ret; } inline bool operator>(const iterator_internal & other) const { return ret > other.ret; } inline bool operator>=(const iterator_internal & other) const { return ret >= other.ret; } inline iterator_internal operator-(difference_type n) { return iterator_internal(ret - n); } inline iterator_internal operator+(difference_type n) { return iterator_internal(ret + n); } inline difference_type operator-(const iterator_internal & b) { return ret - b.ret; } inline pointer data() const { return ret; } inline difference_type offset() const { return _offset; } protected: difference_type _offset; pointer ret; pointer initial; }; /* -------------------------------------------------------------------------- */ /* Begin/End functions implementation */ /* -------------------------------------------------------------------------- */ namespace { template <std::size_t N> struct extract_last { template <typename F, typename... T, typename... Arg> static decltype(auto) extract(F && func, std::tuple<T...> && t, Arg... args) { return extract_last<N - 1>::extract( std::forward<F>(func), std::forward<decltype(t)>(t), std::get<sizeof...(T) - N>(std::forward<decltype(t)>(t)), args...); } }; template <> struct extract_last<1> { template <typename F, typename... T, typename... Arg> static decltype(auto) extract(F && func, std::tuple<T...> && /*unused*/, Arg... args) { return std::forward<F>(func)(args...); } }; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnarrowing" template <std::size_t N> struct InstantiationHelper { template <typename... Ns> static constexpr std::size_t product(Ns... ns) { std::size_t p = 1; for (auto n : std::array<std::size_t, sizeof...(Ns)>{ns...}) p *= n; return p; } template <typename... Ns> static std::string to_string(Ns... ns) { std::stringstream sstr; bool first = true; sstr << "("; for (auto n : std::array<std::size_t, sizeof...(Ns)>{ns...}) { if (!first) { sstr << ", "; } sstr << n; first = false; } sstr << ")"; return sstr.str(); } #pragma GCC diagnostic pop template <typename type, typename T, typename... Ns> static auto instantiate(T && data, Ns... ns) { return new type(data, ns...); } }; template <> struct InstantiationHelper<0> { template <typename type, typename T> static auto instantiate(T && data) { return data; } static constexpr std::size_t product() { return 1; } static std::string to_string() { return ""; } }; template <typename Arr, typename T, typename... Ns> decltype(auto) get_iterator(Arr && array, T * data, Ns... ns) { using type = IteratorHelper_t<sizeof...(Ns) -1, T>; using array_type = std::decay_t<Arr>; using iterator = std::conditional_t<std::is_const<Arr>::value, typename array_type::template const_iterator<type>, typename array_type::template iterator<type>>; AKANTU_DEBUG_ASSERT( array.getNbComponent() * array.size() == InstantiationHelper<sizeof...(Ns)>::product(ns...), "The iterator is not compatible with the type " << debug::demangle(typeid(type).name()) << InstantiationHelper<sizeof...(Ns)>::to_string(ns...)); auto && wrapped = extract_last<sizeof...(Ns)>::extract( [&](auto... n) { return InstantiationHelper<sizeof...(n)>::template instantiate<type>( data, n...); }, std::make_tuple(ns...)); return iterator{wrapped}; } } // namespace /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> template <typename... Ns> inline decltype(auto) Array<T, is_scal>::begin(Ns... ns) { return get_iterator(*this, values, ns..., size_); } template <class T, bool is_scal> template <typename... Ns> inline decltype(auto) Array<T, is_scal>::end(Ns... ns) { return get_iterator(*this, values + nb_component * size_, ns..., size_); } template <class T, bool is_scal> template <typename... Ns> inline decltype(auto) Array<T, is_scal>::begin(Ns... ns) const { return get_iterator(*this, values, ns..., size_); } template <class T, bool is_scal> template <typename... Ns> inline decltype(auto) Array<T, is_scal>::end(Ns... ns) const { return get_iterator(*this, values + nb_component * size_, ns..., size_); } template <class T, bool is_scal> template <typename... Ns> inline decltype(auto) Array<T, is_scal>::begin_reinterpret(Ns... ns) { return get_iterator(*this, values, ns...); } template <class T, bool is_scal> template <typename... Ns> inline decltype(auto) Array<T, is_scal>::end_reinterpret(Ns... ns) { return get_iterator( *this, values + InstantiationHelper<sizeof...(Ns)>::product(ns...), ns...); } template <class T, bool is_scal> template <typename... Ns> inline decltype(auto) Array<T, is_scal>::begin_reinterpret(Ns... ns) const { return get_iterator(*this, values, ns...); } template <class T, bool is_scal> template <typename... Ns> inline decltype(auto) Array<T, is_scal>::end_reinterpret(Ns... ns) const { return get_iterator( *this, values + InstantiationHelper<sizeof...(Ns)>::product(ns...), ns...); } /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> template <typename R> class Array<T, is_scal>::const_iterator : public iterator_internal<const R, R> { public: typedef iterator_internal<const R, R> parent; using value_type = typename parent::value_type; using pointer = typename parent::pointer; using reference = typename parent::reference; using difference_type = typename parent::difference_type; using iterator_category = typename parent::iterator_category; public: const_iterator() : parent(){}; const_iterator(pointer_type data, UInt offset) : parent(data, offset) {} const_iterator(pointer warped) : parent(warped) {} const_iterator(const parent & it) : parent(it) {} // const_iterator(const const_iterator<R> & it) : parent(it) {} inline const_iterator operator+(difference_type n) { return parent::operator+(n); } inline const_iterator operator-(difference_type n) { return parent::operator-(n); } inline difference_type operator-(const const_iterator & b) { return parent::operator-(b); } inline const_iterator & operator++() { parent::operator++(); return *this; }; inline const_iterator & operator--() { parent::operator--(); return *this; }; inline const_iterator & operator+=(const UInt n) { parent::operator+=(n); return *this; } }; // #endif // #if defined(AKANTU_CORE_CXX11) // template<class R> using iterator = iterator_internal<R>; // #else -template <class T, class R, bool issame = is_same<T, R>::value> +template <class T, class R, bool issame = std::is_same<T, R>::value> struct ConstConverterIteratorHelper { using const_iterator = typename Array<T>::template const_iterator<R>; using iterator = typename Array<T>::template iterator<R>; static inline const_iterator convert(const iterator & it) { return const_iterator(new R(*it, false)); } }; template <class T, class R> struct ConstConverterIteratorHelper<T, R, true> { using const_iterator = typename Array<T>::template const_iterator<R>; using iterator = typename Array<T>::template iterator<R>; static inline const_iterator convert(const iterator & it) { return const_iterator(it.data(), it.offset()); } }; template <class T, bool is_scal> template <typename R> class Array<T, is_scal>::iterator : public iterator_internal<R> { public: using parent = iterator_internal<R>; using value_type = typename parent::value_type; using pointer = typename parent::pointer; using reference = typename parent::reference; using difference_type = typename parent::difference_type; using iterator_category = typename parent::iterator_category; public: iterator() : parent(){}; iterator(pointer_type data, UInt offset) : parent(data, offset){}; iterator(pointer warped) : parent(warped) {} iterator(const parent & it) : parent(it) {} // iterator(const iterator<R> & it) : parent(it) {} operator const_iterator<R>() { return ConstConverterIteratorHelper<T, R>::convert(*this); } inline iterator operator+(difference_type n) { return parent::operator+(n); ; } inline iterator operator-(difference_type n) { return parent::operator-(n); ; } inline difference_type operator-(const iterator & b) { return parent::operator-(b); } inline iterator & operator++() { parent::operator++(); return *this; }; inline iterator & operator--() { parent::operator--(); return *this; }; inline iterator & operator+=(const UInt n) { parent::operator+=(n); return *this; } }; /* -------------------------------------------------------------------------- */ template <class T, bool is_scal> template <typename R> inline typename Array<T, is_scal>::template iterator<R> Array<T, is_scal>::erase(const iterator<R> & it) { T * curr = it.data(); UInt pos = (curr - values) / nb_component; erase(pos); iterator<R> rit = it; return --rit; } } // namespace akantu #endif /* __AKANTU_AKA_ARRAY_TMPL_HH__ */ diff --git a/src/common/aka_common.hh b/src/common/aka_common.hh index d53741946..437f748d0 100644 --- a/src/common/aka_common.hh +++ b/src/common/aka_common.hh @@ -1,458 +1,436 @@ /** * @file aka_common.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Jun 14 2010 * @date last modification: Thu Jan 21 2016 * * @brief common type descriptions for akantu * * @section LICENSE * * Copyright (©) 2010-2012, 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/>. * * @section DESCRIPTION * * All common things to be included in the projects files * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COMMON_HH__ #define __AKANTU_COMMON_HH__ /* -------------------------------------------------------------------------- */ #include <list> #include <limits> #include <type_traits> +/* -------------------------------------------------------------------------- */ + +#include "aka_compatibilty_with_cpp_standard.hh" -#if __cplusplus < 201402L -namespace std { -template< bool B, class T = void > -using enable_if_t = typename enable_if<B,T>::type; -} -#endif /* -------------------------------------------------------------------------- */ #define __BEGIN_AKANTU_DUMPER__ namespace dumper { #define __END_AKANTU_DUMPER__ } /* -------------------------------------------------------------------------- */ #if defined(WIN32) #define __attribute__(x) #endif /* -------------------------------------------------------------------------- */ #include "aka_config.hh" #include "aka_error.hh" #include "aka_safe_enum.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ /* Common types */ /* -------------------------------------------------------------------------- */ using ID = std::string; #ifdef AKANTU_NDEBUG static const Real REAL_INIT_VALUE = Real(0.); #else static const Real REAL_INIT_VALUE = std::numeric_limits<Real>::quiet_NaN(); #endif /* -------------------------------------------------------------------------- */ /* Memory types */ /* -------------------------------------------------------------------------- */ using MemoryID = UInt; using Surface = std::string; typedef std::pair<Surface, Surface> SurfacePair; using SurfacePairList = std::list<SurfacePair>; /* -------------------------------------------------------------------------- */ extern const UInt _all_dimensions; /* -------------------------------------------------------------------------- */ /* Mesh/FEM/Model types */ /* -------------------------------------------------------------------------- */ } // akantu #include "aka_element_classes_info.hh" namespace akantu { /// small help to use names for directions enum SpacialDirection { _x = 0, _y = 1, _z = 2 }; /// enum MeshIOType type of mesh reader/writer enum MeshIOType { _miot_auto, ///< Auto guess of the reader to use based on the extension _miot_gmsh, ///< Gmsh files _miot_gmsh_struct, ///< Gsmh reader with reintpretation of elements has /// structures elements _miot_diana, ///< TNO Diana mesh format _miot_abaqus ///< Abaqus mesh format }; /// enum MeshEventHandlerPriority defines relative order of execution of events enum EventHandlerPriority { _ehp_highest = 0, _ehp_mesh = 5, _ehp_fe_engine = 9, _ehp_synchronizer = 10, _ehp_dof_manager = 20, _ehp_model = 94, _ehp_non_local_manager = 100, _ehp_lowest = 100 }; /// enum AnalysisMethod type of solving method used to solve the equation of /// motion enum AnalysisMethod { _static = 0, _implicit_dynamic = 1, _explicit_lumped_mass = 2, _explicit_lumped_capacity = 2, _explicit_consistent_mass = 3 }; /// enum DOFSupportType defines which kind of dof that can exists enum DOFSupportType { _dst_nodal, _dst_generic }; /// Type of non linear resolution available in akantu enum NonLinearSolverType { _nls_linear, ///< No non linear convergence loop _nls_newton_raphson, ///< Regular Newton-Raphson _nls_newton_raphson_modified, ///< Newton-Raphson with initial tangent _nls_lumped, ///< Case of lumped mass or equivalent matrix _nls_auto ///< This will take a default value that make sense in case of /// model::getNewSolver }; /// Define the node/dof type enum NodeType : Int { _nt_pure_gost = -3, _nt_master = -2, _nt_normal = -1 }; /// Type of time stepping solver enum TimeStepSolverType { _tsst_static, ///< Static solution _tsst_dynamic, ///< Dynamic solver _tsst_dynamic_lumped, ///< Dynamic solver with lumped mass _tsst_not_defined, ///< For not defined cases }; /// Type of integration scheme enum IntegrationSchemeType { _ist_pseudo_time, ///< Pseudo Time _ist_forward_euler, ///< GeneralizedTrapezoidal(0) _ist_trapezoidal_rule_1, ///< GeneralizedTrapezoidal(1/2) _ist_backward_euler, ///< GeneralizedTrapezoidal(1) _ist_central_difference, ///< NewmarkBeta(0, 1/2) _ist_fox_goodwin, ///< NewmarkBeta(1/6, 1/2) _ist_trapezoidal_rule_2, ///< NewmarkBeta(1/2, 1/2) _ist_linear_acceleration, ///< NewmarkBeta(1/3, 1/2) _ist_newmark_beta, ///< generic NewmarkBeta with user defined /// alpha and beta _ist_generalized_trapezoidal ///< generic GeneralizedTrapezoidal with user /// defined alpha }; /// enum SolveConvergenceCriteria different convergence criteria enum SolveConvergenceCriteria { _scc_residual, ///< Use residual to test the convergence _scc_solution, ///< Use solution to test the convergence _scc_residual_mass_wgh ///< Use residual weighted by inv. nodal mass to testb }; /// enum CohesiveMethod type of insertion of cohesive elements enum CohesiveMethod { _intrinsic, _extrinsic }; /// @enum SparseMatrixType type of sparse matrix used enum MatrixType { _unsymmetric, _symmetric, _mt_not_defined }; /* -------------------------------------------------------------------------- */ /* Ghosts handling */ /* -------------------------------------------------------------------------- */ using SynchronizerID = ID; /// @enum CommunicatorType type of communication method to use enum CommunicatorType { _communicator_mpi, _communicator_dummy }; /// @enum SynchronizationTag type of synchronizations enum SynchronizationTag { //--- Generic tags --- _gst_whatever, _gst_update, _gst_size, //--- SolidMechanicsModel tags --- _gst_smm_mass, ///< synchronization of the SolidMechanicsModel.mass _gst_smm_for_gradu, ///< synchronization of the /// SolidMechanicsModel.displacement _gst_smm_boundary, ///< synchronization of the boundary, forces, velocities /// and displacement _gst_smm_uv, ///< synchronization of the nodal velocities and displacement _gst_smm_res, ///< synchronization of the nodal residual _gst_smm_init_mat, ///< synchronization of the data to initialize materials _gst_smm_stress, ///< synchronization of the stresses to compute the internal /// forces _gst_smmc_facets, ///< synchronization of facet data to setup facet synch _gst_smmc_facets_conn, ///< synchronization of facet global connectivity _gst_smmc_facets_stress, ///< synchronization of facets' stress to setup facet /// synch _gst_smmc_damage, ///< synchronization of damage // --- GlobalIdsUpdater tags --- _gst_giu_global_conn, ///< synchronization of global connectivities // --- CohesiveElementInserter tags --- _gst_ce_groups, ///< synchronization of cohesive element insertion depending /// on facet groups // --- GroupManager tags --- _gst_gm_clusters, ///< synchronization of clusters // --- HeatTransfer tags --- _gst_htm_capacity, ///< synchronization of the nodal heat capacity _gst_htm_temperature, ///< synchronization of the nodal temperature _gst_htm_gradient_temperature, ///< synchronization of the element gradient /// temperature // --- LevelSet tags --- _gst_htm_phi, ///< synchronization of the nodal level set value phi _gst_htm_gradient_phi, ///< synchronization of the element gradient phi //--- Material non local --- _gst_mnl_for_average, ///< synchronization of data to average in non local /// material _gst_mnl_weight, ///< synchronization of data for the weight computations // --- NeighborhoodSynchronization tags --- _gst_nh_criterion, // --- General tags --- _gst_test, ///< Test tag _gst_user_1, ///< tag for user simulations _gst_user_2, ///< tag for user simulations _gst_material_id, ///< synchronization of the material ids _gst_for_dump, ///< everything that needs to be synch before dump // --- Contact & Friction --- _gst_cf_nodal, ///< synchronization of disp, velo, and current position _gst_cf_incr, ///< synchronization of increment // --- Solver tags --- _gst_solver_solution ///< synchronization of the solution obained with the /// PETSc solver }; /// standard output stream operator for SynchronizationTag inline std::ostream & operator<<(std::ostream & stream, SynchronizationTag type); /// @enum GhostType type of ghost enum GhostType { _not_ghost, _ghost, _casper // not used but a real cute ghost }; /* -------------------------------------------------------------------------- */ struct GhostType_def { using type = GhostType; static const type _begin_ = _not_ghost; static const type _end_ = _casper; }; using ghost_type_t = safe_enum<GhostType_def>; extern ghost_type_t ghost_types; /// standard output stream operator for GhostType inline std::ostream & operator<<(std::ostream & stream, GhostType type); /// @enum SynchronizerOperation reduce operation that the synchronizer can /// perform enum SynchronizerOperation { _so_sum, _so_min, _so_max, _so_prod, _so_land, _so_band, _so_lor, _so_bor, _so_lxor, _so_bxor, _so_min_loc, _so_max_loc, _so_null }; /* -------------------------------------------------------------------------- */ /* Global defines */ /* -------------------------------------------------------------------------- */ #define AKANTU_MIN_ALLOCATION 2000 #define AKANTU_INDENT " " #define AKANTU_INCLUDE_INLINE_IMPL /* -------------------------------------------------------------------------- */ -template <class T> struct is_scalar { - enum { value = false }; -}; - -#define AKANTU_SPECIFY_IS_SCALAR(type) \ - template <> struct is_scalar<type> { \ - enum { value = true }; \ - } - -AKANTU_SPECIFY_IS_SCALAR(Real); -AKANTU_SPECIFY_IS_SCALAR(UInt); -AKANTU_SPECIFY_IS_SCALAR(Int); -AKANTU_SPECIFY_IS_SCALAR(bool); - -template <typename T1, typename T2> struct is_same { - enum { value = false }; // is_same represents a bool. -}; - -template <typename T> struct is_same<T, T> { - enum { value = true }; -}; +template<typename T> +using is_scalar = std::is_arithmetic<T>; /* -------------------------------------------------------------------------- */ #define AKANTU_SET_MACRO(name, variable, type) \ inline void set##name(type variable) { this->variable = variable; } #define AKANTU_GET_MACRO(name, variable, type) \ inline type get##name() const { return variable; } #define AKANTU_GET_MACRO_NOT_CONST(name, variable, type) \ inline type get##name() { return variable; } #define AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, support, con) \ inline con Array<type> & get##name( \ const support & el_type, const GhostType & ghost_type = _not_ghost) \ con { \ return variable(el_type, ghost_type); \ } #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType, ) #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType, const) #define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType, ) #define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE_CONST(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType, const) /* -------------------------------------------------------------------------- */ /// initialize the static part of akantu void initialize(int & argc, char **& argv); /// initialize the static part of akantu and read the global input_file void initialize(const std::string & input_file, int & argc, char **& argv); /* -------------------------------------------------------------------------- */ /// finilize correctly akantu and clean the memory void finalize(); /* -------------------------------------------------------------------------- */ /// Read an new input file void readInputFile(const std::string & input_file); /* -------------------------------------------------------------------------- */ /* * For intel compiler annoying remark */ // #if defined(__INTEL_COMPILER) // /// remark #981: operands are evaluated in unspecified order // #pragma warning(disable : 981) // /// remark #383: value copied to temporary, reference to temporary used // #pragma warning(disable : 383) // #endif // defined(__INTEL_COMPILER) /* -------------------------------------------------------------------------- */ /* string manipulation */ /* -------------------------------------------------------------------------- */ inline std::string to_lower(const std::string & str); /* -------------------------------------------------------------------------- */ inline std::string trim(const std::string & to_trim); /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /// give a string representation of the a human readable size in bit template <typename T> std::string printMemorySize(UInt size); /* -------------------------------------------------------------------------- */ } // akantu #include "aka_fwd.hh" namespace akantu { /// get access to the internal argument parser cppargparse::ArgumentParser & getStaticArgumentParser(); /// get access to the internal input file parser Parser & getStaticParser(); /// get access to the user part of the internal input file parser const ParserSection & getUserParser(); } // akantu #include "aka_common_inline_impl.cc" /* -------------------------------------------------------------------------- */ #if AKANTU_INTEGER_SIZE == 4 #define AKANTU_HASH_COMBINE_MAGIC_NUMBER 0x9e3779b9 #elif AKANTU_INTEGER_SIZE == 8 #define AKANTU_HASH_COMBINE_MAGIC_NUMBER 0x9e3779b97f4a7c13LL #endif namespace std { /** * Hashing function for pairs based on hash_combine from boost The magic number * is coming from the golden number @f[\phi = \frac{1 + \sqrt5}{2}@f] * @f[\frac{2^32}{\phi} = 0x9e3779b9@f] * http://stackoverflow.com/questions/4948780/magic-number-in-boosthash-combine * http://burtleburtle.net/bob/hash/doobs.html */ template <typename a, typename b> struct hash<std::pair<a, b> > { public: hash() : ah(), bh() {} size_t operator()(const std::pair<a, b> & p) const { size_t seed = ah(p.first); return bh(p.second) + AKANTU_HASH_COMBINE_MAGIC_NUMBER + (seed << 6) + (seed >> 2); } private: const hash<a> ah; const hash<b> bh; }; } //std #endif /* __AKANTU_COMMON_HH__ */ diff --git a/src/common/aka_compatibilty_with_cpp_standard.hh b/src/common/aka_compatibilty_with_cpp_standard.hh new file mode 100644 index 000000000..c3b223671 --- /dev/null +++ b/src/common/aka_compatibilty_with_cpp_standard.hh @@ -0,0 +1,63 @@ +/** + * @file aka_compatibilty_with_cpp_standard.hh + * + * @author Nicolas Richart + * + * @date creation Wed Oct 25 2017 + * + * @brief The content of this file is taken from the possible implementations on + * http://en.cppreference.com + * + * @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 <type_traits> +/* -------------------------------------------------------------------------- */ + +#ifndef __AKANTU_AKA_COMPATIBILTY_WITH_CPP_STANDARD_HH__ +#define __AKANTU_AKA_COMPATIBILTY_WITH_CPP_STANDARD_HH__ + +namespace std { + +// Part taken from C++14 +#if __cplusplus < 201402L +template <bool B, class T = void> +using enable_if_t = typename enable_if<B, T>::type; +#endif + +// Part taken from C++17 +#if __cplusplus < 201703L +// bool_constant +template <bool B> using bool_constant = integral_constant<bool, B>; +namespace { + template <bool B> constexpr bool bool_constant_v = bool_constant<B>::value; +} + +// conjunction +template <class...> struct conjunction : std::true_type {}; +template <class B1> struct conjunction<B1> : B1 {}; +template <class B1, class... Bn> +struct conjunction<B1, Bn...> + : std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {}; + +#endif +} + +#endif /* __AKANTU_AKA_COMPATIBILTY_WITH_CPP_STANDARD_HH__ */ diff --git a/src/common/aka_fwd.hh b/src/common/aka_fwd.hh index 7f92fdf2f..9055e696b 100644 --- a/src/common/aka_fwd.hh +++ b/src/common/aka_fwd.hh @@ -1,73 +1,72 @@ /** * @file aka_fwd.hh * * @author Alejandro M. Aragón <alejandro.aragon@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Apr 13 2012 * @date last modification: Tue Aug 18 2015 * * @brief File containing forward declarations in akantu. * This file helps if circular #include would be needed because two classes * refer both to each other. This file usually does not need any modification. * * @section LICENSE * * Copyright (©) 2010-2012, 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/>. * */ - /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_FWD_HH__ #define __AKANTU_FWD_HH__ namespace cppargparse { class ArgumentParser; } namespace akantu { - // forward declaration - template <int dim, class model_type> struct ContactData; +// forward declaration +template <int dim, class model_type> struct ContactData; - template <typename T> class Matrix; - template <typename T> class Vector; - template <typename T> class Tensor3; +template <typename T> class Matrix; +template <typename T> class Vector; +template <typename T> class Tensor3; - template <typename T, bool is_scal = is_scalar<T>::value> class Array; - template <typename T, typename SupportType = ElementType> - class ElementTypeMapArray; +template <typename T, bool is_scal = is_scalar<T>::value> class Array; +template <typename T, typename SupportType = ElementType> +class ElementTypeMapArray; - template <class T> class SpatialGrid; +template <class T> class SpatialGrid; - // Model element - template <class ModelPolicy> class ModelElement; +// Model element +template <class ModelPolicy> class ModelElement; - extern const Array<UInt> empty_filter; +extern const Array<UInt> empty_filter; - class Parser; - class ParserSection; +class Parser; +class ParserSection; - extern Parser static_parser; +extern Parser static_parser; - extern cppargparse::ArgumentParser static_argparser; +extern cppargparse::ArgumentParser static_argparser; - class Mesh; - class SparseMatrix; -} +class Mesh; +class SparseMatrix; +} // namespace akantu #endif /* __AKANTU_FWD_HH__ */ diff --git a/src/common/aka_named_argument.hh b/src/common/aka_named_argument.hh index 2ff44e958..082311383 100644 --- a/src/common/aka_named_argument.hh +++ b/src/common/aka_named_argument.hh @@ -1,161 +1,161 @@ /** * @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 <tuple> #include <type_traits> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_NAMED_ARGUMENT_HH__ #define __AKANTU_AKA_NAMED_ARGUMENT_HH__ namespace akantu { namespace named_argument { /* -- Pack utils (proxy version) -------------------------------------------- */ /// Proxy containing [tag, value] template <typename tag, typename type> struct param_t { 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 T, typename head, typename... tail> struct type_at { 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 tag, typename type> struct is_named_argument<named_argument::param_t<tag, type>> : public std::true_type {}; template <typename tag, typename type> -struct is_named_argument<named_argument::param_t<tag, type & >> +struct is_named_argument<named_argument::param_t<tag, type &>> : public std::true_type {}; template <typename tag, typename type> struct is_named_argument<named_argument::param_t<tag, type &&>> : public std::true_type {}; template <typename tag, typename type> struct is_named_argument<named_argument::param_t<tag, const type &>> : public std::true_type {}; } // namespace akantu #endif /* __AKANTU_AKA_NAMED_ARGUMENT_HH__ */ diff --git a/src/common/aka_static_if.hh b/src/common/aka_static_if.hh index 274a05295..29a9bae34 100644 --- a/src/common/aka_static_if.hh +++ b/src/common/aka_static_if.hh @@ -1,105 +1,94 @@ // Copyright (c) 2016 Vittorio Romeo // License: AFL 3.0 | https://opensource.org/licenses/AFL-3.0 // http://vittorioromeo.info | vittorio.romeo@outlook.com #ifndef __AKANTU_AKA_STATIC_IF_HH__ #define __AKANTU_AKA_STATIC_IF_HH__ #include <utility> #define FWD(...) ::std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__) namespace akantu { -template <bool TX> using bool_ = std::integral_constant<bool, TX>; - -template <bool TX> constexpr bool_<TX> bool_v{}; - -template <int TX> using int_ = std::integral_constant<int, TX>; - -template <int TX> constexpr int_<TX> int_v{}; - -template <std::size_t TX> using sz_ = std::integral_constant<int, TX>; - -template <std::size_t TX> constexpr sz_<TX> sz_v{}; template <typename TPredicate> auto static_if(TPredicate) noexcept; namespace impl { template <bool TPredicateResult> struct static_if_impl; template <typename TFunctionToCall> struct static_if_result; template <typename TF> auto make_static_if_result(TF && f) noexcept; template <> struct static_if_impl<true> { template <typename TF> auto & else_(TF &&) noexcept { // Ignore `else_`, as the predicate is true. return *this; } template <typename TPredicate> auto & else_if(TPredicate) noexcept { // Ignore `else_if`, as the predicate is true. return *this; } template <typename TF> auto then(TF && f) noexcept { // We found a matching branch, just make a result and // ignore everything else. return make_static_if_result(FWD(f)); } }; template <> struct static_if_impl<false> { template <typename TF> auto & then(TF &&) noexcept { // Ignore `then`, as the predicate is false. return *this; } template <typename TF> auto else_(TF && f) noexcept { // (Assuming that `else_` is after all `else_if` calls.) // We found a matching branch, just make a result and // ignore everything else. return make_static_if_result(FWD(f)); } template <typename TPredicate> auto else_if(TPredicate) noexcept { return static_if(TPredicate{}); } template <typename... Ts> auto operator()(Ts &&...) noexcept { // If there are no `else` branches, we must ignore calls // to a failed `static_if` matching. } }; template <typename TFunctionToCall> struct static_if_result : TFunctionToCall { // Perfect-forward the function in the result instance. template <typename TFFwd> explicit static_if_result(TFFwd && f) noexcept : TFunctionToCall(FWD(f)) {} // Ignore everything, we found a result. template <typename TF> auto & then(TF &&) noexcept { return *this; } template <typename TPredicate> auto & else_if(TPredicate) noexcept { return *this; } template <typename TF> auto & else_(TF &&) noexcept { return *this; } }; template <typename TF> auto make_static_if_result(TF && f) noexcept { return static_if_result<TF>{FWD(f)}; } } // namespace impl template <typename TPredicate> auto static_if(TPredicate) noexcept { return impl::static_if_impl<TPredicate{}>{}; } #undef FWD } // namespace akantu #endif /* __AKANTU_AKA_STATIC_IF_HH__ */ diff --git a/src/mesh/element_group.hh b/src/mesh/element_group.hh index 69ff2de25..4c905dec4 100644 --- a/src/mesh/element_group.hh +++ b/src/mesh/element_group.hh @@ -1,188 +1,188 @@ /** * @file element_group.hh * * @author Dana Christen <dana.christen@gmail.com> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri May 03 2013 * @date last modification: Tue Aug 18 2015 * * @brief Stores information relevent to the notion of domain boundary and * surfaces. * * @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 "aka_common.hh" #include "aka_memory.hh" #include "dumpable.hh" #include "element_type_map.hh" #include "node_group.hh" /* -------------------------------------------------------------------------- */ #include <set> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_GROUP_HH__ #define __AKANTU_ELEMENT_GROUP_HH__ namespace akantu { class Mesh; class Element; } // namespace akantu namespace akantu { /* -------------------------------------------------------------------------- */ class ElementGroup : private Memory, public Dumpable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ElementGroup(const std::string & name, const Mesh & mesh, NodeGroup & node_group, UInt dimension = _all_dimensions, const std::string & id = "element_group", const MemoryID & memory_id = 0); /* ------------------------------------------------------------------------ */ /* Type definitions */ /* ------------------------------------------------------------------------ */ public: using ElementList = ElementTypeMapArray<UInt>; using NodeList = Array<UInt>; /* ------------------------------------------------------------------------ */ /* Element iterator */ /* ------------------------------------------------------------------------ */ using type_iterator = ElementList::type_iterator; inline type_iterator firstType(UInt dim = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & kind = _ek_regular) const; inline type_iterator lastType(UInt dim = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & kind = _ek_regular) const; - inline auto elementTypes(UInt dim = _all_dimensions, - const GhostType & ghost_type = _not_ghost, - const ElementKind & kind = _ek_regular) const { - return elements.elementTypes(dim, ghost_type, kind); + template <typename... pack> + inline decltype(auto) elementTypes(pack &&... _pack) const { + return elements.elementTypes(_pack...); } using const_element_iterator = Array<UInt>::const_iterator<UInt>; inline const_element_iterator begin(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; inline const_element_iterator end(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// empty the element group void empty(); /// append another group to this group /// BE CAREFUL: it doesn't conserve the element order void append(const ElementGroup & other_group); /// add an element to the group. By default the it does not add the nodes to /// the group inline void add(const Element & el, bool add_nodes = false, bool check_for_duplicate = true); /// \todo fix the default for add_nodes : make it coherent with the other /// method inline void add(const ElementType & type, UInt element, const GhostType & ghost_type = _not_ghost, bool add_nodes = true, bool check_for_duplicate = true); inline void addNode(UInt node_id, bool check_for_duplicate = true); inline void removeNode(UInt node_id); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /// fill the elements based on the underlying node group. virtual void fillFromNodeGroup(); // sort and remove duplicated values void optimize(); private: inline void addElement(const ElementType & elem_type, UInt elem_id, const GhostType & ghost_type); friend class GroupManager; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - const Array<UInt> & getElements(const ElementType & type, - const GhostType & ghost_type = _not_ghost) const; + const Array<UInt> & + getElements(const ElementType & type, + const GhostType & ghost_type = _not_ghost) const; AKANTU_GET_MACRO(Elements, elements, const ElementTypeMapArray<UInt> &); AKANTU_GET_MACRO(Nodes, node_group.getNodes(), const Array<UInt> &); AKANTU_GET_MACRO(NodeGroup, node_group, const NodeGroup &); AKANTU_GET_MACRO_NOT_CONST(NodeGroup, node_group, NodeGroup &); AKANTU_GET_MACRO(Dimension, dimension, UInt); AKANTU_GET_MACRO(Name, name, std::string); inline UInt getNbNodes() const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// Mesh to which this group belongs const Mesh & mesh; /// name of the group std::string name; /// list of elements composing the group ElementList elements; /// sub list of nodes which are composing the elements NodeGroup & node_group; /// group dimension UInt dimension; /// empty arry for the iterator to work when an element type not present Array<UInt> empty_elements; }; /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const ElementGroup & _this) { _this.printself(stream); return stream; } } // namespace akantu #include "element.hh" #include "element_group_inline_impl.cc" #endif /* __AKANTU_ELEMENT_GROUP_HH__ */ diff --git a/src/mesh/element_type_map.hh b/src/mesh/element_type_map.hh index 15ff1c1a7..a7457fed2 100644 --- a/src/mesh/element_type_map.hh +++ b/src/mesh/element_type_map.hh @@ -1,420 +1,436 @@ /** * @file element_type_map.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Aug 31 2011 * @date last modification: Fri Oct 02 2015 * * @brief storage class by element type * * @section LICENSE * * Copyright (©) 2010-2012, 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 "aka_array.hh" #include "aka_memory.hh" #include "aka_named_argument.hh" #include "element.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_TYPE_MAP_HH__ #define __AKANTU_ELEMENT_TYPE_MAP_HH__ namespace akantu { class FEEngine; } // namespace akantu namespace akantu { namespace { DECLARE_NAMED_ARGUMENT(all_ghost_types); DECLARE_NAMED_ARGUMENT(default_value); DECLARE_NAMED_ARGUMENT(element_kind); DECLARE_NAMED_ARGUMENT(ghost_type); DECLARE_NAMED_ARGUMENT(nb_component); DECLARE_NAMED_ARGUMENT(with_nb_element); DECLARE_NAMED_ARGUMENT(with_nb_nodes_per_element); DECLARE_NAMED_ARGUMENT(spatial_dimension); } // namespace template <class Stored, typename SupportType = ElementType> class ElementTypeMap; /* -------------------------------------------------------------------------- */ /* ElementTypeMapBase */ /* -------------------------------------------------------------------------- */ /// Common non templated base class for the ElementTypeMap class class ElementTypeMapBase { public: virtual ~ElementTypeMapBase() = default; }; /* -------------------------------------------------------------------------- */ /* ElementTypeMap */ /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> class ElementTypeMap : public ElementTypeMapBase { public: ElementTypeMap(); ~ElementTypeMap(); inline static std::string printType(const SupportType & type, const GhostType & ghost_type); /*! Tests whether a type is present in the object * @param type the type to check for * @param ghost_type optional: by default, the data map for non-ghost * elements is searched * @return true if the type is present. */ inline bool exists(const SupportType & type, const GhostType & ghost_type = _not_ghost) const; /*! get the stored data corresponding to a type * @param type the type to check for * @param ghost_type optional: by default, the data map for non-ghost * elements is searched * @return stored data corresponding to type. */ inline const Stored & operator()(const SupportType & type, const GhostType & ghost_type = _not_ghost) const; /*! get the stored data corresponding to a type * @param type the type to check for * @param ghost_type optional: by default, the data map for non-ghost * elements is searched * @return stored data corresponding to type. */ inline Stored & operator()(const SupportType & type, const GhostType & ghost_type = _not_ghost); /*! insert data of a new type (not yet present) into the map. THIS METHOD IS * NOT ARRAY SAFE, when using ElementTypeMapArray, use setArray instead * @param data to insert * @param type type of data (if this type is already present in the map, * an exception is thrown). * @param ghost_type optional: by default, the data map for non-ghost * elements is searched * @return stored data corresponding to type. */ inline Stored & operator()(const Stored & insert, const SupportType & type, const GhostType & ghost_type = _not_ghost); /// print helper virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Element type Iterator */ /* ------------------------------------------------------------------------ */ /*! iterator allows to iterate over type-data pairs of the map. The interface * expects the SupportType to be ElementType. */ typedef std::map<SupportType, Stored> DataMap; class type_iterator : private std::iterator<std::forward_iterator_tag, const SupportType> { public: using value_type = const SupportType; using pointer = const SupportType *; using reference = const SupportType &; protected: using DataMapIterator = typename ElementTypeMap<Stored>::DataMap::const_iterator; public: type_iterator(DataMapIterator & list_begin, DataMapIterator & list_end, UInt dim, ElementKind ek); type_iterator(const type_iterator & it); type_iterator() {} inline reference operator*(); inline reference operator*() const; inline type_iterator & operator++(); type_iterator operator++(int); inline bool operator==(const type_iterator & other) const; inline bool operator!=(const type_iterator & other) const; type_iterator & operator=(const type_iterator & other); private: DataMapIterator list_begin; DataMapIterator list_end; UInt dim; ElementKind kind; }; /// helper class to use in range for constructions class ElementTypesIteratorHelper { public: using Container = ElementTypeMap<Stored, SupportType>; using iterator = typename Container::type_iterator; ElementTypesIteratorHelper(const Container & container, UInt dim, GhostType ghost_type, ElementKind kind) : container(std::cref(container)), dim(dim), ghost_type(ghost_type), kind(kind) {} template <typename... pack> ElementTypesIteratorHelper(const Container & container, use_named_args_t, pack &&... _pack) : ElementTypesIteratorHelper( container, OPTIONAL_NAMED_ARG(spatial_dimension, _all_dimensions), OPTIONAL_NAMED_ARG(ghost_type, _not_ghost), OPTIONAL_NAMED_ARG(element_kind, _ek_regular)) {} ElementTypesIteratorHelper(const ElementTypesIteratorHelper &) = default; ElementTypesIteratorHelper & operator=(const ElementTypesIteratorHelper &) = default; ElementTypesIteratorHelper & operator=(ElementTypesIteratorHelper &&) = default; iterator begin() { return container.get().firstType(dim, ghost_type, kind); } iterator end() { return container.get().lastType(dim, ghost_type, kind); } private: std::reference_wrapper<const Container> container; UInt dim; GhostType ghost_type; ElementKind kind; }; -public: - /// method to create the helper class to use in range for constructs - template <typename... pack> - decltype(auto) elementTypes(pack &&... _pack) const; - private: ElementTypesIteratorHelper - elementTypesImpl(UInt dim, GhostType ghost_type = _not_ghost, + elementTypesImpl(UInt dim = _all_dimensions, + GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) const; template <typename... pack> ElementTypesIteratorHelper elementTypesImpl(const use_named_args_t & /*unused*/, pack &&... _pack) const; + template <typename... pack> + using named_argument_test = + std::conjunction<std::bool_constant<(sizeof...(pack) > 0)>, + is_named_argument<pack>...>; + +public: + template <typename... pack> + std::enable_if_t<named_argument_test<pack...>{}, ElementTypesIteratorHelper> + elementTypes(pack &&... _pack) const { + return elementTypesImpl(use_named_args, + std::forward<decltype(_pack)>(_pack)...); + } + + template <typename... pack> + std::enable_if_t<not named_argument_test<pack...>{}, + ElementTypesIteratorHelper> + elementTypes(pack &&... _pack) const { + return elementTypesImpl(std::forward<decltype(_pack)>(_pack)...); + } + public: /*! Get an iterator to the beginning of a subset datamap. This method expects * the SupportType to be ElementType. * @param dim optional: iterate over data of dimension dim (e.g. when * iterating over (surface) facets of a 3D mesh, dim would be 2). * by default, all dimensions are considered. * @param ghost_type optional: by default, the data map for non-ghost * elements is iterated over. * @param kind optional: the kind of element to search for (see * aka_common.hh), by default all kinds are considered * @return an iterator to the first stored data matching the filters * or an iterator to the end of the map if none match*/ inline type_iterator firstType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_not_defined) const; /*! Get an iterator to the end of a subset datamap. This method expects * the SupportType to be ElementType. * @param dim optional: iterate over data of dimension dim (e.g. when * iterating over (surface) facets of a 3D mesh, dim would be 2). * by default, all dimensions are considered. * @param ghost_type optional: by default, the data map for non-ghost * elements is iterated over. * @param kind optional: the kind of element to search for (see * aka_common.hh), by default all kinds are considered * @return an iterator to the last stored data matching the filters * or an iterator to the end of the map if none match */ inline type_iterator lastType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_not_defined) const; protected: /*! Direct access to the underlying data map. for internal use by daughter * classes only * @param ghost_type whether to return the data map or the ghost_data map * @return the raw map */ inline DataMap & getData(GhostType ghost_type); /*! Direct access to the underlying data map. for internal use by daughter * classes only * @param ghost_type whether to return the data map or the ghost_data map * @return the raw map */ inline const DataMap & getData(GhostType ghost_type) const; /* ------------------------------------------------------------------------ */ protected: DataMap data; DataMap ghost_data; }; /* -------------------------------------------------------------------------- */ /* Some typedefs */ /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> class ElementTypeMapArray : public ElementTypeMap<Array<T> *, SupportType>, public Memory { public: using type = T; using array_type = Array<T>; protected: using parent = ElementTypeMap<Array<T> *, SupportType>; using DataMap = typename parent::DataMap; public: using type_iterator = typename parent::type_iterator; /// standard assigment (copy) operator void operator=(const ElementTypeMapArray &) = delete; ElementTypeMapArray(const ElementTypeMapArray &) = delete; /*! Constructor * @param id optional: identifier (string) * @param parent_id optional: parent identifier. for organizational purposes * only * @param memory_id optional: choose a specific memory, defaults to memory 0 */ ElementTypeMapArray(const ID & id = "by_element_type_array", const ID & parent_id = "no_parent", const MemoryID & memory_id = 0) : parent(), Memory(parent_id + ":" + id, memory_id), name(id){}; /*! allocate memory for a new array * @param size number of tuples of the new array * @param nb_component tuple size * @param type the type under which the array is indexed in the map * @param ghost_type whether to add the field to the data map or the * ghost_data map * @return a reference to the allocated array */ inline Array<T> & alloc(UInt size, UInt nb_component, const SupportType & type, const GhostType & ghost_type, const T & default_value = T()); /*! allocate memory for a new array in both the data and the ghost_data map * @param size number of tuples of the new array * @param nb_component tuple size * @param type the type under which the array is indexed in the map*/ inline void alloc(UInt size, UInt nb_component, const SupportType & type, const T & default_value = T()); /* get a reference to the array of certain type * @param type data filed under type is returned * @param ghost_type optional: by default the non-ghost map is searched * @return a reference to the array */ inline const Array<T> & operator()(const SupportType & type, const GhostType & ghost_type = _not_ghost) const; /// access the data of an element, this combine the map and array accessor inline const T & operator()(const Element & element) const; /// access the data of an element, this combine the map and array accessor inline T & operator()(const Element & element); /* get a reference to the array of certain type * @param type data filed under type is returned * @param ghost_type optional: by default the non-ghost map is searched * @return a const reference to the array */ inline Array<T> & operator()(const SupportType & type, const GhostType & ghost_type = _not_ghost); /*! insert data of a new type (not yet present) into the map. * @param type type of data (if this type is already present in the map, * an exception is thrown). * @param ghost_type optional: by default, the data map for non-ghost * elements is searched * @param vect the vector to include into the map * @return stored data corresponding to type. */ inline void setArray(const SupportType & type, const GhostType & ghost_type, const Array<T> & vect); /*! frees all memory related to the data*/ inline void free(); /*! set all values in the ElementTypeMap to zero*/ inline void clear(); /*! deletes and reorders entries in the stored arrays * @param new_numbering a ElementTypeMapArray of new indices. UInt(-1) * indicates * deleted entries. */ inline void onElementsRemoved(const ElementTypeMapArray<UInt> & new_numbering); /// text output helper virtual void printself(std::ostream & stream, int indent = 0) const; /*! set the id * @param id the new name */ inline void setID(const ID & id) { this->id = id; } ElementTypeMap<UInt> getNbComponents(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_not_defined) const { ElementTypeMap<UInt> nb_components; for (auto & type : this->elementTypes(dim, ghost_type, kind)) { UInt nb_comp = (*this)(type, ghost_type).getNbComponent(); nb_components(type, ghost_type) = nb_comp; } return nb_components; } /* ------------------------------------------------------------------------ */ /* more evolved allocators */ /* ------------------------------------------------------------------------ */ public: /// initialize the arrays in accordance to a functor template <class Func> void initialize(const Func & f, const T & default_value = T()); /// initialize with sizes and number of components in accordance of a mesh /// content template <typename... pack> void initialize(const Mesh & mesh, pack &&... _pack); /// initialize with sizes and number of components in accordance of a fe /// engine content (aka integration points) template <typename... pack> void initialize(const FEEngine & fe_engine, pack &&... _pack); /* ------------------------------------------------------------------------ */ /* Accesssors */ /* ------------------------------------------------------------------------ */ public: /// get the name of the internal field AKANTU_GET_MACRO(Name, name, ID); /// name of the elment type map: e.g. connectivity, grad_u ID name; }; /// to store data Array<Real> by element type using ElementTypeMapReal = ElementTypeMapArray<Real>; /// to store data Array<Int> by element type using ElementTypeMapInt = ElementTypeMapArray<Int>; /// to store data Array<UInt> by element type using ElementTypeMapUInt = ElementTypeMapArray<UInt, ElementType>; /// Map of data of type UInt stored in a mesh using UIntDataMap = std::map<std::string, Array<UInt> *>; using ElementTypeMapUIntDataMap = ElementTypeMap<UIntDataMap, ElementType>; } // namespace akantu #endif /* __AKANTU_ELEMENT_TYPE_MAP_HH__ */ diff --git a/src/mesh/element_type_map_tmpl.hh b/src/mesh/element_type_map_tmpl.hh index 06ad48a37..1bceff808 100644 --- a/src/mesh/element_type_map_tmpl.hh +++ b/src/mesh/element_type_map_tmpl.hh @@ -1,650 +1,631 @@ /** * @file element_type_map_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Aug 31 2011 * @date last modification: Fri Oct 02 2015 * * @brief implementation of template functions of the ElementTypeMap and * ElementTypeMapArray classes * * @section LICENSE * * Copyright (©) 2010-2012, 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 "aka_static_if.hh" #include "element_type_map.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ #include "element_type_conversion.hh" /* -------------------------------------------------------------------------- */ -#include <tuple> -/* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_TYPE_MAP_TMPL_HH__ #define __AKANTU_ELEMENT_TYPE_MAP_TMPL_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ /* ElementTypeMap */ /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline std::string ElementTypeMap<Stored, SupportType>::printType(const SupportType & type, const GhostType & ghost_type) { std::stringstream sstr; sstr << "(" << ghost_type << ":" << type << ")"; return sstr.str(); } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline bool ElementTypeMap<Stored, SupportType>::exists( const SupportType & type, const GhostType & ghost_type) const { return this->getData(ghost_type).find(type) != this->getData(ghost_type).end(); } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline const Stored & ElementTypeMap<Stored, SupportType>:: operator()(const SupportType & type, const GhostType & ghost_type) const { auto it = this->getData(ghost_type).find(type); if (it == this->getData(ghost_type).end()) AKANTU_SILENT_EXCEPTION("No element of type " << ElementTypeMap::printType(type, ghost_type) << " in this ElementTypeMap<" << debug::demangle(typeid(Stored).name()) << "> class"); return it->second; } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline Stored & ElementTypeMap<Stored, SupportType>:: operator()(const SupportType & type, const GhostType & ghost_type) { return this->getData(ghost_type)[type]; } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline Stored & ElementTypeMap<Stored, SupportType>:: operator()(const Stored & insert, const SupportType & type, const GhostType & ghost_type) { auto it = this->getData(ghost_type).find(type); if (it != this->getData(ghost_type).end()) { AKANTU_SILENT_EXCEPTION("Element of type " << ElementTypeMap::printType(type, ghost_type) << " already in this ElementTypeMap<" << debug::demangle(typeid(Stored).name()) << "> class"); } else { auto & data = this->getData(ghost_type); const auto & res = data.insert(std::pair<ElementType, Stored>(type, insert)); it = res.first; } return it->second; } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline typename ElementTypeMap<Stored, SupportType>::DataMap & ElementTypeMap<Stored, SupportType>::getData(GhostType ghost_type) { if (ghost_type == _not_ghost) return data; return ghost_data; } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline const typename ElementTypeMap<Stored, SupportType>::DataMap & ElementTypeMap<Stored, SupportType>::getData(GhostType ghost_type) const { if (ghost_type == _not_ghost) return data; return ghost_data; } /* -------------------------------------------------------------------------- */ /// Works only if stored is a pointer to a class with a printself method template <class Stored, typename SupportType> void ElementTypeMap<Stored, SupportType>::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "ElementTypeMap<" << debug::demangle(typeid(Stored).name()) << "> [" << std::endl; for (auto gt : ghost_types) { const DataMap & data = getData(gt); for (auto & pair : data) { stream << space << space << ElementTypeMap::printType(pair.first, gt) << std::endl; } } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> ElementTypeMap<Stored, SupportType>::ElementTypeMap() = default; /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> ElementTypeMap<Stored, SupportType>::~ElementTypeMap() = default; /* -------------------------------------------------------------------------- */ /* ElementTypeMapArray */ /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> inline Array<T> & ElementTypeMapArray<T, SupportType>::alloc( UInt size, UInt nb_component, const SupportType & type, const GhostType & ghost_type, const T & default_value) { std::string ghost_id = ""; if (ghost_type == _ghost) ghost_id = ":ghost"; Array<T> * tmp; auto it = this->getData(ghost_type).find(type); if (it == this->getData(ghost_type).end()) { std::stringstream sstr; sstr << this->id << ":" << type << ghost_id; tmp = &(Memory::alloc<T>(sstr.str(), size, nb_component, default_value)); std::stringstream sstrg; sstrg << ghost_type; // tmp->setTag(sstrg.str()); this->getData(ghost_type)[type] = tmp; } else { AKANTU_DEBUG_INFO( "The vector " << this->id << this->printType(type, ghost_type) << " already exists, it is resized instead of allocated."); tmp = it->second; it->second->resize(size); } return *tmp; } /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> inline void ElementTypeMapArray<T, SupportType>::alloc(UInt size, UInt nb_component, const SupportType & type, const T & default_value) { this->alloc(size, nb_component, type, _not_ghost, default_value); this->alloc(size, nb_component, type, _ghost, default_value); } /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> inline void ElementTypeMapArray<T, SupportType>::free() { AKANTU_DEBUG_IN(); - for (auto && gt : ghost_types) { + for (auto gt : ghost_types) { auto & data = this->getData(gt); for (auto & pair : data) { dealloc(pair.second->getID()); } data.clear(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> inline void ElementTypeMapArray<T, SupportType>::clear() { for (auto gt : ghost_types) { auto & data = this->getData(gt); for (auto & vect : data) { vect.second->clear(); } } } /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> inline const Array<T> & ElementTypeMapArray<T, SupportType>:: operator()(const SupportType & type, const GhostType & ghost_type) const { auto it = this->getData(ghost_type).find(type); if (it == this->getData(ghost_type).end()) AKANTU_SILENT_EXCEPTION("No element of type " << ElementTypeMapArray::printType(type, ghost_type) << " in this const ElementTypeMapArray<" << debug::demangle(typeid(T).name()) << "> class(\"" << this->id << "\")"); return *(it->second); } /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> inline Array<T> & ElementTypeMapArray<T, SupportType>:: operator()(const SupportType & type, const GhostType & ghost_type) { auto it = this->getData(ghost_type).find(type); if (it == this->getData(ghost_type).end()) AKANTU_SILENT_EXCEPTION("No element of type " << ElementTypeMapArray::printType(type, ghost_type) << " in this ElementTypeMapArray<" << debug::demangle(typeid(T).name()) << "> class (\"" << this->id << "\")"); return *(it->second); } /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> inline void ElementTypeMapArray<T, SupportType>::setArray(const SupportType & type, const GhostType & ghost_type, const Array<T> & vect) { auto it = this->getData(ghost_type).find(type); if (AKANTU_DEBUG_TEST(dblWarning) && it != this->getData(ghost_type).end() && it->second != &vect) { AKANTU_DEBUG_WARNING( "The Array " << this->printType(type, ghost_type) << " is already registred, this call can lead to a memory leak."); } this->getData(ghost_type)[type] = &(const_cast<Array<T> &>(vect)); } /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> inline void ElementTypeMapArray<T, SupportType>::onElementsRemoved( const ElementTypeMapArray<UInt> & new_numbering) { for (auto gt : ghost_types) { for (auto & type : new_numbering.elementTypes(_all_dimensions, gt, _ek_not_defined)) { SupportType support_type = convertType<ElementType, SupportType>(type); if (this->exists(support_type, gt)) { const auto & renumbering = new_numbering(type, gt); if (renumbering.size() == 0) continue; auto & vect = this->operator()(support_type, gt); auto nb_component = vect.getNbComponent(); Array<T> tmp(renumbering.size(), nb_component); UInt new_size = 0; for (UInt i = 0; i < vect.size(); ++i) { UInt new_i = renumbering(i); if (new_i != UInt(-1)) { memcpy(tmp.storage() + new_i * nb_component, vect.storage() + i * nb_component, nb_component * sizeof(T)); ++new_size; } } tmp.resize(new_size); vect.copy(tmp); } } } } /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> void ElementTypeMapArray<T, SupportType>::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "ElementTypeMapArray<" << debug::demangle(typeid(T).name()) << "> [" << std::endl; for (UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType)g; const DataMap & data = this->getData(gt); typename DataMap::const_iterator it; for (it = data.begin(); it != data.end(); ++it) { stream << space << space << ElementTypeMapArray::printType(it->first, gt) << " [" << std::endl; it->second->printself(stream, indent + 3); stream << space << space << " ]" << std::endl; } } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ /* SupportType Iterator */ /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> ElementTypeMap<Stored, SupportType>::type_iterator::type_iterator( DataMapIterator & list_begin, DataMapIterator & list_end, UInt dim, ElementKind ek) : list_begin(list_begin), list_end(list_end), dim(dim), kind(ek) {} /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> ElementTypeMap<Stored, SupportType>::type_iterator::type_iterator( const type_iterator & it) : list_begin(it.list_begin), list_end(it.list_end), dim(it.dim), kind(it.kind) {} /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> typename ElementTypeMap<Stored, SupportType>::type_iterator & ElementTypeMap<Stored, SupportType>::type_iterator:: operator=(const type_iterator & it) { if (this != &it) { list_begin = it.list_begin; list_end = it.list_end; dim = it.dim; kind = it.kind; } return *this; } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline typename ElementTypeMap<Stored, SupportType>::type_iterator::reference ElementTypeMap<Stored, SupportType>::type_iterator::operator*() { return list_begin->first; } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline typename ElementTypeMap<Stored, SupportType>::type_iterator::reference ElementTypeMap<Stored, SupportType>::type_iterator::operator*() const { return list_begin->first; } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline typename ElementTypeMap<Stored, SupportType>::type_iterator & ElementTypeMap<Stored, SupportType>::type_iterator::operator++() { ++list_begin; while ((list_begin != list_end) && (((dim != _all_dimensions) && (dim != Mesh::getSpatialDimension(list_begin->first))) || ((kind != _ek_not_defined) && (kind != Mesh::getKind(list_begin->first))))) ++list_begin; return *this; } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> typename ElementTypeMap<Stored, SupportType>::type_iterator ElementTypeMap<Stored, SupportType>::type_iterator::operator++(int) { type_iterator tmp(*this); operator++(); return tmp; } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline bool ElementTypeMap<Stored, SupportType>::type_iterator:: operator==(const type_iterator & other) const { return this->list_begin == other.list_begin; } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline bool ElementTypeMap<Stored, SupportType>::type_iterator:: operator!=(const type_iterator & other) const { return this->list_begin != other.list_begin; } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> typename ElementTypeMap<Stored, SupportType>::ElementTypesIteratorHelper ElementTypeMap<Stored, SupportType>::elementTypesImpl( UInt dim, GhostType ghost_type, ElementKind kind) const { return ElementTypesIteratorHelper(*this, dim, ghost_type, kind); } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> template <typename... pack> typename ElementTypeMap<Stored, SupportType>::ElementTypesIteratorHelper ElementTypeMap<Stored, SupportType>::elementTypesImpl( const use_named_args_t & /*unused*/, pack &&... _pack) const { return ElementTypesIteratorHelper(*this, use_named_args, _pack...); } -/* -------------------------------------------------------------------------- */ -template <class Stored, typename SupportType> -template <typename... pack> -decltype(auto) -ElementTypeMap<Stored, SupportType>::elementTypes(pack &&... _pack) const { - auto && first_arg = std::get<0>(std::forward_as_tuple(_pack...)); - - return static_if(is_named_argument<std::decay_t<decltype(first_arg)>>{}) - .then([&](auto && /*a*/) { - return elementTypesImpl(use_named_args, - std::forward<decltype(_pack)>(_pack)...); - }) - .else_([&](auto && /*a*/) { - return elementTypesImpl(std::forward<decltype(_pack)>(_pack)...); - })(std::forward<decltype(first_arg)>(first_arg)); -} - /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline typename ElementTypeMap<Stored, SupportType>::type_iterator ElementTypeMap<Stored, SupportType>::firstType(UInt dim, GhostType ghost_type, ElementKind kind) const { typename DataMap::const_iterator b, e; b = getData(ghost_type).begin(); e = getData(ghost_type).end(); // loop until the first valid type while ((b != e) && (((dim != _all_dimensions) && (dim != Mesh::getSpatialDimension(b->first))) || ((kind != _ek_not_defined) && (kind != Mesh::getKind(b->first))))) ++b; return typename ElementTypeMap<Stored, SupportType>::type_iterator(b, e, dim, kind); } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline typename ElementTypeMap<Stored, SupportType>::type_iterator ElementTypeMap<Stored, SupportType>::lastType(UInt dim, GhostType ghost_type, ElementKind kind) const { typename DataMap::const_iterator e; e = getData(ghost_type).end(); return typename ElementTypeMap<Stored, SupportType>::type_iterator(e, e, dim, kind); } /* -------------------------------------------------------------------------- */ /// standard output stream operator template <class Stored, typename SupportType> inline std::ostream & operator<<(std::ostream & stream, const ElementTypeMap<Stored, SupportType> & _this) { _this.printself(stream); return stream; } /* -------------------------------------------------------------------------- */ class ElementTypeMapArrayInializer { public: ElementTypeMapArrayInializer(UInt spatial_dimension = _all_dimensions, UInt nb_component = 1, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_regular) : spatial_dimension(spatial_dimension), nb_component(nb_component), ghost_type(ghost_type), element_kind(element_kind) {} const GhostType & ghostType() const { return ghost_type; } protected: UInt spatial_dimension; UInt nb_component; GhostType ghost_type; ElementKind element_kind; }; /* -------------------------------------------------------------------------- */ class MeshElementTypeMapArrayInializer : public ElementTypeMapArrayInializer { public: MeshElementTypeMapArrayInializer( const Mesh & mesh, UInt nb_component = 1, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_regular, bool with_nb_element = false, bool with_nb_nodes_per_element = false) : ElementTypeMapArrayInializer(spatial_dimension, nb_component, ghost_type, element_kind), mesh(mesh), with_nb_element(with_nb_element), with_nb_nodes_per_element(with_nb_nodes_per_element) {} decltype(auto) elementTypes() const { return mesh.elementTypes(this->spatial_dimension, this->ghost_type, this->element_kind); } virtual UInt size(const ElementType & type) const { if (with_nb_element) return mesh.getNbElement(type, this->ghost_type); return 0; } UInt nbComponent(const ElementType & type) const { if (with_nb_nodes_per_element) return (this->nb_component * mesh.getNbNodesPerElement(type)); return this->nb_component; } protected: const Mesh & mesh; bool with_nb_element; bool with_nb_nodes_per_element; }; /* -------------------------------------------------------------------------- */ class FEEngineElementTypeMapArrayInializer : public MeshElementTypeMapArrayInializer { public: FEEngineElementTypeMapArrayInializer( const FEEngine & fe_engine, UInt nb_component = 1, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_regular); UInt size(const ElementType & type) const override; using ElementTypesIteratorHelper = ElementTypeMapArray<Real, ElementType>::ElementTypesIteratorHelper; ElementTypesIteratorHelper elementTypes() const; protected: const FEEngine & fe_engine; }; /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> template <class Func> void ElementTypeMapArray<T, SupportType>::initialize(const Func & f, const T & default_value) { for (auto & type : f.elementTypes()) { if (not this->exists(type, f.ghostType())) this->alloc(f.size(type), f.nbComponent(type), type, f.ghostType(), default_value); } } /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> template <typename... pack> void ElementTypeMapArray<T, SupportType>::initialize(const Mesh & mesh, pack &&... _pack) { GhostType requested_ghost_type = OPTIONAL_NAMED_ARG(ghost_type, _casper); bool all_ghost_types = requested_ghost_type == _casper; for (auto ghost_type : ghost_types) { if ((not(ghost_type == requested_ghost_type)) and (not all_ghost_types)) continue; this->initialize( MeshElementTypeMapArrayInializer( mesh, OPTIONAL_NAMED_ARG(nb_component, 1), OPTIONAL_NAMED_ARG(spatial_dimension, mesh.getSpatialDimension()), ghost_type, OPTIONAL_NAMED_ARG(element_kind, _ek_regular), OPTIONAL_NAMED_ARG(with_nb_element, false), OPTIONAL_NAMED_ARG(with_nb_nodes_per_element, false)), OPTIONAL_NAMED_ARG(default_value, T())); } } /* -------------------------------------------------------------------------- */ template <typename T, typename SupportType> template <typename... pack> void ElementTypeMapArray<T, SupportType>::initialize(const FEEngine & fe_engine, pack &&... _pack) { bool all_ghost_types = OPTIONAL_NAMED_ARG(all_ghost_types, true); GhostType requested_ghost_type = OPTIONAL_NAMED_ARG(ghost_type, _not_ghost); for (auto ghost_type : ghost_types) { if ((not(ghost_type == requested_ghost_type)) and (not all_ghost_types)) continue; this->initialize(FEEngineElementTypeMapArrayInializer( fe_engine, OPTIONAL_NAMED_ARG(nb_component, 1), OPTIONAL_NAMED_ARG(spatial_dimension, UInt(-2)), ghost_type, OPTIONAL_NAMED_ARG(element_kind, _ek_regular)), OPTIONAL_NAMED_ARG(default_value, T())); } } /* -------------------------------------------------------------------------- */ template <class T, typename SupportType> inline T & ElementTypeMapArray<T, SupportType>:: operator()(const Element & element) { return this->operator()(element.type, element.ghost_type)(element.element); } /* -------------------------------------------------------------------------- */ template <class T, typename SupportType> inline const T & ElementTypeMapArray<T, SupportType>:: operator()(const Element & element) const { return this->operator()(element.type, element.ghost_type)(element.element); } } // namespace akantu #endif /* __AKANTU_ELEMENT_TYPE_MAP_TMPL_HH__ */