diff --git a/packages/core.cmake b/packages/core.cmake index e362dc234..0261b1224 100644 --- a/packages/core.cmake +++ b/packages/core.cmake @@ -1,584 +1,585 @@ #=============================================================================== # @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_zip.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/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.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_inline_impl.cc fe_engine/shape_lagrange.cc fe_engine/shape_lagrange.hh fe_engine/shape_lagrange_inline_impl.cc fe_engine/shape_linked.cc fe_engine/shape_linked.hh fe_engine/shape_linked_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_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/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 ) 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_grid_dynamic.hh b/src/common/aka_grid_dynamic.hh index 8de0a6a78..ccc2bf128 100644 --- a/src/common/aka_grid_dynamic.hh +++ b/src/common/aka_grid_dynamic.hh @@ -1,494 +1,472 @@ /** * @file aka_grid_dynamic.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Sat Sep 26 2015 * * @brief Grid that is auto balanced * * @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_array.hh" #include "aka_types.hh" #include <iostream> /* -------------------------------------------------------------------------- */ #include <map> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_GRID_DYNAMIC_HH__ #define __AKANTU_AKA_GRID_DYNAMIC_HH__ namespace akantu { class Mesh; template<typename T> class SpatialGrid { public: SpatialGrid(UInt dimension) : dimension(dimension), spacing(dimension), center(dimension), lower(dimension), upper(dimension), empty_cell() {} SpatialGrid(UInt dimension, const Vector<Real> & spacing, const Vector<Real> & center) : dimension(dimension), spacing(spacing), center(center), lower(dimension), upper(dimension), empty_cell() { for (UInt i = 0; i < dimension; ++i) { lower(i) = std::numeric_limits<Real>::max(); upper(i) = - std::numeric_limits<Real>::max(); } } virtual ~SpatialGrid() {}; class neighbor_cells_iterator; class cells_iterator; class CellID { public: CellID() : ids() {} CellID(UInt dimention) : ids(dimention) {} void setID(UInt dir, Int id) { ids(dir) = id; } Int getID(UInt dir) const { return ids(dir); } bool operator<(const CellID & id) const { return std::lexicographical_compare(ids.storage(), ids.storage() + ids.size(), id.ids.storage(), id.ids.storage() + id.ids.size()); } bool operator==(const CellID & id) const { return std::equal(ids.storage(), ids.storage() + ids.size(), id.ids.storage()); } bool operator!=(const CellID & id) const { return !(operator==(id)); } private: friend class neighbor_cells_iterator; friend class cells_iterator; Vector<Int> ids; }; /* -------------------------------------------------------------------------- */ class Cell { public: typedef typename std::vector<T>::iterator iterator; typedef typename std::vector<T>::const_iterator const_iterator; Cell() : id(), data() { } Cell(const CellID &cell_id) : id(cell_id), data() { } bool operator==(const Cell & cell) const { return id == cell.id; } bool operator!=(const Cell & cell) const { return id != cell.id; } Cell & add(const T & d) { data.push_back(d); return *this; } iterator begin() { return data.begin(); } const_iterator begin() const { return data.begin(); } iterator end() { return data.end(); } const_iterator end() const { return data.end(); } private: CellID id; std::vector<T> data; }; private: typedef std::map<CellID, Cell> cells_container; public: const Cell & getCell(const CellID & cell_id) const { typename cells_container::const_iterator it = cells.find(cell_id); if(it != cells.end()) return it->second; else return empty_cell; } typename Cell::iterator beginCell(const CellID & cell_id) { typename cells_container::iterator it = cells.find(cell_id); if(it != cells.end()) return it->second.begin(); else return empty_cell.begin(); } typename Cell::iterator endCell(const CellID & cell_id) { typename cells_container::iterator it = cells.find(cell_id); if(it != cells.end()) return it->second.end(); else return empty_cell.end(); } typename Cell::const_iterator beginCell(const CellID & cell_id) const { typename cells_container::const_iterator it = cells.find(cell_id); if(it != cells.end()) return it->second.begin(); else return empty_cell.begin(); } typename Cell::const_iterator endCell(const CellID & cell_id) const { typename cells_container::const_iterator it = cells.find(cell_id); if(it != cells.end()) return it->second.end(); else return empty_cell.end(); } class neighbor_cells_iterator : private std::iterator<std::forward_iterator_tag, UInt> { public: neighbor_cells_iterator(const CellID & cell_id, bool end) : cell_id(cell_id), position(cell_id.ids.size(), end ? 1 : -1) { this->updateIt(); if(end) this->it++; } neighbor_cells_iterator& operator++() { UInt i = 0; for (; i < position.size() && position(i) == 1; ++i); if(i == position.size()) ++it; else { for (UInt j = 0; j < i; ++j) position(j) = -1; position(i)++; updateIt(); } return *this; } neighbor_cells_iterator operator++(int) { neighbor_cells_iterator tmp(*this); operator++(); return tmp; }; bool operator==(const neighbor_cells_iterator& rhs) const { return cell_id == rhs.cell_id && it == rhs.it; }; bool operator!=(const neighbor_cells_iterator& rhs) const { return ! operator==(rhs); }; CellID operator*() const { CellID cur_cell_id(cell_id); cur_cell_id.ids += position; return cur_cell_id; }; private: void updateIt() { it = 0; for (UInt i = 0; i < position.size(); ++i) it = it * 3 + (position(i) + 1); } private: /// central cell id const CellID & cell_id; // number representing the current neighbor in base 3; UInt it; Vector<Int> position; }; class cells_iterator : private std::iterator<std::forward_iterator_tag, CellID> { public: cells_iterator(typename std::map<CellID, Cell>::const_iterator it) : it(it) { } cells_iterator & operator++() { this->it++; return *this; } cells_iterator operator++(int) {cells_iterator tmp(*this); operator++(); return tmp; }; bool operator==(const cells_iterator& rhs) const { return it == rhs.it; }; bool operator!=(const cells_iterator& rhs) const { return ! operator==(rhs); }; CellID operator*() const { CellID cur_cell_id(this->it->first); return cur_cell_id; }; private: /// map iterator typename std::map<CellID, Cell>::const_iterator it; }; public: template<class vector_type> Cell & insert(const T & d, const vector_type & position) { CellID cell_id = getCellID(position); typename cells_container::iterator it = cells.find(cell_id); if(it == cells.end()) { Cell cell(cell_id); // #if defined(AKANTU_NDEBUG) Cell & tmp = (cells[cell_id] = cell).add(d); // #else // Cell & tmp = (cells[cell_id] = cell).add(d, position); // #endif for (UInt i = 0; i < dimension; ++i) { Real posl = center(i) + cell_id.getID(i) * spacing(i); Real posu = posl + spacing(i); if(posl < lower(i)) lower(i) = posl; if(posu > upper(i)) upper(i) = posu; } return tmp; } else { // #if defined(AKANTU_NDEBUG) return it->second.add(d); // #else // return it->second.add(d, position); // #endif } } inline neighbor_cells_iterator beginNeighborCells(const CellID & cell_id) const { return neighbor_cells_iterator(cell_id, false); } inline neighbor_cells_iterator endNeighborCells(const CellID & cell_id) const { return neighbor_cells_iterator(cell_id, true); } inline cells_iterator beginCells() const { typename std::map<CellID, Cell>::const_iterator begin = this->cells.begin(); return cells_iterator(begin); } inline cells_iterator endCells() const { typename std::map<CellID, Cell>::const_iterator end = this->cells.end(); return cells_iterator(end); } template<class vector_type> CellID getCellID(const vector_type & position) const { CellID cell_id(dimension); for (UInt i = 0; i < dimension; ++i) { cell_id.setID(i, getCellID(position(i), i)); } return cell_id; } void printself(std::ostream & stream, int indent = 0) 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(5); stream << space << "SpatialGrid<" << debug::demangle(typeid(T).name()) << "> [" << std::endl; stream << space << " + dimension : " << this->dimension << std::endl; stream << space << " + lower bounds : {"; for (UInt i = 0; i < lower.size(); ++i) { if(i != 0) stream << ", "; stream << lower(i); }; stream << "}" << std::endl; stream << space << " + upper bounds : {"; for (UInt i = 0; i < upper.size(); ++i) { if(i != 0) stream << ", "; stream << upper(i); }; stream << "}" << std::endl; stream << space << " + spacing : {"; for (UInt i = 0; i < spacing.size(); ++i) { if(i != 0) stream << ", "; stream << spacing(i); }; stream << "}" << std::endl; stream << space << " + center : {"; for (UInt i = 0; i < center.size(); ++i) { if(i != 0) stream << ", "; stream << center(i); }; stream << "}" << std::endl; stream << space << " + nb_cells : " << this->cells.size() << "/"; Vector<Real> dist(this->dimension); dist = upper; dist -= lower; for (UInt i = 0; i < this->dimension; ++i) { dist(i) /= spacing(i); } UInt nb_cells = std::ceil(dist(0)); for (UInt i = 1; i < this->dimension; ++i) { nb_cells *= std::ceil(dist(i)); } stream << nb_cells << std::endl; stream << space << "]" << std::endl; stream.precision(prec); stream.flags(ff); } void saveAsMesh(Mesh & mesh) const; private: /* -------------------------------------------------------------------------- */ inline UInt getCellID(Real position, UInt direction) const { AKANTU_DEBUG_ASSERT(direction < center.size(), "The direction asked (" << direction << ") is out of range " << center.size()); Real dist_center = position - center(direction); Int id = std::floor(dist_center / spacing(direction)); //if(dist_center < 0) id--; return id; } friend class GridSynchronizer; public: AKANTU_GET_MACRO(LowerBounds, lower, const Vector<Real> &); AKANTU_GET_MACRO(UpperBounds, upper, const Vector<Real> &); AKANTU_GET_MACRO(Spacing, spacing, const Vector<Real> &); protected: UInt dimension; cells_container cells; Vector<Real> spacing; Vector<Real> center; Vector<Real> lower; Vector<Real> upper; Cell empty_cell; }; /// standard output stream operator template<typename T> inline std::ostream & operator <<(std::ostream & stream, const SpatialGrid<T> & _this) { _this.printself(stream); return stream; } } // akantu #include "mesh.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template<typename T> void SpatialGrid<T>::saveAsMesh(Mesh & mesh) const { Array<Real> & nodes = const_cast<Array<Real> &>(mesh.getNodes()); ElementType type; switch(dimension) { case 1: type = _segment_2; break; case 2: type = _quadrangle_4; break; case 3: type = _hexahedron_8; break; } mesh.addConnectivityType(type); - Array<UInt> & connectivity = const_cast<Array<UInt> &>(mesh.getConnectivity(type)); - Array<UInt> & uint_data = *mesh.getDataPointer<UInt>("tag_1", type); - - typename cells_container::const_iterator it = cells.begin(); - typename cells_container::const_iterator end = cells.end(); + auto & connectivity = const_cast<Array<UInt> &>(mesh.getConnectivity(type)); + auto & uint_data = mesh.getDataPointer<UInt>("tag_1", type); Vector<Real> pos(dimension); UInt global_id = 0; - for (;it != end; ++it, ++global_id) { + for (auto & cell_pair : cells) { UInt cur_node = nodes.getSize(); UInt cur_elem = connectivity.getSize(); - const CellID & cell_id = it->first; + const CellID & cell_id = cell_pair.first; for (UInt i = 0; i < dimension; ++i) pos(i) = center(i) + cell_id.getID(i) * spacing(i); nodes.push_back(pos); for (UInt i = 0; i < dimension; ++i) pos(i) += spacing(i); nodes.push_back(pos); connectivity.push_back(cur_node); switch(dimension) { case 1: connectivity(cur_elem, 1) = cur_node + 1; break; case 2: pos(0) -= spacing(0); nodes.push_back(pos); pos(0) += spacing(0); pos(1) -= spacing(1); nodes.push_back(pos); connectivity(cur_elem, 1) = cur_node + 3; connectivity(cur_elem, 2) = cur_node + 1; connectivity(cur_elem, 3) = cur_node + 2; break; case 3: pos(1) -= spacing(1); pos(2) -= spacing(2); nodes.push_back(pos); pos(1) += spacing(1); nodes.push_back(pos); pos(0) -= spacing(0); nodes.push_back(pos); pos(1) -= spacing(1); pos(2) += spacing(2); nodes.push_back(pos); pos(0) += spacing(0); nodes.push_back(pos); pos(0) -= spacing(0); pos(1) += spacing(1); nodes.push_back(pos); connectivity(cur_elem, 1) = cur_node + 2; connectivity(cur_elem, 2) = cur_node + 3; connectivity(cur_elem, 3) = cur_node + 4; connectivity(cur_elem, 4) = cur_node + 5; connectivity(cur_elem, 5) = cur_node + 6; connectivity(cur_elem, 6) = cur_node + 1; connectivity(cur_elem, 7) = cur_node + 7; break; } uint_data.push_back(global_id); - } -// #if not defined(AKANTU_NDEBUG) -// mesh.addConnectivityType(_point_1); -// Array<UInt> & connectivity_pos = const_cast<Array<UInt> &>(mesh.getConnectivity(_point_1)); -// Array<UInt> & uint_data_pos = *mesh.getDataPointer<UInt>( "tag_1", _point_1); -// Array<UInt> & uint_data_pos_ghost = *mesh.getDataPointer<UInt>("tag_0", _point_1); - -// it = cells.begin(); -// global_id = 0; -// for (;it != end; ++it, ++global_id) { -// typename Cell::position_iterator cell_it = it->second.begin_pos(); -// typename Cell::const_iterator cell_it_cont = it->second.begin(); -// typename Cell::position_iterator cell_end = it->second.end_pos(); -// for (;cell_it != cell_end; ++cell_it, ++cell_it_cont) { -// nodes.push_back(*cell_it); -// connectivity_pos.push_back(nodes.getSize()-1); -// uint_data_pos.push_back(global_id); -// uint_data_pos_ghost.push_back(cell_it_cont->ghost_type==_ghost); -// } -// } -// #endif + ++global_id; + } } } // akantu #endif /* __AKANTU_AKA_GRID_DYNAMIC_HH__ */ diff --git a/src/fe_engine/element.hh b/src/fe_engine/element.hh index 3541a12e7..4ec8329b0 100644 --- a/src/fe_engine/element.hh +++ b/src/fe_engine/element.hh @@ -1,127 +1,117 @@ /** * @file element.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Sep 02 2014 * @date last modification: Sat Jul 11 2015 * * @brief Element helper class * * @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" +/* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_HH__ #define __AKANTU_ELEMENT_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ /* Element */ /* -------------------------------------------------------------------------- */ class Element; extern const Element ElementNull; class Element { - /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ - public: explicit Element(ElementType type = _not_defined, UInt element = 0, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) : type(type), element(element), ghost_type(ghost_type), kind(kind) {}; Element(const Element & element) { this->type = element.type; this->element = element.element; this->ghost_type = element.ghost_type; this->kind = element.kind; } - virtual ~Element() {}; + virtual ~Element() = default; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ - public: - inline bool operator==(const Element & elem) const { return ((element == elem.element) && (type == elem.type) && (ghost_type == elem.ghost_type) && (kind == elem.kind)); } inline bool operator!=(const Element & elem) const { return ((element != elem.element) || (type != elem.type) || (ghost_type != elem.ghost_type) || (kind != elem.kind)); } - bool operator<(const Element& rhs) const { + bool operator<(const Element & rhs) const { bool res = (rhs == ElementNull) || ((this->kind < rhs.kind) || ((this->kind == rhs.kind) && ((this->ghost_type < rhs.ghost_type) || ((this->ghost_type == rhs.ghost_type) && ((this->type < rhs.type) || ((this->type == rhs.type) && (this->element < rhs.element))))))); return res; } /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ - public: - const ElementType & getType(){return type;} const UInt & getIndex(){return element;}; const GhostType & getGhostType(){return ghost_type;} const ElementKind & getElementKind(){return kind;} /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ - public: ElementType type; UInt element; GhostType ghost_type; ElementKind kind; }; -struct CompElementLess { - bool operator() (const Element& lhs, const Element& rhs) const { - return lhs < rhs; - } -}; - } // akantu #endif /* __AKANTU_ELEMENT_HH__ */ diff --git a/src/io/mesh_io.cc b/src/io/mesh_io.cc index e4ed84cca..d2aee2f94 100644 --- a/src/io/mesh_io.cc +++ b/src/io/mesh_io.cc @@ -1,156 +1,148 @@ /** * @file mesh_io.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Mon Jun 01 2015 * * @brief common part for all mesh io 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_common.hh" #include "mesh_io.hh" - +#include "aka_common.hh" +#include "aka_zip.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ MeshIO::MeshIO() { canReadSurface = false; canReadExtendedData = false; } /* -------------------------------------------------------------------------- */ MeshIO::~MeshIO() {} /* -------------------------------------------------------------------------- */ -MeshIO * MeshIO::getMeshIO(const std::string & filename, - const MeshIOType & type) { +std::unique_ptr<MeshIO> MeshIO::getMeshIO(const std::string & filename, + const MeshIOType & type) { MeshIOType t = type; if (type == _miot_auto) { std::string::size_type idx = filename.rfind('.'); std::string ext; if (idx != std::string::npos) { ext = filename.substr(idx + 1); } if (ext == "msh") { t = _miot_gmsh; } else if (ext == "diana") { t = _miot_diana; } else if (ext == "inp") { t = _miot_abaqus; } else AKANTU_EXCEPTION("Cannot guess the type of file of " << filename << " (ext " << ext << "). " << "Please provide the MeshIOType to the read function"); } switch (t) { case _miot_gmsh: - return new MeshIOMSH(); + return std::make_unique<MeshIOMSH>(); #if defined(AKANTU_STRUCTURAL_MECHANICS) case _miot_gmsh_struct: - return new MeshIOMSHStruct(); + return std::make_unique<MeshIOMSHStruct>(); #endif case _miot_diana: - return new MeshIODiana(); + return std::make_unique<MeshIODiana>(); case _miot_abaqus: - return new MeshIOAbaqus(); + return std::make_unique<MeshIOAbaqus>(); default: - return NULL; + return nullptr; } } /* -------------------------------------------------------------------------- */ void MeshIO::read(const std::string & filename, Mesh & mesh, const MeshIOType & type) { - MeshIO * mesh_io = getMeshIO(filename, type); + std::unique_ptr<MeshIO> mesh_io = getMeshIO(filename, type); mesh_io->read(filename, mesh); - delete mesh_io; } /* -------------------------------------------------------------------------- */ void MeshIO::write(const std::string & filename, Mesh & mesh, const MeshIOType & type) { - MeshIO * mesh_io = getMeshIO(filename, type); + std::unique_ptr<MeshIO> mesh_io = getMeshIO(filename, type); mesh_io->write(filename, mesh); - delete mesh_io; } /* -------------------------------------------------------------------------- */ void MeshIO::constructPhysicalNames(const std::string & tag_name, Mesh & mesh) { - if (!phys_name_map.empty()) { for (Mesh::type_iterator type_it = mesh.firstType(); type_it != mesh.lastType(); ++type_it) { - Array<std::string> * name_vec = + auto & name_vec = mesh.getDataPointer<std::string>("physical_names", *type_it); - const Array<UInt> & tags_vec = mesh.getData<UInt>(tag_name, *type_it); + const auto & tags_vec = mesh.getData<UInt>(tag_name, *type_it); - for (UInt i(0); i < tags_vec.getSize(); i++) { - std::map<UInt, std::string>::const_iterator map_it = - phys_name_map.find(tags_vec(i)); + for (auto pair : zip(tags_vec, name_vec)) { + auto tag = std::get<0>(pair); + auto & name = std::get<1>(pair); + auto map_it = phys_name_map.find(tag); if (map_it == phys_name_map.end()) { std::stringstream sstm; - sstm << tags_vec(i); - name_vec->operator()(i) = sstm.str(); + sstm << tag; + + name = sstm.str(); } else { - name_vec->operator()(i) = map_it->second; + name = map_it->second; } } } } } /* -------------------------------------------------------------------------- */ - void MeshIO::printself(std::ostream & stream, int indent) const { - std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; if (phys_name_map.size()) { - stream << space << "Physical map:" << std::endl; - - std::map<UInt, std::string>::const_iterator it = phys_name_map.begin(); - std::map<UInt, std::string>::const_iterator end = phys_name_map.end(); - - for (; it != end; ++it) { - stream << space << it->first << ": " << it->second << std::endl; + for (auto & pair : phys_name_map) { + stream << space << pair.first << ": " << pair.second << std::endl; } } } /* -------------------------------------------------------------------------- */ -} // akantu +} // namespace akantu diff --git a/src/io/mesh_io.hh b/src/io/mesh_io.hh index 680d7d418..5e4860613 100644 --- a/src/io/mesh_io.hh +++ b/src/io/mesh_io.hh @@ -1,118 +1,118 @@ /** * @file mesh_io.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Mon Jun 01 2015 * * @brief interface of a mesh io class, reader and writer * * @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_MESH_IO_HH__ #define __AKANTU_MESH_IO_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_accessor.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class MeshIO { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshIO(); virtual ~MeshIO(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void read(const std::string & filename, Mesh & mesh, const MeshIOType & type); void write(const std::string & filename, Mesh & mesh, const MeshIOType & type); /// read a mesh from the file virtual void read(__attribute__((unused)) const std::string & filename, __attribute__((unused)) Mesh & mesh) {} /// write a mesh to a file virtual void write(__attribute__((unused)) const std::string & filename, __attribute__((unused)) const Mesh & mesh) {} /// function to request the manual construction of the physical names maps virtual void constructPhysicalNames(const std::string & tag_name, Mesh & mesh); /// method to permit to be printed to a generic stream virtual void printself(std::ostream & stream, int indent = 0) const; /// static contruction of a meshio object - static MeshIO * getMeshIO(const std::string & filename, - const MeshIOType & type); + static std::unique_ptr<MeshIO> getMeshIO(const std::string & filename, + const MeshIOType & type); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: std::map<UInt, std::string> & getPhysicalNameMap() { return phys_name_map; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: bool canReadSurface; bool canReadExtendedData; /// correspondance between a tag and physical names (if applicable) std::map<UInt, std::string> phys_name_map; }; /* -------------------------------------------------------------------------- */ inline std::ostream & operator<<(std::ostream & stream, const MeshIO & _this) { _this.printself(stream); return stream; } /* -------------------------------------------------------------------------- */ -} // akantu +} // namespace akantu -#include "mesh_io_msh.hh" -#include "mesh_io_diana.hh" #include "mesh_io_abaqus.hh" +#include "mesh_io_diana.hh" +#include "mesh_io_msh.hh" #if defined(AKANTU_STRUCTURAL_MECHANICS) #include "mesh_io_msh_struct.hh" #endif #endif /* __AKANTU_MESH_IO_HH__ */ diff --git a/src/io/mesh_io/mesh_io_abaqus.cc b/src/io/mesh_io/mesh_io_abaqus.cc index 2caf717c8..7c3461a79 100644 --- a/src/io/mesh_io/mesh_io_abaqus.cc +++ b/src/io/mesh_io/mesh_io_abaqus.cc @@ -1,483 +1,475 @@ /** * @file mesh_io_abaqus.cc * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jan 04 2013 * @date last modification: Fri Dec 11 2015 * * @brief read a mesh from an abaqus input file * * @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/>. * */ /* -------------------------------------------------------------------------- */ // std library header files #include <fstream> // akantu header files #include "mesh_io_abaqus.hh" #include "mesh.hh" #include "mesh_utils.hh" #include "element_group.hh" #include "node_group.hh" #if defined(__INTEL_COMPILER) //#pragma warning ( disable : 383 ) #elif defined (__clang__) // test clang to be sure that when we test for gnu it is only gnu #elif (defined(__GNUC__) || defined(__GNUG__)) # define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) # if GCC_VERSION > 40600 # pragma GCC diagnostic push # endif # pragma GCC diagnostic ignored "-Wunused-local-typedefs" #endif /* -------------------------------------------------------------------------- */ #include <boost/config/warning_disable.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ MeshIOAbaqus::MeshIOAbaqus() {} /* -------------------------------------------------------------------------- */ MeshIOAbaqus::~MeshIOAbaqus() {} /* -------------------------------------------------------------------------- */ namespace spirit = boost::spirit; namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; namespace lbs = boost::spirit::qi::labels; namespace phx = boost::phoenix; /* -------------------------------------------------------------------------- */ void element_read(Mesh & mesh, const ElementType & type, UInt id, const std::vector<Int> & conn, const std::map<UInt, UInt> & nodes_mapping, std::map<UInt, Element> & elements_mapping) { Vector<UInt> tmp_conn(Mesh::getNbNodesPerElement(type)); AKANTU_DEBUG_ASSERT(conn.size() == tmp_conn.size(), "The nodes in the Abaqus file have too many coordinates" << " for the mesh you try to fill."); mesh.addConnectivityType(type); Array<UInt> & connectivity = mesh.getConnectivity(type); UInt i = 0; for (std::vector<Int>::const_iterator it = conn.begin(); it != conn.end(); ++it) { std::map<UInt, UInt>::const_iterator nit = nodes_mapping.find(*it); AKANTU_DEBUG_ASSERT(nit != nodes_mapping.end(), "There is an unknown node in the connectivity."); tmp_conn[i++] = nit->second; } Element el(type, connectivity.getSize()); elements_mapping[id] = el; connectivity.push_back(tmp_conn); } void node_read(Mesh & mesh, UInt id, const std::vector<Real> & pos, std::map<UInt, UInt> & nodes_mapping) { Vector<Real> tmp_pos(mesh.getSpatialDimension()); UInt i = 0; for (std::vector<Real>::const_iterator it = pos.begin(); it != pos.end() || i < mesh.getSpatialDimension(); ++it) tmp_pos[i++] = *it; nodes_mapping[id] = mesh.getNbNodes(); mesh.getNodes().push_back(tmp_pos); } /* ------------------------------------------------------------------------ */ void add_element_to_group(ElementGroup * el_grp, UInt element, const std::map<UInt, Element> & elements_mapping) { std::map<UInt, Element>::const_iterator eit = elements_mapping.find(element); AKANTU_DEBUG_ASSERT(eit != elements_mapping.end(), "There is an unknown element (" << element << ") in the in the ELSET " << el_grp->getName() << "."); el_grp->add(eit->second, true, false); } ElementGroup * element_group_create(Mesh & mesh, const ID & name) { Mesh::element_group_iterator eg_it = mesh.element_group_find(name); if (eg_it != mesh.element_group_end()) { return eg_it->second; } else { return &mesh.createElementGroup(name, _all_dimensions); } } NodeGroup * node_group_create(Mesh & mesh, const ID & name) { Mesh::node_group_iterator ng_it = mesh.node_group_find(name); if (ng_it != mesh.node_group_end()) { return ng_it->second; } else { return &mesh.createNodeGroup(name, mesh.getSpatialDimension()); } } void add_node_to_group(NodeGroup * node_grp, UInt node, const std::map<UInt, UInt> & nodes_mapping) { std::map<UInt, UInt>::const_iterator nit = nodes_mapping.find(node); AKANTU_DEBUG_ASSERT(nit != nodes_mapping.end(), "There is an unknown node in the in the NSET " << node_grp->getName() << "."); node_grp->add(nit->second, false); } void optimize_group(NodeGroup * grp) { grp->optimize(); } void optimize_element_group(ElementGroup * grp) { grp->optimize(); } /* -------------------------------------------------------------------------- */ template <class Iterator> struct AbaqusSkipper : qi::grammar<Iterator> { AbaqusSkipper() : AbaqusSkipper::base_type(skip, "abaqus_skipper") { /* clang-format off */ skip = (ascii::space - spirit::eol) | "**" >> *(qi::char_ - spirit::eol) >> spirit::eol ; /* clang-format on */ } qi::rule<Iterator> skip; }; /* -------------------------------------------------------------------------- */ template <class Iterator, typename Skipper = AbaqusSkipper<Iterator> > struct AbaqusMeshGrammar : qi::grammar<Iterator, void(), Skipper> { public: AbaqusMeshGrammar(Mesh & mesh) : AbaqusMeshGrammar::base_type(start, "abaqus_mesh_reader"), mesh(mesh) { /* clang-format off */ start = *( (qi::char_('*') > ( (qi::no_case[ qi::lit("node output") ] > any_section) | (qi::no_case[ qi::lit("element output") ] > any_section) | (qi::no_case[ qi::lit("node") ] > nodes) | (qi::no_case[ qi::lit("element") ] > elements) | (qi::no_case[ qi::lit("heading") ] > header) | (qi::no_case[ qi::lit("elset") ] > elements_set) | (qi::no_case[ qi::lit("nset") ] > nodes_set) | (qi::no_case[ qi::lit("material") ] > material) | (keyword > any_section) ) ) | spirit::eol ) ; header = spirit::eol > *any_line ; nodes = *(qi::char_(',') >> option) >> spirit::eol >> *( (qi::int_ > node_position) [ phx::bind(&node_read, phx::ref(mesh), lbs::_1, lbs::_2, phx::ref(abaqus_nodes_to_akantu)) ] >> spirit::eol ) ; elements = ( ( qi::char_(',') >> qi::no_case[qi::lit("type")] >> '=' >> abaqus_element_type [ lbs::_a = lbs::_1 ] ) ^ *(qi::char_(',') >> option) ) >> spirit::eol >> *( (qi::int_ > connectivity) [ phx::bind(&element_read, phx::ref(mesh), lbs::_a, lbs::_1, lbs::_2, phx::cref(abaqus_nodes_to_akantu), phx::ref(abaqus_elements_to_akantu)) ] >> spirit::eol ) ; elements_set = ( ( ( qi::char_(',') >> qi::no_case[ qi::lit("elset") ] >> '=' >> value [ lbs::_a = phx::bind<ElementGroup *>(&element_group_create, phx::ref(mesh), lbs::_1) ] ) ^ *(qi::char_(',') >> option) ) >> spirit::eol >> qi::skip (qi::char_(',') | qi::space) [ +(qi::int_ [ phx::bind(&add_element_to_group, lbs::_a, lbs::_1, phx::cref(abaqus_elements_to_akantu) ) ] ) ] ) [ phx::bind(&optimize_element_group, lbs::_a) ] ; nodes_set = ( ( ( qi::char_(',') >> qi::no_case[ qi::lit("nset") ] >> '=' >> value [ lbs::_a = phx::bind<NodeGroup *>(&node_group_create, phx::ref(mesh), lbs::_1) ] ) ^ *(qi::char_(',') >> option) ) >> spirit::eol >> qi::skip (qi::char_(',') | qi::space) [ +(qi::int_ [ phx::bind(&add_node_to_group, lbs::_a, lbs::_1, phx::cref(abaqus_nodes_to_akantu) ) ] ) ] ) [ phx::bind(&optimize_group, lbs::_a) ] ; material = ( ( qi::char_(',') >> qi::no_case[ qi::lit("name") ] >> '=' >> value [ phx::push_back(phx::ref(material_names), lbs::_1) ] ) ^ *(qi::char_(',') >> option) ) >> spirit::eol; ; node_position = +(qi::char_(',') > real [ phx::push_back(lbs::_val, lbs::_1) ]) ; connectivity = +(qi::char_(',') > qi::int_ [ phx::push_back(lbs::_val, lbs::_1) ]) ; any_section = *(qi::char_(',') >> option) > spirit::eol > *any_line ; any_line = *(qi::char_ - spirit::eol - qi::char_('*')) >> spirit::eol ; keyword = qi::lexeme[ +(qi::char_ - (qi::char_('*') | spirit::eol)) ] ; option = key > -( '=' >> value ); key = qi::char_("a-zA-Z_") >> *(qi::char_("a-zA-Z_0-9") | qi::char_('-')) ; value = key.alias() ; BOOST_SPIRIT_DEBUG_NODE(start); abaqus_element_type.add #if defined(AKANTU_STRUCTURAL_MECHANICS) ("BE21" , _bernoulli_beam_2) ("BE31" , _bernoulli_beam_3) #endif ("T3D2" , _segment_2) // Gmsh generates this elements ("T3D3" , _segment_3) // Gmsh generates this elements ("CPE3" , _triangle_3) ("CPS3" , _triangle_3) ("DC2D3" , _triangle_3) ("CPE6" , _triangle_6) ("CPS6" , _triangle_6) ("DC2D6" , _triangle_6) ("CPE4" , _quadrangle_4) ("CPS4" , _quadrangle_4) ("DC2D4" , _quadrangle_4) ("CPE8" , _quadrangle_8) ("CPS8" , _quadrangle_8) ("DC2D8" , _quadrangle_8) ("C3D4" , _tetrahedron_4) ("DC3D4" , _tetrahedron_4) ("C3D8" , _hexahedron_8) ("C3D8R" , _hexahedron_8) ("DC3D8" , _hexahedron_8) ("C3D10" , _tetrahedron_10) ("DC3D10", _tetrahedron_10); #if !defined(AKANTU_NDEBUG) && defined(AKANTU_CORE_CXX_11) qi::on_error<qi::fail>(start, error_handler(lbs::_4, lbs::_3, lbs::_2)); #endif start .name("abaqus-start-rule"); connectivity .name("abaqus-connectivity"); node_position .name("abaqus-nodes-position"); nodes .name("abaqus-nodes"); any_section .name("abaqus-any_section"); header .name("abaqus-header"); material .name("abaqus-material"); elements .name("abaqus-elements"); elements_set .name("abaqus-elements-set"); nodes_set .name("abaqus-nodes-set"); key .name("abaqus-key"); value .name("abaqus-value"); option .name("abaqus-option"); keyword .name("abaqus-keyword"); any_line .name("abaqus-any-line"); abaqus_element_type.name("abaqus-element-type"); /* clang-format on */ } public: AKANTU_GET_MACRO(MaterialNames, material_names, const std::vector<std::string> &); /* ------------------------------------------------------------------------ */ /* Rules */ /* ------------------------------------------------------------------------ */ private: qi::rule<Iterator, void(), Skipper> start; qi::rule<Iterator, std::vector<int>(), Skipper> connectivity; qi::rule<Iterator, std::vector<Real>(), Skipper> node_position; qi::rule<Iterator, void(), Skipper> nodes, any_section, header, material; qi::rule<Iterator, void(), qi::locals<ElementType>, Skipper> elements; qi::rule<Iterator, void(), qi::locals<ElementGroup *>, Skipper> elements_set; qi::rule<Iterator, void(), qi::locals<NodeGroup *>, Skipper> nodes_set; qi::rule<Iterator, std::string(), Skipper> key, value, option, keyword, any_line; qi::real_parser<Real, qi::real_policies<Real> > real; qi::symbols<char, ElementType> abaqus_element_type; /* ------------------------------------------------------------------------ */ /* Mambers */ /* ------------------------------------------------------------------------ */ private: /// reference to the mesh to read Mesh & mesh; /// correspondance between the numbering of nodes in the abaqus file and in /// the akantu mesh std::map<UInt, UInt> abaqus_nodes_to_akantu; /// correspondance between the element number in the abaqus file and the /// Element in the akantu mesh std::map<UInt, Element> abaqus_elements_to_akantu; /// list of the material names std::vector<std::string> material_names; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void MeshIOAbaqus::read(const std::string & filename, Mesh & mesh) { namespace spirit = boost::spirit; namespace qi = boost::spirit::qi; namespace lbs = boost::spirit::qi::labels; namespace ascii = boost::spirit::ascii; namespace phx = boost::phoenix; std::ifstream infile; infile.open(filename.c_str()); if (!infile.good()) { AKANTU_DEBUG_ERROR("Cannot open file " << filename); } std::string storage; // We will read the contents here. infile.unsetf(std::ios::skipws); // No white space skipping! std::copy(std::istream_iterator<char>(infile), std::istream_iterator<char>(), std::back_inserter(storage)); typedef std::string::const_iterator iterator_t; typedef AbaqusSkipper<iterator_t> skipper; typedef AbaqusMeshGrammar<iterator_t, skipper> grammar; grammar g(mesh); skipper ws; iterator_t iter = storage.begin(); iterator_t end = storage.end(); qi::phrase_parse(iter, end, g, ws); - std::vector<std::string>::const_iterator mnit = g.getMaterialNames().begin(); - std::vector<std::string>::const_iterator mnend = g.getMaterialNames().end(); - MeshAccessor mesh_accessor(mesh); - for (; mnit != mnend; ++mnit) { - Mesh::element_group_iterator eg_it = mesh.element_group_find(*mnit); - ElementGroup & eg = *eg_it->second; + for (auto & mat_name : g.getMaterialNames()) { + auto eg_it = mesh.element_group_find(mat_name); + auto & eg = *eg_it->second; if (eg_it != mesh.element_group_end()) { - ElementGroup::type_iterator tit = eg.firstType(); - ElementGroup::type_iterator tend = eg.lastType(); - - for (; tit != tend; ++tit) { + for (auto & type : eg.elementTypes()) { Array<std::string> & abaqus_material = - mesh_accessor.getData<std::string>("abaqus_material", *tit); + mesh_accessor.getData<std::string>("abaqus_material", type); - ElementGroup::const_element_iterator eit = eg.element_begin(*tit); - ElementGroup::const_element_iterator eend = eg.element_end(*tit); - for (; eit != eend; ++eit) { - abaqus_material(*eit) = *mnit; + for (auto elem : eg.getElements(type)) { + abaqus_material(elem) = mat_name; } } } } mesh_accessor.setNbGlobalNodes(mesh.getNodes().getSize()); MeshUtils::fillElementToSubElementsData(mesh); } } // akantu diff --git a/src/io/mesh_io/mesh_io_diana.cc b/src/io/mesh_io/mesh_io_diana.cc index 2014b6b92..b75e511fd 100644 --- a/src/io/mesh_io/mesh_io_diana.cc +++ b/src/io/mesh_io/mesh_io_diana.cc @@ -1,587 +1,604 @@ /** * @file mesh_io_diana.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Alodie Schneuwly <alodie.schneuwly@epfl.ch> * * @date creation: Sat Mar 26 2011 * @date last modification: Thu Jan 21 2016 * * @brief handles diana meshes * * @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 <fstream> #include <iostream> /* -------------------------------------------------------------------------- */ +#include "element_group.hh" #include "mesh_io_diana.hh" #include "mesh_utils.hh" -#include "element_group.hh" /* -------------------------------------------------------------------------- */ #include <string.h> /* -------------------------------------------------------------------------- */ #include <stdio.h> namespace akantu { /* -------------------------------------------------------------------------- */ /* Methods Implentations */ /* -------------------------------------------------------------------------- */ MeshIODiana::MeshIODiana() { canReadSurface = true; canReadExtendedData = true; _diana_to_akantu_element_types["T9TM"] = _triangle_3; _diana_to_akantu_element_types["CT6CM"] = _triangle_6; _diana_to_akantu_element_types["Q12TM"] = _quadrangle_4; _diana_to_akantu_element_types["CQ8CM"] = _quadrangle_8; _diana_to_akantu_element_types["TP18L"] = _pentahedron_6; _diana_to_akantu_element_types["CTP45"] = _pentahedron_15; _diana_to_akantu_element_types["TE12L"] = _tetrahedron_4; _diana_to_akantu_element_types["HX24L"] = _hexahedron_8; _diana_to_akantu_element_types["CHX60"] = _hexahedron_20; _diana_to_akantu_mat_prop["YOUNG"] = "E"; _diana_to_akantu_mat_prop["DENSIT"] = "rho"; _diana_to_akantu_mat_prop["POISON"] = "nu"; std::map<std::string, ElementType>::iterator it; for (it = _diana_to_akantu_element_types.begin(); it != _diana_to_akantu_element_types.end(); ++it) { UInt nb_nodes = Mesh::getNbNodesPerElement(it->second); UInt * tmp = new UInt[nb_nodes]; for (UInt i = 0; i < nb_nodes; ++i) { tmp[i] = i; } switch (it->second) { case _tetrahedron_10: tmp[8] = 9; tmp[9] = 8; break; case _pentahedron_15: tmp[0] = 2; tmp[1] = 8; tmp[2] = 0; tmp[3] = 6; tmp[4] = 1; tmp[5] = 7; tmp[6] = 11; tmp[7] = 9; tmp[8] = 10; tmp[9] = 5; tmp[10] = 14; tmp[11] = 3; tmp[12] = 12; tmp[13] = 4; tmp[14] = 13; break; case _hexahedron_20: tmp[0] = 5; tmp[1] = 16; tmp[2] = 4; tmp[3] = 19; tmp[4] = 7; tmp[5] = 18; tmp[6] = 6; tmp[7] = 17; tmp[8] = 13; tmp[9] = 12; tmp[10] = 15; tmp[11] = 14; tmp[12] = 1; tmp[13] = 8; tmp[14] = 0; tmp[15] = 11; tmp[16] = 3; tmp[17] = 10; tmp[18] = 2; tmp[19] = 9; break; default: // nothing to change break; } _read_order[it->second] = tmp; } } /* -------------------------------------------------------------------------- */ MeshIODiana::~MeshIODiana() {} /* -------------------------------------------------------------------------- */ inline void my_getline(std::ifstream & infile, std::string & line) { std::getline(infile, line); // read the line size_t pos = line.find("\r"); /// remove the extra \r if needed line = line.substr(0, pos); } /* -------------------------------------------------------------------------- */ void MeshIODiana::read(const std::string & filename, Mesh & mesh) { AKANTU_DEBUG_IN(); MeshAccessor mesh_accessor(mesh); std::ifstream infile; infile.open(filename.c_str()); std::string line; UInt first_node_number = std::numeric_limits<UInt>::max(); diana_element_number_to_elements.clear(); - if (!infile.good()) { AKANTU_DEBUG_ERROR("Cannot open file " << filename); } + if (!infile.good()) { + AKANTU_DEBUG_ERROR("Cannot open file " << filename); + } while (infile.good()) { my_getline(infile, line); /// read all nodes if (line == "'COORDINATES'") { line = readCoordinates(infile, mesh, first_node_number); } /// read all elements if (line == "'ELEMENTS'") { line = readElements(infile, mesh, first_node_number); } /// read the material properties and write a .dat file - if (line == "'MATERIALS'") { line = readMaterial(infile, filename); } + if (line == "'MATERIALS'") { + line = readMaterial(infile, filename); + } /// read the material properties and write a .dat file if (line == "'GROUPS'") { line = readGroups(infile, mesh, first_node_number); } } infile.close(); mesh_accessor.setNbGlobalNodes(mesh.getNbNodes()); MeshUtils::fillElementToSubElementsData(mesh); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshIODiana::write(__attribute__((unused)) const std::string & filename, __attribute__((unused)) const Mesh & mesh) { AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readCoordinates(std::ifstream & infile, Mesh & mesh, UInt & first_node_number) { AKANTU_DEBUG_IN(); MeshAccessor mesh_accessor(mesh); Array<Real> & nodes = mesh_accessor.getNodes(); std::string line; UInt index; Vector<Real> coord(3); do { my_getline(infile, line); - if ("'ELEMENTS'" == line) break; + if ("'ELEMENTS'" == line) + break; std::stringstream sstr_node(line); sstr_node >> index >> coord(0) >> coord(1) >> coord(2); first_node_number = first_node_number < index ? first_node_number : index; nodes.push_back(coord); } while (true); AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ UInt MeshIODiana::readInterval(std::stringstream & line, std::set<UInt> & interval) { UInt first; line >> first; - if (line.fail()) { return 0; } + if (line.fail()) { + return 0; + } interval.insert(first); UInt second; int dash; dash = line.get(); if (dash == '-') { line >> second; interval.insert(second); return 2; } if (line.fail()) line.clear(std::ios::eofbit); // in case of get at end of the line else line.unget(); return 1; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readGroups(std::ifstream & infile, Mesh & mesh, UInt first_node_number) { AKANTU_DEBUG_IN(); std::string line; my_getline(infile, line); bool reading_nodes_group = false; while (line != "'SUPPORTS'") { if (line == "NODES") { reading_nodes_group = true; my_getline(infile, line); } if (line == "ELEMEN") { reading_nodes_group = false; my_getline(infile, line); } std::stringstream * str = new std::stringstream(line); UInt id; std::string name; char c; *str >> id >> name >> c; Array<UInt> * list_ids = new Array<UInt>(0, 1, name); UInt s = 1; bool end = false; while (!end) { while (!str->eof() && s != 0) { std::set<UInt> interval; s = readInterval(*str, interval); std::set<UInt>::iterator it = interval.begin(); - if (s == 1) list_ids->push_back(*it); + if (s == 1) + list_ids->push_back(*it); if (s == 2) { UInt first = *it; ++it; UInt second = *it; for (UInt i = first; i <= second; ++i) { list_ids->push_back(i); } } } if (str->fail()) end = true; else { my_getline(infile, line); delete str; str = new std::stringstream(line); } } delete str; if (reading_nodes_group) { NodeGroup & ng = mesh.createNodeGroup(name); for (UInt i = 0; i < list_ids->getSize(); ++i) { - UInt node = (*list_ids)(i) - first_node_number; + UInt node = (*list_ids)(i)-first_node_number; ng.add(node, false); } delete list_ids; } else { ElementGroup & eg = mesh.createElementGroup(name); for (UInt i = 0; i < list_ids->getSize(); ++i) { - Element & elem = diana_element_number_to_elements[ (*list_ids)(i)]; - if (elem.type != _not_defined) eg.add(elem, false, false); + Element & elem = diana_element_number_to_elements[(*list_ids)(i)]; + if (elem.type != _not_defined) + eg.add(elem, false, false); } eg.optimize(); delete list_ids; } my_getline(infile, line); } AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readElements(std::ifstream & infile, Mesh & mesh, UInt first_node_number) { AKANTU_DEBUG_IN(); std::string line; my_getline(infile, line); if ("CONNECTIVITY" == line) { line = readConnectivity(infile, mesh, first_node_number); } /// read the line corresponding to the materials - if ("MATERIALS" == line) { line = readMaterialElement(infile, mesh); } + if ("MATERIALS" == line) { + line = readMaterialElement(infile, mesh); + } AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readConnectivity(std::ifstream & infile, Mesh & mesh, UInt first_node_number) { AKANTU_DEBUG_IN(); MeshAccessor mesh_accessor(mesh); Int index; std::string lline; std::string diana_type; ElementType akantu_type, akantu_type_old = _not_defined; Array<UInt> * connectivity = NULL; UInt node_per_element = 0; Element elem; UInt * read_order = NULL; while (1) { my_getline(infile, lline); // std::cerr << lline << std::endl; std::stringstream sstr_elem(lline); - if (lline == "MATERIALS") break; + if (lline == "MATERIALS") + break; /// traiter les coordonnees sstr_elem >> index; sstr_elem >> diana_type; akantu_type = _diana_to_akantu_element_types[diana_type]; - if (akantu_type == _not_defined) continue; + if (akantu_type == _not_defined) + continue; if (akantu_type != akantu_type_old) { connectivity = &(mesh_accessor.getConnectivity(akantu_type)); node_per_element = connectivity->getNbComponent(); akantu_type_old = akantu_type; read_order = _read_order[akantu_type]; } Vector<UInt> local_connect(node_per_element); // used if element is written on two lines UInt j_last = 0; for (UInt j = 0; j < node_per_element; ++j) { UInt node_index; sstr_elem >> node_index; // check s'il y a pas plus rien après un certain point if (sstr_elem.fail()) { sstr_elem.clear(); sstr_elem.ignore(); break; } node_index -= first_node_number; local_connect(read_order[j]) = node_index; j_last = j; } // check if element is written in two lines if (j_last != (node_per_element - 1)) { // if this is the case, read on more line my_getline(infile, lline); std::stringstream sstr_elem(lline); for (UInt j = (j_last + 1); j < node_per_element; ++j) { UInt node_index; sstr_elem >> node_index; node_index -= first_node_number; local_connect(read_order[j]) = node_index; } } connectivity->push_back(local_connect); elem.type = akantu_type; elem.element = connectivity->getSize() - 1; diana_element_number_to_elements[index] = elem; akantu_number_to_diana_number[elem] = index; } AKANTU_DEBUG_OUT(); return lline; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readMaterialElement(std::ifstream & infile, Mesh & mesh) { AKANTU_DEBUG_IN(); std::string line; std::stringstream sstr_tag_name; sstr_tag_name << "tag_" << 0; Mesh::type_iterator it = mesh.firstType(); Mesh::type_iterator end = mesh.lastType(); for (; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it); mesh.getDataPointer<UInt>("material", *it, _not_ghost, 1) - ->resize(nb_element); + .resize(nb_element); } my_getline(infile, line); while (line != "'MATERIALS'") { line = line.substr(line.find('/') + 1, std::string::npos); // erase the first slash / of the line char tutu[250]; strcpy(tutu, line.c_str()); AKANTU_DEBUG_WARNING("reading line " << line); Array<UInt> temp_id(0, 2); UInt mat; while (true) { std::stringstream sstr_intervals_elements(line); Vector<UInt> id(2); char temp; while (sstr_intervals_elements.good()) { sstr_intervals_elements >> id(0) >> temp >> id(1); // >> "/" >> mat; - if (!sstr_intervals_elements.fail()) temp_id.push_back(id); + if (!sstr_intervals_elements.fail()) + temp_id.push_back(id); } if (sstr_intervals_elements.fail()) { sstr_intervals_elements.clear(); sstr_intervals_elements.ignore(); sstr_intervals_elements >> mat; break; } my_getline(infile, line); } // loop over elements // UInt * temp_id_val = temp_id.storage(); for (UInt i = 0; i < temp_id.getSize(); ++i) for (UInt j = temp_id(i, 0); j <= temp_id(i, 1); ++j) { Element & element = diana_element_number_to_elements[j]; - if (element.type == _not_defined) continue; + if (element.type == _not_defined) + continue; UInt elem = element.element; ElementType type = element.type; Array<UInt> & data = - *(mesh.getDataPointer<UInt>("material", type, _not_ghost)); + mesh.getDataPointer<UInt>("material", type, _not_ghost); data(elem) = mat; } my_getline(infile, line); } AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readMaterial(std::ifstream & infile, const std::string & filename) { AKANTU_DEBUG_IN(); std::stringstream mat_file_name; mat_file_name << "material_" << filename; std::ofstream material_file; material_file.open(mat_file_name.str().c_str()); // mat_file_name.str()); UInt mat_index; std::string line; bool first_mat = true; bool end = false; UInt mat_id = 0; typedef std::map<std::string, Real> MatProp; MatProp mat_prop; do { my_getline(infile, line); std::stringstream sstr_material(line); if (("'GROUPS'" == line) || ("'END'" == line)) { if (!mat_prop.empty()) { material_file << "material elastic [" << std::endl; material_file << "\tname = material" << ++mat_id << std::endl; for (MatProp::iterator it = mat_prop.begin(); it != mat_prop.end(); ++it) material_file << "\t" << it->first << " = " << it->second << std::endl; material_file << "]" << std::endl; mat_prop.clear(); } end = true; } else { /// traiter les caractéristiques des matériaux sstr_material >> mat_index; if (!sstr_material.fail()) { if (!first_mat) { if (!mat_prop.empty()) { material_file << "material elastic [" << std::endl; material_file << "\tname = material" << ++mat_id << std::endl; for (MatProp::iterator it = mat_prop.begin(); it != mat_prop.end(); ++it) material_file << "\t" << it->first << " = " << it->second << std::endl; material_file << "]" << std::endl; mat_prop.clear(); } } first_mat = false; - } else { sstr_material.clear(); } + } else { + sstr_material.clear(); + } std::string prop_name; sstr_material >> prop_name; std::map<std::string, std::string>::iterator it; it = _diana_to_akantu_mat_prop.find(prop_name); if (it != _diana_to_akantu_mat_prop.end()) { Real value; sstr_material >> value; mat_prop[it->second] = value; } else { AKANTU_DEBUG_INFO("In material reader, property " << prop_name << "not recognized"); } } } while (!end); AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ -} // akantu +} // namespace akantu diff --git a/src/io/mesh_io/mesh_io_msh.cc b/src/io/mesh_io/mesh_io_msh.cc index 44990b5b2..a2efe333e 100644 --- a/src/io/mesh_io/mesh_io_msh.cc +++ b/src/io/mesh_io/mesh_io_msh.cc @@ -1,981 +1,981 @@ /** * @file mesh_io_msh.cc * * @author Dana Christen <dana.christen@gmail.com> * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Jan 21 2016 * * @brief Read/Write for MSH files generated by gmsh * * @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/>. * */ /* ----------------------------------------------------------------------------- Version (Legacy) 1.0 $NOD number-of-nodes node-number x-coord y-coord z-coord ... $ENDNOD $ELM number-of-elements elm-number elm-type reg-phys reg-elem number-of-nodes node-number-list ... $ENDELM ----------------------------------------------------------------------------- Version 2.1 $MeshFormat version-number file-type data-size $EndMeshFormat $Nodes number-of-nodes node-number x-coord y-coord z-coord ... $EndNodes $Elements number-of-elements elm-number elm-type number-of-tags < tag > ... node-number-list ... $EndElements $PhysicalNames number-of-names physical-dimension physical-number "physical-name" ... $EndPhysicalNames $NodeData number-of-string-tags < "string-tag" > ... number-of-real-tags < real-tag > ... number-of-integer-tags < integer-tag > ... node-number value ... ... $EndNodeData $ElementData number-of-string-tags < "string-tag" > ... number-of-real-tags < real-tag > ... number-of-integer-tags < integer-tag > ... elm-number value ... ... $EndElementData $ElementNodeData number-of-string-tags < "string-tag" > ... number-of-real-tags < real-tag > ... number-of-integer-tags < integer-tag > ... elm-number number-of-nodes-per-element value ... ... $ElementEndNodeData ----------------------------------------------------------------------------- elem-type 1: 2-node line. 2: 3-node triangle. 3: 4-node quadrangle. 4: 4-node tetrahedron. 5: 8-node hexahedron. 6: 6-node prism. 7: 5-node pyramid. 8: 3-node second order line 9: 6-node second order triangle 10: 9-node second order quadrangle 11: 10-node second order tetrahedron 12: 27-node second order hexahedron 13: 18-node second order prism 14: 14-node second order pyramid 15: 1-node point. 16: 8-node second order quadrangle 17: 20-node second order hexahedron 18: 15-node second order prism 19: 13-node second order pyramid 20: 9-node third order incomplete triangle 21: 10-node third order triangle 22: 12-node fourth order incomplete triangle 23: 15-node fourth order triangle 24: 15-node fifth order incomplete triangle 25: 21-node fifth order complete triangle 26: 4-node third order edge 27: 5-node fourth order edge 28: 6-node fifth order edge 29: 20-node third order tetrahedron 30: 35-node fourth order tetrahedron 31: 56-node fifth order tetrahedron -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ #include "mesh_io.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ // The boost spirit is a work on the way it does not compile so I kept the // current code. The current code does not handle files generated on Windows // <CRLF> // #include <boost/config/warning_disable.hpp> // #include <boost/spirit/include/qi.hpp> // #include <boost/spirit/include/phoenix_core.hpp> // #include <boost/spirit/include/phoenix_fusion.hpp> // #include <boost/spirit/include/phoenix_object.hpp> // #include <boost/spirit/include/phoenix_container.hpp> // #include <boost/spirit/include/phoenix_operator.hpp> // #include <boost/spirit/include/phoenix_bind.hpp> // #include <boost/spirit/include/phoenix_stl.hpp> /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ /* Methods Implentations */ /* -------------------------------------------------------------------------- */ MeshIOMSH::MeshIOMSH() { canReadSurface = true; canReadExtendedData = true; _msh_nodes_per_elem[_msh_not_defined] = 0; _msh_nodes_per_elem[_msh_segment_2] = 2; _msh_nodes_per_elem[_msh_triangle_3] = 3; _msh_nodes_per_elem[_msh_quadrangle_4] = 4; _msh_nodes_per_elem[_msh_tetrahedron_4] = 4; _msh_nodes_per_elem[_msh_hexahedron_8] = 8; _msh_nodes_per_elem[_msh_prism_1] = 6; _msh_nodes_per_elem[_msh_pyramid_1] = 1; _msh_nodes_per_elem[_msh_segment_3] = 3; _msh_nodes_per_elem[_msh_triangle_6] = 6; _msh_nodes_per_elem[_msh_quadrangle_9] = 9; _msh_nodes_per_elem[_msh_tetrahedron_10] = 10; _msh_nodes_per_elem[_msh_hexahedron_27] = 27; _msh_nodes_per_elem[_msh_hexahedron_20] = 20; _msh_nodes_per_elem[_msh_prism_18] = 18; _msh_nodes_per_elem[_msh_prism_15] = 15; _msh_nodes_per_elem[_msh_pyramid_14] = 14; _msh_nodes_per_elem[_msh_point] = 1; _msh_nodes_per_elem[_msh_quadrangle_8] = 8; _msh_to_akantu_element_types[_msh_not_defined] = _not_defined; _msh_to_akantu_element_types[_msh_segment_2] = _segment_2; _msh_to_akantu_element_types[_msh_triangle_3] = _triangle_3; _msh_to_akantu_element_types[_msh_quadrangle_4] = _quadrangle_4; _msh_to_akantu_element_types[_msh_tetrahedron_4] = _tetrahedron_4; _msh_to_akantu_element_types[_msh_hexahedron_8] = _hexahedron_8; _msh_to_akantu_element_types[_msh_prism_1] = _pentahedron_6; _msh_to_akantu_element_types[_msh_pyramid_1] = _not_defined; _msh_to_akantu_element_types[_msh_segment_3] = _segment_3; _msh_to_akantu_element_types[_msh_triangle_6] = _triangle_6; _msh_to_akantu_element_types[_msh_quadrangle_9] = _not_defined; _msh_to_akantu_element_types[_msh_tetrahedron_10] = _tetrahedron_10; _msh_to_akantu_element_types[_msh_hexahedron_27] = _not_defined; _msh_to_akantu_element_types[_msh_hexahedron_20] = _hexahedron_20; _msh_to_akantu_element_types[_msh_prism_18] = _not_defined; _msh_to_akantu_element_types[_msh_prism_15] = _pentahedron_15; _msh_to_akantu_element_types[_msh_pyramid_14] = _not_defined; _msh_to_akantu_element_types[_msh_point] = _point_1; _msh_to_akantu_element_types[_msh_quadrangle_8] = _quadrangle_8; _akantu_to_msh_element_types[_not_defined] = _msh_not_defined; _akantu_to_msh_element_types[_segment_2] = _msh_segment_2; _akantu_to_msh_element_types[_segment_3] = _msh_segment_3; _akantu_to_msh_element_types[_triangle_3] = _msh_triangle_3; _akantu_to_msh_element_types[_triangle_6] = _msh_triangle_6; _akantu_to_msh_element_types[_tetrahedron_4] = _msh_tetrahedron_4; _akantu_to_msh_element_types[_tetrahedron_10] = _msh_tetrahedron_10; _akantu_to_msh_element_types[_quadrangle_4] = _msh_quadrangle_4; _akantu_to_msh_element_types[_quadrangle_8] = _msh_quadrangle_8; _akantu_to_msh_element_types[_hexahedron_8] = _msh_hexahedron_8; _akantu_to_msh_element_types[_hexahedron_20] = _msh_hexahedron_20; _akantu_to_msh_element_types[_pentahedron_6] = _msh_prism_1; _akantu_to_msh_element_types[_pentahedron_15] = _msh_prism_15; _akantu_to_msh_element_types[_point_1] = _msh_point; #if defined(AKANTU_STRUCTURAL_MECHANICS) _akantu_to_msh_element_types[_bernoulli_beam_2] = _msh_segment_2; _akantu_to_msh_element_types[_bernoulli_beam_3] = _msh_segment_2; _akantu_to_msh_element_types[_kirchhoff_shell] = _msh_triangle_3; #endif std::map<ElementType, MSHElementType>::iterator it; for (it = _akantu_to_msh_element_types.begin(); it != _akantu_to_msh_element_types.end(); ++it) { UInt nb_nodes = _msh_nodes_per_elem[it->second]; std::vector<UInt> tmp(nb_nodes); for (UInt i = 0; i < nb_nodes; ++i) { tmp[i] = i; } switch (it->first) { case _tetrahedron_10: tmp[8] = 9; tmp[9] = 8; break; case _pentahedron_6: tmp[0] = 2; tmp[1] = 0; tmp[2] = 1; tmp[3] = 5; tmp[4] = 3; tmp[5] = 4; break; case _pentahedron_15: tmp[0] = 2; tmp[1] = 0; tmp[2] = 1; tmp[3] = 5; tmp[4] = 3; tmp[5] = 4; tmp[6] = 8; tmp[8] = 11; tmp[9] = 6; tmp[10] = 9; tmp[11] = 10; tmp[12] = 14; tmp[14] = 12; break; case _hexahedron_20: tmp[9] = 11; tmp[10] = 12; tmp[11] = 9; tmp[12] = 13; tmp[13] = 10; tmp[17] = 19; tmp[18] = 17; tmp[19] = 18; break; default: // nothing to change break; } _read_order[it->first] = tmp; } } /* -------------------------------------------------------------------------- */ MeshIOMSH::~MeshIOMSH() {} /* -------------------------------------------------------------------------- */ /* Spirit stuff */ /* -------------------------------------------------------------------------- */ // namespace _parser { // namespace spirit = ::boost::spirit; // namespace qi = ::boost::spirit::qi; // namespace ascii = ::boost::spirit::ascii; // namespace lbs = ::boost::spirit::qi::labels; // namespace phx = ::boost::phoenix; // /* ------------------------------------------------------------------------ // */ // /* Lazy functors */ // /* ------------------------------------------------------------------------ // */ // struct _Element { // int index; // std::vector<int> tags; // std::vector<int> connectivity; // ElementType type; // }; // /* ------------------------------------------------------------------------ // */ // struct lazy_get_nb_nodes_ { // template <class elem_type> struct result { typedef int type; }; // template <class elem_type> bool operator()(elem_type et) { // return MeshIOMSH::_msh_nodes_per_elem[et]; // } // }; // /* ------------------------------------------------------------------------ // */ // struct lazy_element_ { // template <class id_t, class tags_t, class elem_type, class conn_t> // struct result { // typedef _Element type; // }; // template <class id_t, class tags_t, class elem_type, class conn_t> // _Element operator()(id_t id, const elem_type & et, const tags_t & t, // const conn_t & c) { // _Element tmp_el; // tmp_el.index = id; // tmp_el.tags = t; // tmp_el.connectivity = c; // tmp_el.type = et; // return tmp_el; // } // }; // /* ------------------------------------------------------------------------ // */ // struct lazy_check_value_ { // template <class T> struct result { typedef void type; }; // template <class T> void operator()(T v1, T v2) { // if (v1 != v2) { // AKANTU_EXCEPTION("The msh parser expected a " // << v2 << " in the header bug got a " << v1); // } // } // }; // /* ------------------------------------------------------------------------ // */ // struct lazy_node_read_ { // template <class Mesh, class ID, class V, class size, class Map> // struct result { // typedef bool type; // }; // template <class Mesh, class ID, class V, class size, class Map> // bool operator()(Mesh & mesh, const ID & id, const V & pos, size max, // Map & nodes_mapping) const { // Vector<Real> tmp_pos(mesh.getSpatialDimension()); // UInt i = 0; // for (typename V::const_iterator it = pos.begin(); // it != pos.end() || i < mesh.getSpatialDimension(); ++it) // tmp_pos[i++] = *it; // nodes_mapping[id] = mesh.getNbNodes(); // mesh.getNodes().push_back(tmp_pos); // return (mesh.getNbNodes() < UInt(max)); // } // }; // /* ------------------------------------------------------------------------ // */ // struct lazy_element_read_ { // template <class Mesh, class EL, class size, class NodeMap, class ElemMap> // struct result { // typedef bool type; // }; // template <class Mesh, class EL, class size, class NodeMap, class ElemMap> // bool operator()(Mesh & mesh, const EL & element, size max, // const NodeMap & nodes_mapping, // ElemMap & elements_mapping) const { // Vector<UInt> tmp_conn(Mesh::getNbNodesPerElement(element.type)); // AKANTU_DEBUG_ASSERT(element.connectivity.size() == tmp_conn.size(), // "The element " // << element.index // << "in the MSH file has too many nodes."); // mesh.addConnectivityType(element.type); // Array<UInt> & connectivity = mesh.getConnectivity(element.type); // UInt i = 0; // for (std::vector<int>::const_iterator it = // element.connectivity.begin(); // it != element.connectivity.end(); ++it) { // typename NodeMap::const_iterator nit = nodes_mapping.find(*it); // AKANTU_DEBUG_ASSERT(nit != nodes_mapping.end(), // "There is an unknown node in the connectivity."); // tmp_conn[i++] = nit->second; // } // ::akantu::Element el(element.type, connectivity.getSize()); // elements_mapping[element.index] = el; // connectivity.push_back(tmp_conn); // for (UInt i = 0; i < element.tags.size(); ++i) { // std::stringstream tag_sstr; // tag_sstr << "tag_" << i; // Array<UInt> * data = // mesh.template getDataPointer<UInt>(tag_sstr.str(), element.type, // _not_ghost); // data->push_back(element.tags[i]); // } // return (mesh.getNbElement() < UInt(max)); // } // }; // /* ------------------------------------------------------------------------ // */ // template <class Iterator, typename Skipper = ascii::space_type> // struct MshMeshGrammar : qi::grammar<Iterator, void(), Skipper> { // public: // MshMeshGrammar(Mesh & mesh) // : MshMeshGrammar::base_type(start, "msh_mesh_reader"), mesh(mesh) { // phx::function<lazy_element_> lazy_element; // phx::function<lazy_get_nb_nodes_> lazy_get_nb_nodes; // phx::function<lazy_check_value_> lazy_check_value; // phx::function<lazy_node_read_> lazy_node_read; // phx::function<lazy_element_read_> lazy_element_read; // clang-format off // start // = *( known_section | unknown_section // ) // ; // known_section // = qi::char_("$") // >> sections [ lbs::_a = lbs::_1 ] // >> qi::lazy(*lbs::_a) // >> qi::lit("$End") // //>> qi::lit(phx::ref(lbs::_a)) // ; // unknown_section // = qi::char_("$") // >> qi::char_("") [ lbs::_a = lbs::_1 ] // >> ignore_section // >> qi::lit("$End") // >> qi::lit(phx::val(lbs::_a)) // ; // mesh_format // version followed by 0 or 1 for ascii or binary // = version >> ( // ( qi::char_("0") // >> qi::int_ [ lazy_check_value(lbs::_1, 8) ] // ) // | ( qi::char_("1") // >> qi::int_ [ lazy_check_value(lbs::_1, 8) ] // >> qi::dword [ lazy_check_value(lbs::_1, 1) ] // ) // ) // ; // nodes // = nodes_ // ; // nodes_ // = qi::int_ [ lbs::_a = lbs::_1 ] // > *( // ( qi::int_ >> position ) [ lazy_node_read(phx::ref(mesh), // lbs::_1, // phx::cref(lbs::_2), // lbs::_a, // phx::ref(this->msh_nodes_to_akantu)) ] // ) // ; // element // = elements_ // ; // elements_ // = qi::int_ [ lbs::_a = lbs::_1 ] // > qi::repeat(phx::ref(lbs::_a))[ element [ lazy_element_read(phx::ref(mesh), // lbs::_1, // phx::cref(lbs::_a), // phx::cref(this->msh_nodes_to_akantu), // phx::ref(this->msh_elemt_to_akantu)) ]] // ; // ignore_section // = *(qi::char_ - qi::char_('$')) // ; // interpolation_scheme = ignore_section; // element_data = ignore_section; // node_data = ignore_section; // version // = qi::int_ [ phx::push_back(lbs::_val, lbs::_1) ] // >> *( qi::char_(".") >> qi::int_ [ phx::push_back(lbs::_val, lbs::_1) ] ) // ; // position // = real [ phx::push_back(lbs::_val, lbs::_1) ] // > real [ phx::push_back(lbs::_val, lbs::_1) ] // > real [ phx::push_back(lbs::_val, lbs::_1) ] // ; // tags // = qi::int_ [ lbs::_a = lbs::_1 ] // > qi::repeat(phx::val(lbs::_a))[ qi::int_ [ phx::push_back(lbs::_val, // lbs::_1) ] ] // ; // element // = ( qi::int_ [ lbs::_a = lbs::_1 ] // > msh_element_type [ lbs::_b = lazy_get_nb_nodes(lbs::_1) ] // > tags [ lbs::_c = lbs::_1 ] // > connectivity(lbs::_a) [ lbs::_d = lbs::_1 ] // ) [ lbs::_val = lazy_element(lbs::_a, // phx::cref(lbs::_b), // phx::cref(lbs::_c), // phx::cref(lbs::_d)) ] // ; // connectivity // = qi::repeat(lbs::_r1)[ qi::int_ [ phx::push_back(lbs::_val, // lbs::_1) ] ] // ; // sections.add // ("MeshFormat", &mesh_format) // ("Nodes", &nodes) // ("Elements", &elements) // ("PhysicalNames", &physical_names) // ("InterpolationScheme", &interpolation_scheme) // ("ElementData", &element_data) // ("NodeData", &node_data); // msh_element_type.add // ("0" , _not_defined ) // ("1" , _segment_2 ) // ("2" , _triangle_3 ) // ("3" , _quadrangle_4 ) // ("4" , _tetrahedron_4 ) // ("5" , _hexahedron_8 ) // ("6" , _pentahedron_6 ) // ("7" , _not_defined ) // ("8" , _segment_3 ) // ("9" , _triangle_6 ) // ("10", _not_defined ) // ("11", _tetrahedron_10) // ("12", _not_defined ) // ("13", _not_defined ) // ("14", _hexahedron_20 ) // ("15", _pentahedron_15) // ("16", _not_defined ) // ("17", _point_1 ) // ("18", _quadrangle_8 ); // mesh_format .name("MeshFormat" ); // nodes .name("Nodes" ); // elements .name("Elements" ); // physical_names .name("PhysicalNames" ); // interpolation_scheme.name("InterpolationScheme"); // element_data .name("ElementData" ); // node_data .name("NodeData" ); // clang-format on // } // /* ---------------------------------------------------------------------- // */ // /* Rules */ // /* ---------------------------------------------------------------------- // */ // private: // qi::symbols<char, ElementType> msh_element_type; // qi::symbols<char, qi::rule<Iterator, void(), Skipper> *> sections; // qi::rule<Iterator, void(), Skipper> start; // qi::rule<Iterator, void(), Skipper, qi::locals<std::string> > // unknown_section; // qi::rule<Iterator, void(), Skipper, qi::locals<qi::rule<Iterator, // Skipper> *> > known_section; // qi::rule<Iterator, void(), Skipper> mesh_format, nodes, elements, // physical_names, ignore_section, // interpolation_scheme, element_data, node_data, any_line; // qi::rule<Iterator, void(), Skipper, qi::locals<int> > nodes_; // qi::rule<Iterator, void(), Skipper, qi::locals< int, int, vector<int>, // vector<int> > > elements_; // qi::rule<Iterator, std::vector<int>(), Skipper> version; // qi::rule<Iterator, _Element(), Skipper, qi::locals<ElementType> > // element; // qi::rule<Iterator, std::vector<int>(), Skipper, qi::locals<int> > tags; // qi::rule<Iterator, std::vector<int>(int), Skipper> connectivity; // qi::rule<Iterator, std::vector<Real>(), Skipper> position; // qi::real_parser<Real, qi::real_policies<Real> > real; // /* ---------------------------------------------------------------------- // */ // /* Members */ // /* ---------------------------------------------------------------------- // */ // private: // /// reference to the mesh to read // Mesh & mesh; // /// correspondance between the numbering of nodes in the abaqus file and // in // /// the akantu mesh // std::map<UInt, UInt> msh_nodes_to_akantu; // /// correspondance between the element number in the abaqus file and the // /// Element in the akantu mesh // std::map<UInt, Element> msh_elemt_to_akantu; // }; // } // /* -------------------------------------------------------------------------- // */ // void MeshIOAbaqus::read(const std::string& filename, Mesh& mesh) { // namespace qi = boost::spirit::qi; // namespace ascii = boost::spirit::ascii; // std::ifstream infile; // infile.open(filename.c_str()); // if(!infile.good()) { // AKANTU_DEBUG_ERROR("Cannot open file " << filename); // } // std::string storage; // We will read the contents here. // infile.unsetf(std::ios::skipws); // No white space skipping! // std::copy(std::istream_iterator<char>(infile), // std::istream_iterator<char>(), // std::back_inserter(storage)); // typedef std::string::const_iterator iterator_t; // typedef ascii::space_type skipper; // typedef _parser::MshMeshGrammar<iterator_t, skipper> grammar; // grammar g(mesh); // skipper ws; // iterator_t iter = storage.begin(); // iterator_t end = storage.end(); // qi::phrase_parse(iter, end, g, ws); // this->setNbGlobalNodes(mesh, mesh.getNodes().getSize()); // MeshUtils::fillElementToSubElementsData(mesh); // } static void my_getline(std::ifstream & infile, std::string & str) { std::string tmp_str; std::getline(infile, tmp_str); str = trim(tmp_str); } /* -------------------------------------------------------------------------- */ void MeshIOMSH::read(const std::string & filename, Mesh & mesh) { MeshAccessor mesh_accessor(mesh); std::ifstream infile; infile.open(filename.c_str()); std::string line; UInt first_node_number = std::numeric_limits<UInt>::max(), last_node_number = 0, file_format = 1, current_line = 0; bool has_physical_names = false; if (!infile.good()) { AKANTU_DEBUG_ERROR("Cannot open file " << filename); } while (infile.good()) { my_getline(infile, line); current_line++; /// read the header if (line == "$MeshFormat") { my_getline(infile, line); /// the format line std::stringstream sstr(line); std::string version; sstr >> version; Int format; sstr >> format; if (format != 0) AKANTU_DEBUG_ERROR("This reader can only read ASCII files."); my_getline(infile, line); /// the end of block line current_line += 2; file_format = 2; } /// read the physical names if (line == "$PhysicalNames") { has_physical_names = true; my_getline(infile, line); /// the format line std::stringstream sstr(line); UInt num_of_phys_names; sstr >> num_of_phys_names; for (UInt k(0); k < num_of_phys_names; k++) { my_getline(infile, line); std::stringstream sstr_phys_name(line); UInt phys_name_id; UInt phys_dim; sstr_phys_name >> phys_dim >> phys_name_id; std::size_t b = line.find("\""); std::size_t e = line.rfind("\""); std::string phys_name = line.substr(b + 1, e - b - 1); phys_name_map[phys_name_id] = phys_name; } } /// read all nodes if (line == "$Nodes" || line == "$NOD") { UInt nb_nodes; my_getline(infile, line); std::stringstream sstr(line); sstr >> nb_nodes; current_line++; Array<Real> & nodes = mesh_accessor.getNodes(); nodes.resize(nb_nodes); mesh_accessor.setNbGlobalNodes(nb_nodes); UInt index; Real coord[3]; UInt spatial_dimension = nodes.getNbComponent(); /// for each node, read the coordinates for (UInt i = 0; i < nb_nodes; ++i) { UInt offset = i * spatial_dimension; my_getline(infile, line); std::stringstream sstr_node(line); sstr_node >> index >> coord[0] >> coord[1] >> coord[2]; current_line++; first_node_number = std::min(first_node_number, index); last_node_number = std::max(last_node_number, index); /// read the coordinates for (UInt j = 0; j < spatial_dimension; ++j) nodes.storage()[offset + j] = coord[j]; } my_getline(infile, line); /// the end of block line } /// read all elements if (line == "$Elements" || line == "$ELM") { UInt nb_elements; std::vector<UInt> read_order; my_getline(infile, line); std::stringstream sstr(line); sstr >> nb_elements; current_line++; Int index; UInt msh_type; ElementType akantu_type, akantu_type_old = _not_defined; Array<UInt> * connectivity = NULL; UInt node_per_element = 0; for (UInt i = 0; i < nb_elements; ++i) { my_getline(infile, line); std::stringstream sstr_elem(line); current_line++; sstr_elem >> index; sstr_elem >> msh_type; /// get the connectivity vector depending on the element type akantu_type = this->_msh_to_akantu_element_types[(MSHElementType)msh_type]; if (akantu_type == _not_defined) { AKANTU_DEBUG_WARNING("Unsuported element kind " << msh_type << " at line " << current_line); continue; } if (akantu_type != akantu_type_old) { connectivity = &mesh_accessor.getConnectivity(akantu_type); // connectivity->resize(0); node_per_element = connectivity->getNbComponent(); akantu_type_old = akantu_type; read_order = this->_read_order[akantu_type]; } /// read tags informations if (file_format == 2) { UInt nb_tags; sstr_elem >> nb_tags; for (UInt j = 0; j < nb_tags; ++j) { Int tag; sstr_elem >> tag; std::stringstream sstr_tag_name; sstr_tag_name << "tag_" << j; - Array<UInt> * data = mesh.getDataPointer<UInt>( + Array<UInt> & data = mesh.getDataPointer<UInt>( sstr_tag_name.str(), akantu_type, _not_ghost); - data->push_back(tag); + data.push_back(tag); } } else if (file_format == 1) { Int tag; sstr_elem >> tag; // reg-phys std::string tag_name = "tag_0"; Array<UInt> * data = - mesh.getDataPointer<UInt>(tag_name, akantu_type, _not_ghost); + &mesh.getDataPointer<UInt>(tag_name, akantu_type, _not_ghost); data->push_back(tag); sstr_elem >> tag; // reg-elem tag_name = "tag_1"; - data = mesh.getDataPointer<UInt>(tag_name, akantu_type, _not_ghost); + data = &mesh.getDataPointer<UInt>(tag_name, akantu_type, _not_ghost); data->push_back(tag); sstr_elem >> tag; // number-of-nodes } Vector<UInt> local_connect(node_per_element); for (UInt j = 0; j < node_per_element; ++j) { UInt node_index; sstr_elem >> node_index; AKANTU_DEBUG_ASSERT(node_index <= last_node_number, "Node number not in range : line " << current_line); node_index -= first_node_number; local_connect(read_order[j]) = node_index; } connectivity->push_back(local_connect); } my_getline(infile, line); /// the end of block line } if ((line[0] == '$') && (line.find("End") == std::string::npos)) { AKANTU_DEBUG_WARNING("Unsuported block_kind " << line << " at line " << current_line); } } - mesh.updateTypesOffsets(_not_ghost); + //mesh.updateTypesOffsets(_not_ghost); infile.close(); this->constructPhysicalNames("tag_0", mesh); if (has_physical_names) mesh.createGroupsFromMeshData<std::string>("physical_names"); MeshUtils::fillElementToSubElementsData(mesh); } /* -------------------------------------------------------------------------- */ void MeshIOMSH::write(const std::string & filename, const Mesh & mesh) { std::ofstream outfile; const Array<Real> & nodes = mesh.getNodes(); outfile.open(filename.c_str()); outfile << "$MeshFormat" << std::endl; outfile << "2.1 0 8" << std::endl; outfile << "$EndMeshFormat" << std::endl; outfile << std::setprecision(std::numeric_limits<Real>::digits10); outfile << "$Nodes" << std::endl; outfile << nodes.getSize() << std::endl; outfile << std::uppercase; for (UInt i = 0; i < nodes.getSize(); ++i) { Int offset = i * nodes.getNbComponent(); outfile << i + 1; for (UInt j = 0; j < nodes.getNbComponent(); ++j) { outfile << " " << nodes.storage()[offset + j]; } for (UInt p = nodes.getNbComponent(); p < 3; ++p) outfile << " " << 0.; outfile << std::endl; ; } outfile << std::nouppercase; outfile << "$EndNodes" << std::endl; ; outfile << "$Elements" << std::endl; ; Mesh::type_iterator it = mesh.firstType(_all_dimensions, _not_ghost, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(_all_dimensions, _not_ghost, _ek_not_defined); Int nb_elements = 0; for (; it != end; ++it) { const Array<UInt> & connectivity = mesh.getConnectivity(*it, _not_ghost); nb_elements += connectivity.getSize(); } outfile << nb_elements << std::endl; UInt element_idx = 1; for (it = mesh.firstType(_all_dimensions, _not_ghost, _ek_not_defined); it != end; ++it) { ElementType type = *it; const Array<UInt> & connectivity = mesh.getConnectivity(type, _not_ghost); UInt * tag[2] = {NULL, NULL}; try { const Array<UInt> & data_tag_0 = mesh.getData<UInt>("tag_0", type, _not_ghost); tag[0] = data_tag_0.storage(); } catch (...) { tag[0] = NULL; } try { const Array<UInt> & data_tag_1 = mesh.getData<UInt>("tag_1", type, _not_ghost); tag[1] = data_tag_1.storage(); } catch (...) { tag[1] = NULL; } for (UInt i = 0; i < connectivity.getSize(); ++i) { UInt offset = i * connectivity.getNbComponent(); outfile << element_idx << " " << _akantu_to_msh_element_types[type] << " 2"; /// \todo write the real data in the file for (UInt t = 0; t < 2; ++t) if (tag[t]) outfile << " " << tag[t][i]; else outfile << " 0"; for (UInt j = 0; j < connectivity.getNbComponent(); ++j) { outfile << " " << connectivity.storage()[offset + j] + 1; } outfile << std::endl; element_idx++; } } outfile << "$EndElements" << std::endl; ; outfile.close(); } /* -------------------------------------------------------------------------- */ } // akantu diff --git a/src/mesh/element_group.hh b/src/mesh/element_group.hh index be5a6ab5c..181d9c3d6 100644 --- a/src/mesh/element_group.hh +++ b/src/mesh/element_group.hh @@ -1,188 +1,187 @@ /** * @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; -} // akantu +} // 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: - typedef ElementTypeMapArray<UInt> ElementList; - typedef Array<UInt> NodeList; - - /* ------------------------------------------------------------------------ */ - /* Node iterator */ - /* ------------------------------------------------------------------------ */ - typedef NodeGroup::const_node_iterator const_node_iterator; - inline const_node_iterator node_begin() const; - inline const_node_iterator node_end() const; + using ElementList = ElementTypeMapArray<UInt>; + using NodeList = Array<UInt>; /* ------------------------------------------------------------------------ */ /* Element iterator */ /* ------------------------------------------------------------------------ */ - typedef ElementList::type_iterator type_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; - typedef Array<UInt>::const_iterator<UInt> const_element_iterator; + 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); + } + + using const_element_iterator = Array<UInt>::const_iterator<UInt>; inline const_element_iterator - element_begin(const ElementType & type, - const GhostType & ghost_type = _not_ghost) const; + begin(const ElementType & type, + const GhostType & ghost_type = _not_ghost) const; inline const_element_iterator - element_end(const ElementType & type, - const GhostType & ghost_type = _not_ghost) const; + 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: AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Elements, elements, UInt); 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; } -} // akantu +} // namespace akantu #include "element.hh" #include "element_group_inline_impl.cc" #endif /* __AKANTU_ELEMENT_GROUP_HH__ */ diff --git a/src/mesh/element_group_inline_impl.cc b/src/mesh/element_group_inline_impl.cc index ba16ea036..7ff809849 100644 --- a/src/mesh/element_group_inline_impl.cc +++ b/src/mesh/element_group_inline_impl.cc @@ -1,137 +1,135 @@ /** * @file element_group_inline_impl.cc * * @author Dana Christen <dana.christen@gmail.com> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 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 "mesh.hh" +#include "element_group.hh" + /* -------------------------------------------------------------------------- */ +#ifndef __AKANTU_ELEMENT_GROUP_INLINE_IMPL_CC__ +#define __AKANTU_ELEMENT_GROUP_INLINE_IMPL_CC__ namespace akantu { /* -------------------------------------------------------------------------- */ -inline void ElementGroup::add(const Element & el, bool add_nodes, - bool check_for_duplicate) { - this->add(el.type,el.element,el.ghost_type,add_nodes,check_for_duplicate); +inline void ElementGroup::add(const Element & el, bool add_nodes, + bool check_for_duplicate) { + this->add(el.type, el.element, el.ghost_type, add_nodes, check_for_duplicate); } - /* -------------------------------------------------------------------------- */ -inline void ElementGroup::add(const ElementType & type, UInt element, - const GhostType & ghost_type,bool add_nodes, - bool check_for_duplicate) { +inline void ElementGroup::add(const ElementType & type, UInt element, + const GhostType & ghost_type, bool add_nodes, + bool check_for_duplicate) { addElement(type, element, ghost_type); - if(add_nodes) { + if (add_nodes) { Array<UInt>::const_vector_iterator it = - mesh.getConnectivity(type, ghost_type).begin(mesh.getNbNodesPerElement(type)) + element; + mesh.getConnectivity(type, ghost_type) + .begin(mesh.getNbNodesPerElement(type)) + + element; const Vector<UInt> & conn = *it; - for (UInt i = 0; i < conn.size(); ++i) addNode(conn[i], check_for_duplicate); + for (UInt i = 0; i < conn.size(); ++i) + addNode(conn[i], check_for_duplicate); } } /* -------------------------------------------------------------------------- */ inline void ElementGroup::addNode(UInt node_id, bool check_for_duplicate) { node_group.add(node_id, check_for_duplicate); } /* -------------------------------------------------------------------------- */ inline void ElementGroup::removeNode(UInt node_id) { node_group.remove(node_id); } /* -------------------------------------------------------------------------- */ inline void ElementGroup::addElement(const ElementType & elem_type, - UInt elem_id, - const GhostType & ghost_type) { - if(!(elements.exists(elem_type, ghost_type))) { + UInt elem_id, + const GhostType & ghost_type) { + if (!(elements.exists(elem_type, ghost_type))) { elements.alloc(0, 1, elem_type, ghost_type); } elements(elem_type, ghost_type).push_back(elem_id); - this->dimension = UInt(std::max(Int(this->dimension), Int(mesh.getSpatialDimension(elem_type)))); -} - -/* -------------------------------------------------------------------------- */ -inline UInt ElementGroup::getNbNodes() const { - return node_group.getSize(); + this->dimension = UInt( + std::max(Int(this->dimension), Int(mesh.getSpatialDimension(elem_type)))); } /* -------------------------------------------------------------------------- */ -inline ElementGroup::const_node_iterator ElementGroup::node_begin() const { - return node_group.begin(); -} +inline UInt ElementGroup::getNbNodes() const { return node_group.getSize(); } /* -------------------------------------------------------------------------- */ -inline ElementGroup::const_node_iterator ElementGroup::node_end() const { - return node_group.end(); -} - -/* -------------------------------------------------------------------------- */ -inline ElementGroup::type_iterator ElementGroup::firstType(UInt dim, - const GhostType & ghost_type, - const ElementKind & kind) const { +inline ElementGroup::type_iterator +ElementGroup::firstType(UInt dim, const GhostType & ghost_type, + const ElementKind & kind) const { return elements.firstType(dim, ghost_type, kind); } /* -------------------------------------------------------------------------- */ -inline ElementGroup::type_iterator ElementGroup::lastType(UInt dim, - const GhostType & ghost_type, - const ElementKind & kind) const { +inline ElementGroup::type_iterator +ElementGroup::lastType(UInt dim, const GhostType & ghost_type, + const ElementKind & kind) const { return elements.lastType(dim, ghost_type, kind); } /* -------------------------------------------------------------------------- */ -inline ElementGroup::const_element_iterator ElementGroup::element_begin(const ElementType & type, - const GhostType & ghost_type) const { - if(elements.exists(type, ghost_type)) { +inline ElementGroup::const_element_iterator +ElementGroup::begin(const ElementType & type, + const GhostType & ghost_type) const { + if (elements.exists(type, ghost_type)) { return elements(type, ghost_type).begin(); } else { return empty_elements.begin(); } } /* -------------------------------------------------------------------------- */ -inline ElementGroup::const_element_iterator ElementGroup::element_end(const ElementType & type, - const GhostType & ghost_type) const { - if(elements.exists(type, ghost_type)) { +inline ElementGroup::const_element_iterator +ElementGroup::end(const ElementType & type, + const GhostType & ghost_type) const { + if (elements.exists(type, ghost_type)) { return elements(type, ghost_type).end(); } else { return empty_elements.end(); } - } /* -------------------------------------------------------------------------- */ -} // akantu +} // namespace akantu + +#endif /* __AKANTU_ELEMENT_GROUP_INLINE_IMPL_CC__ */ diff --git a/src/mesh/element_type_map.cc b/src/mesh/element_type_map.cc index 3aad70e2e..10ed4c342 100644 --- a/src/mesh/element_type_map.cc +++ b/src/mesh/element_type_map.cc @@ -1,50 +1,59 @@ /** * @file element_type_map.cc * * @author Nicolas Richart * * @date creation Tue Jun 27 2017 * * @brief A Documented file. * * @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 "mesh.hh" #include "fe_engine.hh" +#include "mesh.hh" /* -------------------------------------------------------------------------- */ namespace akantu { FEEngineElementTypeMapArrayInializer::FEEngineElementTypeMapArrayInializer( - const FEEngine & fe_engine, UInt spatial_dimension, - UInt nb_component, const GhostType & ghost_type, - const ElementKind & element_kind) - : MeshElementTypeMapArrayInializer(fe_engine.getMesh(), spatial_dimension, - nb_component, ghost_type, element_kind, - true, false), - fe_engine(fe_engine) {} + const FEEngine & fe_engine, UInt nb_component, UInt spatial_dimension, + const GhostType & ghost_type, const ElementKind & element_kind) + : MeshElementTypeMapArrayInializer( + fe_engine.getMesh(), + nb_component, + spatial_dimension == UInt(-2) + ? fe_engine.getMesh().getSpatialDimension() + : spatial_dimension, + ghost_type, element_kind, true, false), + fe_engine(fe_engine) {} -UInt FEEngineElementTypeMapArrayInializer::size(const ElementType & type) const { +UInt FEEngineElementTypeMapArrayInializer::size( + const ElementType & type) const { return MeshElementTypeMapArrayInializer::size(type) * - fe_engine.getNbIntegrationPoints(type, this->ghost_type); + fe_engine.getNbIntegrationPoints(type, this->ghost_type); } -} // akantu +FEEngineElementTypeMapArrayInializer::ElementTypesIteratorHelper +FEEngineElementTypeMapArrayInializer::elementTypes() const { + return this->fe_engine.elementTypes(spatial_dimension, ghost_type, + element_kind); +} +} // namespace akantu diff --git a/src/mesh/element_type_map.hh b/src/mesh/element_type_map.hh index 141edba25..438683f5c 100644 --- a/src/mesh/element_type_map.hh +++ b/src/mesh/element_type_map.hh @@ -1,394 +1,391 @@ /** * @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" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_TYPE_MAP_HH__ #define __AKANTU_ELEMENT_TYPE_MAP_HH__ namespace akantu { class FEEngine; } // namespace akantu namespace akantu { template <class Stored, typename SupportType = ElementType> class ElementTypeMap; /* -------------------------------------------------------------------------- */ /* ElementTypeMapBase */ /* -------------------------------------------------------------------------- */ /// Common non templated base class for the ElementTypeMap class class ElementTypeMapBase { public: virtual ~ElementTypeMapBase(){}; }; /* -------------------------------------------------------------------------- */ /* 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: typedef const SupportType value_type; typedef const SupportType * pointer; typedef const SupportType & reference; protected: typedef typename ElementTypeMap<Stored>::DataMap::const_iterator DataMapIterator; 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 = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) : container(std::cref(container)), dim(dim), ghost_type(ghost_type), kind(kind) {} 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; }; /// method to create the helper class to use in range for constructs ElementTypesIteratorHelper elementTypes(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) const; /*! 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: typedef T type; typedef Array<T> array_type; protected: typedef ElementTypeMap<Array<T> *, SupportType> parent; typedef typename parent::DataMap DataMap; private: private: /// standard assigment (copy) operator void operator=(const ElementTypeMap<T, SupportType> &){}; public: - typedef typename parent::type_iterator type_iterator; + using type_iterator = typename parent::type_iterator; /*! 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; /* 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; - type_iterator tit = this->firstType(dim, ghost_type, kind); - type_iterator end = this->lastType(dim, ghost_type, kind); - - while (tit != end) { - UInt nb_comp = (*this)(*tit, ghost_type).getNbComponent(); - nb_components(*tit, ghost_type) = nb_comp; - ++tit; + 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); private: ElementTypeMapArray operator=(__attribute__((unused)) const ElementTypeMapArray & other){}; /// name of the elment type map: e.g. connectivity, grad_u ID name; }; /// to store data Array<Real> by element type typedef ElementTypeMapArray<Real> ElementTypeMapReal; /// to store data Array<Int> by element type typedef ElementTypeMapArray<Int> ElementTypeMapInt; /// to store data Array<UInt> by element type typedef ElementTypeMapArray<UInt, ElementType> ElementTypeMapUInt; /// Map of data of type UInt stored in a mesh typedef std::map<std::string, Array<UInt> *> UIntDataMap; typedef ElementTypeMap<UIntDataMap, ElementType> ElementTypeMapUIntDataMap; } // 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 6a6e038e3..91735c2a0 100644 --- a/src/mesh/element_type_map_tmpl.hh +++ b/src/mesh/element_type_map_tmpl.hh @@ -1,623 +1,621 @@ /** * @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 "element_type_map.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ +#include "element_type_conversion.hh" +/* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_TYPE_MAP_TMPL_HH__ #define __AKANTU_ELEMENT_TYPE_MAP_TMPL_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ -/* ElementTypeMap */ +/* 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 { typename DataMap::const_iterator 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) { typename DataMap::iterator 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 { DataMap & data = this->getData(ghost_type); const std::pair<typename DataMap::iterator, bool> & 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; else 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; else 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 (UInt g = _not_ghost; g <= _ghost; ++g) { - GhostType gt = (GhostType)g; - + for (auto gt : ghost_types) { const DataMap & data = getData(gt); - typename DataMap::const_iterator it; - for (it = data.begin(); it != data.end(); ++it) { - stream << space << space << ElementTypeMap::printType(it->first, 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() { AKANTU_DEBUG_IN(); // std::stringstream sstr; // if(parent_id != "") sstr << parent_id << ":"; // sstr << id; // this->id = sstr.str(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> ElementTypeMap<Stored, SupportType>::~ElementTypeMap() {} /* -------------------------------------------------------------------------- */ /* 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; typename ElementTypeMapArray<T, SupportType>::DataMap::iterator 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 (UInt g = _not_ghost; g <= _ghost; ++g) { - GhostType gt = (GhostType)g; - + for (auto gt : ghost_types) { DataMap & data = this->getData(gt); - typename DataMap::const_iterator it; - for (it = data.begin(); it != data.end(); ++it) { - dealloc(it->second->getID()); + 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 (UInt g = _not_ghost; g <= _ghost; ++g) { - GhostType gt = (GhostType)g; - + for (auto gt : ghost_types) { DataMap & data = this->getData(gt); - typename DataMap::const_iterator it; - for (it = data.begin(); it != data.end(); ++it) { - it->second->clear(); + 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 { typename ElementTypeMapArray<T, SupportType>::DataMap::const_iterator 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) { typename ElementTypeMapArray<T, SupportType>::DataMap::iterator 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) { typename ElementTypeMapArray<T, SupportType>::DataMap::iterator 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 (UInt g = _not_ghost; g <= _ghost; ++g) { - GhostType gt = (GhostType)g; - ElementTypeMapArray<UInt>::type_iterator it = - new_numbering.firstType(_all_dimensions, gt, _ek_not_defined); - ElementTypeMapArray<UInt>::type_iterator end = - new_numbering.lastType(_all_dimensions, gt, _ek_not_defined); - for (; it != end; ++it) { - SupportType type = *it; - if (this->exists(type, gt)) { - const Array<UInt> & renumbering = new_numbering(type, gt); + 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.getSize() == 0) continue; - Array<T> & vect = this->operator()(type, gt); - UInt nb_component = vect.getNbComponent(); + + auto & vect = this->operator()(support_type, gt); + auto nb_component = vect.getNbComponent(); Array<T> tmp(renumbering.getSize(), nb_component); UInt new_size = 0; + for (UInt i = 0; i < vect.getSize(); ++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>::elementTypes(UInt dim, GhostType ghost_type, ElementKind kind) const { return ElementTypesIteratorHelper(*this, dim, ghost_type, kind); } /* -------------------------------------------------------------------------- */ 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 spatial_dimension = _all_dimensions, - UInt nb_component = 1, const GhostType & ghost_type = _not_ghost, + 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 spatial_dimension = _all_dimensions, - UInt nb_component = 1, const GhostType & ghost_type = _not_ghost, + 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(spatial_dimension, _all_dimensions), - OPTIONAL_NAMED_ARG(nb_component, 1), ghost_type, + 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())); } } } // namespace akantu #endif /* __AKANTU_ELEMENT_TYPE_MAP_TMPL_HH__ */ diff --git a/src/mesh/group_manager.cc b/src/mesh/group_manager.cc index 18afdb476..f9517336a 100644 --- a/src/mesh/group_manager.cc +++ b/src/mesh/group_manager.cc @@ -1,1030 +1,1041 @@ /** * @file group_manager.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@gmail.com> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Mon Aug 17 2015 * * @brief Stores information about ElementGroup and NodeGroup * * @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 "group_manager.hh" #include "aka_csr.hh" #include "data_accessor.hh" #include "element_group.hh" #include "element_synchronizer.hh" #include "mesh.hh" +#include "mesh_accessor.hh" #include "mesh_utils.hh" #include "node_group.hh" /* -------------------------------------------------------------------------- */ #include <algorithm> #include <iterator> #include <list> #include <numeric> #include <queue> #include <sstream> /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ GroupManager::GroupManager(const Mesh & mesh, const ID & id, const MemoryID & mem_id) : id(id), memory_id(mem_id), mesh(mesh) { AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ GroupManager::~GroupManager() { auto eit = element_groups.begin(); auto eend = element_groups.end(); for (; eit != eend; ++eit) delete (eit->second); auto nit = node_groups.begin(); auto nend = node_groups.end(); for (; nit != nend; ++nit) delete (nit->second); } /* -------------------------------------------------------------------------- */ NodeGroup & GroupManager::createNodeGroup(const std::string & group_name, bool replace_group) { AKANTU_DEBUG_IN(); auto it = node_groups.find(group_name); if (it != node_groups.end()) { if (replace_group) { it->second->empty(); AKANTU_DEBUG_OUT(); return *(it->second); } else AKANTU_EXCEPTION( "Trying to create a node group that already exists:" << group_name); } std::stringstream sstr; sstr << this->id << ":" << group_name << "_node_group"; NodeGroup * node_group = new NodeGroup(group_name, mesh, sstr.str(), memory_id); node_groups[group_name] = node_group; AKANTU_DEBUG_OUT(); return *node_group; } /* -------------------------------------------------------------------------- */ template <typename T> NodeGroup & GroupManager::createFilteredNodeGroup(const std::string & group_name, const NodeGroup & source_node_group, T & filter) { AKANTU_DEBUG_IN(); NodeGroup & node_group = this->createNodeGroup(group_name); node_group.append(source_node_group); if (T::type == FilterFunctor::_node_filter_functor) { node_group.applyNodeFilter(filter); } else { AKANTU_DEBUG_ERROR("ElementFilter cannot be applied to NodeGroup yet." << " Needs to be implemented."); } AKANTU_DEBUG_OUT(); return node_group; } /* -------------------------------------------------------------------------- */ void GroupManager::destroyNodeGroup(const std::string & group_name) { AKANTU_DEBUG_IN(); NodeGroups::iterator nit = node_groups.find(group_name); NodeGroups::iterator nend = node_groups.end(); if (nit != nend) { delete (nit->second); node_groups.erase(nit); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ElementGroup & GroupManager::createElementGroup(const std::string & group_name, UInt dimension, bool replace_group) { AKANTU_DEBUG_IN(); NodeGroup & new_node_group = createNodeGroup(group_name + "_nodes", replace_group); auto it = element_groups.find(group_name); if (it != element_groups.end()) { if (replace_group) { it->second->empty(); AKANTU_DEBUG_OUT(); return *(it->second); } else AKANTU_EXCEPTION("Trying to create a element group that already exists:" << group_name); } std::stringstream sstr; sstr << this->id << ":" << group_name << "_element_group"; ElementGroup * element_group = new ElementGroup( group_name, mesh, new_node_group, dimension, sstr.str(), memory_id); std::stringstream sstr_nodes; sstr_nodes << group_name << "_nodes"; node_groups[sstr_nodes.str()] = &new_node_group; element_groups[group_name] = element_group; AKANTU_DEBUG_OUT(); return *element_group; } /* -------------------------------------------------------------------------- */ void GroupManager::destroyElementGroup(const std::string & group_name, bool destroy_node_group) { AKANTU_DEBUG_IN(); auto eit = element_groups.find(group_name); auto eend = element_groups.end(); if (eit != eend) { if (destroy_node_group) destroyNodeGroup(eit->second->getNodeGroup().getName()); delete (eit->second); element_groups.erase(eit); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GroupManager::destroyAllElementGroups(bool destroy_node_groups) { AKANTU_DEBUG_IN(); auto eit = element_groups.begin(); auto eend = element_groups.end(); for (; eit != eend; ++eit) { if (destroy_node_groups) destroyNodeGroup(eit->second->getNodeGroup().getName()); delete (eit->second); } element_groups.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ElementGroup & GroupManager::createElementGroup(const std::string & group_name, UInt dimension, NodeGroup & node_group) { AKANTU_DEBUG_IN(); if (element_groups.find(group_name) != element_groups.end()) AKANTU_EXCEPTION( "Trying to create a element group that already exists:" << group_name); ElementGroup * element_group = new ElementGroup(group_name, mesh, node_group, dimension, id + ":" + group_name + "_element_group", memory_id); element_groups[group_name] = element_group; AKANTU_DEBUG_OUT(); return *element_group; } /* -------------------------------------------------------------------------- */ template <typename T> ElementGroup & GroupManager::createFilteredElementGroup( const std::string & group_name, UInt dimension, const NodeGroup & node_group, T & filter) { AKANTU_DEBUG_IN(); ElementGroup * element_group = NULL; if (T::type == FilterFunctor::_node_filter_functor) { NodeGroup & filtered_node_group = this->createFilteredNodeGroup( group_name + "_nodes", node_group, filter); element_group = &(this->createElementGroup(group_name, dimension, filtered_node_group)); } else if (T::type == FilterFunctor::_element_filter_functor) { AKANTU_DEBUG_ERROR( "Cannot handle an ElementFilter yet. Needs to be implemented."); } AKANTU_DEBUG_OUT(); return *element_group; } /* -------------------------------------------------------------------------- */ class ClusterSynchronizer : public DataAccessor<Element> { using DistantIDs = std::set<std::pair<UInt, UInt>>; public: ClusterSynchronizer(GroupManager & group_manager, UInt element_dimension, std::string cluster_name_prefix, ElementTypeMapArray<UInt> & element_to_fragment, const ElementSynchronizer & element_synchronizer, UInt nb_cluster) : group_manager(group_manager), element_dimension(element_dimension), cluster_name_prefix(cluster_name_prefix), element_to_fragment(element_to_fragment), element_synchronizer(element_synchronizer), nb_cluster(nb_cluster) {} UInt synchronize() { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); UInt rank = comm.whoAmI(); UInt nb_proc = comm.getNbProc(); /// find starting index to renumber local clusters Array<UInt> nb_cluster_per_proc(nb_proc); nb_cluster_per_proc(rank) = nb_cluster; comm.allGather(nb_cluster_per_proc); starting_index = std::accumulate(nb_cluster_per_proc.begin(), nb_cluster_per_proc.begin() + rank, 0); UInt global_nb_fragment = std::accumulate(nb_cluster_per_proc.begin() + rank, nb_cluster_per_proc.end(), starting_index); /// create the local to distant cluster pairs with neighbors element_synchronizer.synchronizeOnce(*this, _gst_gm_clusters); /// count total number of pairs Array<int> nb_pairs(nb_proc); // This is potentially a bug for more than // 2**31 pairs, but due to a all gatherv after // it must be int to match MPI interfaces nb_pairs(rank) = distant_ids.size(); comm.allGather(nb_pairs); UInt total_nb_pairs = std::accumulate(nb_pairs.begin(), nb_pairs.end(), 0); /// generate pairs global array UInt local_pair_index = std::accumulate(nb_pairs.storage(), nb_pairs.storage() + rank, 0); Array<UInt> total_pairs(total_nb_pairs, 2); for (auto & ids : distant_ids) { total_pairs(local_pair_index, 0) = ids.first; total_pairs(local_pair_index, 1) = ids.second; ++local_pair_index; } /// communicate pairs to all processors nb_pairs *= 2; comm.allGatherV(total_pairs, nb_pairs); /// renumber clusters /// generate fragment list std::vector<std::set<UInt>> global_clusters; UInt total_nb_cluster = 0; Array<bool> is_fragment_in_cluster(global_nb_fragment, 1, false); std::queue<UInt> fragment_check_list; while (total_pairs.getSize() != 0) { /// create a new cluster ++total_nb_cluster; global_clusters.resize(total_nb_cluster); std::set<UInt> & current_cluster = global_clusters[total_nb_cluster - 1]; UInt first_fragment = total_pairs(0, 0); UInt second_fragment = total_pairs(0, 1); total_pairs.erase(0); fragment_check_list.push(first_fragment); fragment_check_list.push(second_fragment); while (!fragment_check_list.empty()) { UInt current_fragment = fragment_check_list.front(); UInt * total_pairs_end = total_pairs.storage() + total_pairs.getSize() * 2; UInt * fragment_found = std::find(total_pairs.storage(), total_pairs_end, current_fragment); if (fragment_found != total_pairs_end) { UInt position = fragment_found - total_pairs.storage(); UInt pair = position / 2; UInt other_index = (position + 1) % 2; fragment_check_list.push(total_pairs(pair, other_index)); total_pairs.erase(pair); } else { fragment_check_list.pop(); current_cluster.insert(current_fragment); is_fragment_in_cluster(current_fragment) = true; } } } /// add to FragmentToCluster all local fragments for (UInt c = 0; c < global_nb_fragment; ++c) { if (!is_fragment_in_cluster(c)) { ++total_nb_cluster; global_clusters.resize(total_nb_cluster); std::set<UInt> & current_cluster = global_clusters[total_nb_cluster - 1]; current_cluster.insert(c); } } /// reorganize element groups to match global clusters for (UInt c = 0; c < global_clusters.size(); ++c) { /// create new element group corresponding to current cluster std::stringstream sstr; sstr << cluster_name_prefix << "_" << c; ElementGroup & cluster = group_manager.createElementGroup(sstr.str(), element_dimension, true); std::set<UInt>::iterator it = global_clusters[c].begin(); std::set<UInt>::iterator end = global_clusters[c].end(); /// append to current element group all fragments that belong to /// the same cluster if they exist for (; it != end; ++it) { Int local_index = *it - starting_index; if (local_index < 0 || local_index >= Int(nb_cluster)) continue; std::stringstream tmp_sstr; tmp_sstr << "tmp_" << cluster_name_prefix << "_" << local_index; auto eg_it = group_manager.element_group_find(tmp_sstr.str()); AKANTU_DEBUG_ASSERT(eg_it != group_manager.element_group_end(), "Temporary fragment \"" << tmp_sstr.str() << "\" not found"); cluster.append(*(eg_it->second)); group_manager.destroyElementGroup(tmp_sstr.str(), true); } } return total_nb_cluster; } private: /// functions for parallel communications inline UInt getNbData(const Array<Element> & elements, const SynchronizationTag & tag) const { if (tag == _gst_gm_clusters) return elements.getSize() * sizeof(UInt); return 0; } inline void packData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) const { if (tag != _gst_gm_clusters) return; Array<Element>::const_iterator<> el_it = elements.begin(); Array<Element>::const_iterator<> el_end = elements.end(); for (; el_it != el_end; ++el_it) { const Element & el = *el_it; /// for each element pack its global cluster index buffer << element_to_fragment(el.type, el.ghost_type)(el.element) + starting_index; } } inline void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) { if (tag != _gst_gm_clusters) return; Array<Element>::const_iterator<> el_it = elements.begin(); Array<Element>::const_iterator<> el_end = elements.end(); for (; el_it != el_end; ++el_it) { UInt distant_cluster; buffer >> distant_cluster; const Element & el = *el_it; UInt local_cluster = element_to_fragment(el.type, el.ghost_type)(el.element) + starting_index; distant_ids.insert(std::make_pair(local_cluster, distant_cluster)); } } private: GroupManager & group_manager; UInt element_dimension; std::string cluster_name_prefix; ElementTypeMapArray<UInt> & element_to_fragment; const ElementSynchronizer & element_synchronizer; UInt nb_cluster; DistantIDs distant_ids; UInt starting_index; }; /* -------------------------------------------------------------------------- */ /// \todo this function doesn't work in 1D UInt GroupManager::createBoundaryGroupFromGeometry() { UInt spatial_dimension = mesh.getSpatialDimension(); return createClusters(spatial_dimension - 1, "boundary"); } +/* -------------------------------------------------------------------------- */ +UInt GroupManager::createClusters( + UInt element_dimension, Mesh & mesh_facets, std::string cluster_name_prefix, + const GroupManager::ClusteringFilter & filter) { + return createClusters(element_dimension, cluster_name_prefix, filter, mesh_facets); +} + +/* -------------------------------------------------------------------------- */ +UInt GroupManager::createClusters( + UInt element_dimension, std::string cluster_name_prefix, + const GroupManager::ClusteringFilter & filter) { + std::unique_ptr<Mesh> mesh_facets; + if (!mesh_facets && element_dimension > 0) { + MeshAccessor mesh_accessor(const_cast<Mesh &>(mesh)); + mesh_facets = std::make_unique<Mesh>(mesh.getSpatialDimension(), + mesh_accessor.getNodesSharedPtr(), + "mesh_facets_for_clusters"); + + mesh_facets->defineMeshParent(mesh); + + MeshUtils::buildAllFacets(mesh, *mesh_facets, element_dimension, + element_dimension - 1); + } + + return createClusters(element_dimension, cluster_name_prefix, filter, *mesh_facets); +} + /* -------------------------------------------------------------------------- */ //// \todo if needed element list construction can be optimized by //// templating the filter class UInt GroupManager::createClusters(UInt element_dimension, std::string cluster_name_prefix, const GroupManager::ClusteringFilter & filter, - Mesh * mesh_facets) { + Mesh & mesh_facets) { AKANTU_DEBUG_IN(); UInt nb_proc = StaticCommunicator::getStaticCommunicator().getNbProc(); std::string tmp_cluster_name_prefix = cluster_name_prefix; ElementTypeMapArray<UInt> * element_to_fragment = nullptr; if (nb_proc > 1 && mesh.isDistributed()) { element_to_fragment = new ElementTypeMapArray<UInt>("element_to_fragment", id, memory_id); - element_to_fragment->initialize(mesh, _nb_component = 1, - _spatial_dimension = element_dimension, - _element_kind = _ek_not_defined, - _with_nb_element = true); + element_to_fragment->initialize( + mesh, _nb_component = 1, _spatial_dimension = element_dimension, + _element_kind = _ek_not_defined, _with_nb_element = true); // mesh.initElementTypeMapArray(*element_to_fragment, 1, element_dimension, // false, _ek_not_defined, true); tmp_cluster_name_prefix = "tmp_" + tmp_cluster_name_prefix; } - /// Get facets - bool mesh_facets_created = false; - - if (!mesh_facets && element_dimension > 0) { - mesh_facets = new Mesh(mesh.getSpatialDimension(), mesh.getNodes().getID(), - "mesh_facets_for_clusters"); - - mesh_facets->defineMeshParent(mesh); - - MeshUtils::buildAllFacets(mesh, *mesh_facets, element_dimension, - element_dimension - 1); - } - ElementTypeMapArray<bool> seen_elements("seen_elements", id, memory_id); seen_elements.initialize(mesh, _spatial_dimension = element_dimension, - _element_kind = _ek_not_defined, - _with_nb_element = true); + _element_kind = _ek_not_defined, + _with_nb_element = true); // mesh.initElementTypeMapArray(seen_elements, 1, element_dimension, false, // _ek_not_defined, true); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Element el; el.ghost_type = ghost_type; Mesh::type_iterator type_it = mesh.firstType(element_dimension, ghost_type, _ek_not_defined); Mesh::type_iterator type_end = mesh.lastType(element_dimension, ghost_type, _ek_not_defined); for (; type_it != type_end; ++type_it) { el.type = *type_it; el.kind = Mesh::getKind(*type_it); UInt nb_element = mesh.getNbElement(*type_it, ghost_type); Array<bool> & seen_elements_array = seen_elements(el.type, ghost_type); for (UInt e = 0; e < nb_element; ++e) { el.element = e; if (!filter(el)) seen_elements_array(e) = true; } } } Array<bool> checked_node(mesh.getNbNodes(), 1, false); UInt nb_cluster = 0; /// keep looping until all elements are seen for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Element uns_el; uns_el.ghost_type = ghost_type; Mesh::type_iterator type_it = mesh.firstType(element_dimension, ghost_type, _ek_not_defined); Mesh::type_iterator type_end = mesh.lastType(element_dimension, ghost_type, _ek_not_defined); for (; type_it != type_end; ++type_it) { uns_el.type = *type_it; Array<bool> & seen_elements_vec = seen_elements(uns_el.type, uns_el.ghost_type); for (UInt e = 0; e < seen_elements_vec.getSize(); ++e) { // skip elements that have been already seen if (seen_elements_vec(e) == true) continue; // set current element uns_el.element = e; seen_elements_vec(e) = true; /// create a new cluster std::stringstream sstr; sstr << tmp_cluster_name_prefix << "_" << nb_cluster; ElementGroup & cluster = createElementGroup(sstr.str(), element_dimension, true); ++nb_cluster; // point element are cluster by themself if (element_dimension == 0) { cluster.add(uns_el); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(uns_el.type); Vector<UInt> connect = mesh.getConnectivity(uns_el.type, uns_el.ghost_type) .begin(nb_nodes_per_element)[uns_el.element]; for (UInt n = 0; n < nb_nodes_per_element; ++n) { /// add element's nodes to the cluster UInt node = connect[n]; if (!checked_node(node)) { cluster.addNode(node); checked_node(node) = true; } } continue; } std::queue<Element> element_to_add; element_to_add.push(uns_el); /// keep looping until current cluster is complete (no more /// connected elements) while (!element_to_add.empty()) { /// take first element and erase it in the queue Element el = element_to_add.front(); element_to_add.pop(); /// if parallel, store cluster index per element if (nb_proc > 1 && mesh.isDistributed()) (*element_to_fragment)(el.type, el.ghost_type)(el.element) = nb_cluster - 1; /// add current element to the cluster cluster.add(el); const Array<Element> & element_to_facet = - mesh_facets->getSubelementToElement(el.type, el.ghost_type); + mesh_facets.getSubelementToElement(el.type, el.ghost_type); UInt nb_facet_per_element = element_to_facet.getNbComponent(); for (UInt f = 0; f < nb_facet_per_element; ++f) { const Element & facet = element_to_facet(el.element, f); if (facet == ElementNull) continue; const std::vector<Element> & connected_elements = - mesh_facets->getElementToSubelement( + mesh_facets.getElementToSubelement( facet.type, facet.ghost_type)(facet.element); for (UInt elem = 0; elem < connected_elements.size(); ++elem) { const Element & check_el = connected_elements[elem]; // check if this element has to be skipped if (check_el == ElementNull || check_el == el) continue; Array<bool> & seen_elements_vec_current = seen_elements(check_el.type, check_el.ghost_type); if (seen_elements_vec_current(check_el.element) == false) { seen_elements_vec_current(check_el.element) = true; element_to_add.push(check_el); } } } UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(el.type); Vector<UInt> connect = mesh.getConnectivity(el.type, el.ghost_type) .begin(nb_nodes_per_element)[el.element]; for (UInt n = 0; n < nb_nodes_per_element; ++n) { /// add element's nodes to the cluster UInt node = connect[n]; if (!checked_node(node)) { cluster.addNode(node, false); checked_node(node) = true; } } } } } } if (nb_proc > 1 && mesh.isDistributed()) { ClusterSynchronizer cluster_synchronizer( *this, element_dimension, cluster_name_prefix, *element_to_fragment, this->mesh.getElementSynchronizer(), nb_cluster); nb_cluster = cluster_synchronizer.synchronize(); delete element_to_fragment; } - if (mesh_facets_created) - delete mesh_facets; - if (mesh.isDistributed()) this->synchronizeGroupNames(); AKANTU_DEBUG_OUT(); return nb_cluster; } /* -------------------------------------------------------------------------- */ template <typename T> void GroupManager::createGroupsFromMeshData(const std::string & dataset_name) { std::set<std::string> group_names; const ElementTypeMapArray<T> & datas = mesh.getData<T>(dataset_name); typedef typename ElementTypeMapArray<T>::type_iterator type_iterator; std::map<std::string, UInt> group_dim; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { type_iterator type_it = datas.firstType(_all_dimensions, *gt); type_iterator type_end = datas.lastType(_all_dimensions, *gt); for (; type_it != type_end; ++type_it) { const Array<T> & dataset = datas(*type_it, *gt); UInt nb_element = mesh.getNbElement(*type_it, *gt); AKANTU_DEBUG_ASSERT(dataset.getSize() == nb_element, "Not the same number of elements (" << *type_it << ":" << *gt << ") in the map from MeshData (" << dataset.getSize() << ") " << dataset_name << " and in the mesh (" << nb_element << ")!"); for (UInt e(0); e < nb_element; ++e) { std::stringstream sstr; sstr << dataset(e); std::string gname = sstr.str(); group_names.insert(gname); std::map<std::string, UInt>::iterator it = group_dim.find(gname); if (it == group_dim.end()) { group_dim[gname] = mesh.getSpatialDimension(*type_it); } else { it->second = std::max(it->second, mesh.getSpatialDimension(*type_it)); } } } } std::set<std::string>::iterator git = group_names.begin(); std::set<std::string>::iterator gend = group_names.end(); for (; git != gend; ++git) createElementGroup(*git, group_dim[*git]); if (mesh.isDistributed()) this->synchronizeGroupNames(); Element el; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { el.ghost_type = *gt; type_iterator type_it = datas.firstType(_all_dimensions, *gt); type_iterator type_end = datas.lastType(_all_dimensions, *gt); for (; type_it != type_end; ++type_it) { el.type = *type_it; const Array<T> & dataset = datas(*type_it, *gt); UInt nb_element = mesh.getNbElement(*type_it, *gt); AKANTU_DEBUG_ASSERT(dataset.getSize() == nb_element, "Not the same number of elements in the map from " "MeshData and in the mesh!"); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(el.type); Array<UInt>::const_iterator<Vector<UInt>> cit = mesh.getConnectivity(*type_it, *gt).begin(nb_nodes_per_element); for (UInt e(0); e < nb_element; ++e, ++cit) { el.element = e; std::stringstream sstr; sstr << dataset(e); ElementGroup & group = getElementGroup(sstr.str()); group.add(el, false, false); const Vector<UInt> & connect = *cit; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connect[n]; group.addNode(node, false); } } } } git = group_names.begin(); for (; git != gend; ++git) { getElementGroup(*git).optimize(); } } template void GroupManager::createGroupsFromMeshData<std::string>( const std::string & dataset_name); template void GroupManager::createGroupsFromMeshData<UInt>(const std::string & dataset_name); /* -------------------------------------------------------------------------- */ void GroupManager::createElementGroupFromNodeGroup( const std::string & name, const std::string & node_group_name, UInt dimension) { NodeGroup & node_group = getNodeGroup(node_group_name); ElementGroup & group = createElementGroup(name, dimension, node_group); group.fillFromNodeGroup(); } /* -------------------------------------------------------------------------- */ void GroupManager::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "GroupManager [" << std::endl; std::set<std::string> node_group_seen; for (const_element_group_iterator it(element_group_begin()); it != element_group_end(); ++it) { it->second->printself(stream, indent + 1); node_group_seen.insert(it->second->getNodeGroup().getName()); } for (const_node_group_iterator it(node_group_begin()); it != node_group_end(); ++it) { if (node_group_seen.find(it->second->getName()) == node_group_seen.end()) it->second->printself(stream, indent + 1); } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ UInt GroupManager::getNbElementGroups(UInt dimension) const { if (dimension == _all_dimensions) return element_groups.size(); ElementGroups::const_iterator it = element_groups.begin(); ElementGroups::const_iterator end = element_groups.end(); UInt count = 0; for (; it != end; ++it) count += (it->second->getDimension() == dimension); return count; } /* -------------------------------------------------------------------------- */ void GroupManager::checkAndAddGroups(CommunicationBuffer & buffer) { AKANTU_DEBUG_IN(); UInt nb_node_group; buffer >> nb_node_group; AKANTU_DEBUG_INFO("Received " << nb_node_group << " node group names"); for (UInt ng = 0; ng < nb_node_group; ++ng) { std::string node_group_name; buffer >> node_group_name; if (node_groups.find(node_group_name) == node_groups.end()) { this->createNodeGroup(node_group_name); } AKANTU_DEBUG_INFO("Received node goup name: " << node_group_name); } UInt nb_element_group; buffer >> nb_element_group; AKANTU_DEBUG_INFO("Received " << nb_element_group << " element group names"); for (UInt eg = 0; eg < nb_element_group; ++eg) { std::string element_group_name; buffer >> element_group_name; std::string node_group_name; buffer >> node_group_name; UInt dim; buffer >> dim; AKANTU_DEBUG_INFO("Received element group name: " << element_group_name << " corresponding to a " << Int(dim) << "D group with node group " << node_group_name); NodeGroup & node_group = *node_groups[node_group_name]; if (element_groups.find(element_group_name) == element_groups.end()) { this->createElementGroup(element_group_name, dim, node_group); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GroupManager::fillBufferWithGroupNames( DynamicCommunicationBuffer & comm_buffer) const { AKANTU_DEBUG_IN(); // packing node group names; UInt nb_groups = this->node_groups.size(); comm_buffer << nb_groups; AKANTU_DEBUG_INFO("Sending " << nb_groups << " node group names"); NodeGroups::const_iterator nnames_it = node_groups.begin(); NodeGroups::const_iterator nnames_end = node_groups.end(); for (; nnames_it != nnames_end; ++nnames_it) { std::string node_group_name = nnames_it->first; comm_buffer << node_group_name; AKANTU_DEBUG_INFO("Sending node goupe name: " << node_group_name); } // packing element group names with there associated node group name nb_groups = this->element_groups.size(); comm_buffer << nb_groups; AKANTU_DEBUG_INFO("Sending " << nb_groups << " element group names"); ElementGroups::const_iterator gnames_it = this->element_groups.begin(); ElementGroups::const_iterator gnames_end = this->element_groups.end(); for (; gnames_it != gnames_end; ++gnames_it) { ElementGroup & element_group = *(gnames_it->second); std::string element_group_name = gnames_it->first; std::string node_group_name = element_group.getNodeGroup().getName(); UInt dim = element_group.getDimension(); comm_buffer << element_group_name; comm_buffer << node_group_name; comm_buffer << dim; AKANTU_DEBUG_INFO("Sending element group name: " << element_group_name << " corresponding to a " << Int(dim) << "D group with the node group " << node_group_name); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GroupManager::synchronizeGroupNames() { AKANTU_DEBUG_IN(); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int nb_proc = comm.getNbProc(); Int my_rank = comm.whoAmI(); if (nb_proc == 1) return; if (my_rank == 0) { for (Int p = 1; p < nb_proc; ++p) { CommunicationStatus status; comm.probe<char>(p, p, status); AKANTU_DEBUG_INFO("Got " << printMemorySize<char>(status.getSize()) << " from proc " << p); CommunicationBuffer recv_buffer(status.getSize()); comm.receive(recv_buffer, p, p); this->checkAndAddGroups(recv_buffer); } DynamicCommunicationBuffer comm_buffer; this->fillBufferWithGroupNames(comm_buffer); UInt buffer_size = comm_buffer.getSize(); comm.broadcast(buffer_size, 0); AKANTU_DEBUG_INFO("Initiating broadcast with " << printMemorySize<char>(comm_buffer.getSize())); comm.broadcast(comm_buffer, 0); } else { DynamicCommunicationBuffer comm_buffer; this->fillBufferWithGroupNames(comm_buffer); AKANTU_DEBUG_INFO("Sending " << printMemorySize<char>(comm_buffer.getSize()) << " to proc " << 0); comm.send(comm_buffer, 0, my_rank); UInt buffer_size = 0; comm.broadcast(buffer_size, 0); AKANTU_DEBUG_INFO("Receiving broadcast with " << printMemorySize<char>(comm_buffer.getSize())); CommunicationBuffer recv_buffer(buffer_size); comm.broadcast(recv_buffer, 0); this->checkAndAddGroups(recv_buffer); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ const ElementGroup & GroupManager::getElementGroup(const std::string & name) const { const_element_group_iterator it = element_group_find(name); if (it == element_group_end()) { AKANTU_EXCEPTION("There are no element groups named " << name << " associated to the group manager: " << id); } return *(it->second); } /* -------------------------------------------------------------------------- */ ElementGroup & GroupManager::getElementGroup(const std::string & name) { element_group_iterator it = element_group_find(name); if (it == element_group_end()) { AKANTU_EXCEPTION("There are no element groups named " << name << " associated to the group manager: " << id); } return *(it->second); } /* -------------------------------------------------------------------------- */ const NodeGroup & GroupManager::getNodeGroup(const std::string & name) const { const_node_group_iterator it = node_group_find(name); if (it == node_group_end()) { AKANTU_EXCEPTION("There are no node groups named " << name << " associated to the group manager: " << id); } return *(it->second); } /* -------------------------------------------------------------------------- */ NodeGroup & GroupManager::getNodeGroup(const std::string & name) { node_group_iterator it = node_group_find(name); if (it == node_group_end()) { AKANTU_EXCEPTION("There are no node groups named " << name << " associated to the group manager: " << id); } return *(it->second); } } // namespace akantu diff --git a/src/mesh/group_manager.hh b/src/mesh/group_manager.hh index d4b7dc1a3..731f71f2c 100644 --- a/src/mesh/group_manager.hh +++ b/src/mesh/group_manager.hh @@ -1,294 +1,304 @@ /** * @file group_manager.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@gmail.com> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Mon Nov 16 2015 * * @brief Stores information relevent to the notion of element and nodes *groups. * * @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/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_GROUP_MANAGER_HH__ #define __AKANTU_GROUP_MANAGER_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "element_type_map.hh" /* -------------------------------------------------------------------------- */ #include <set> /* -------------------------------------------------------------------------- */ namespace akantu { class ElementGroup; class NodeGroup; class Mesh; class Element; class ElementSynchronizer; template <bool> class CommunicationBufferTemplated; namespace dumper { class Field; } } // namespace akantu namespace akantu { /* -------------------------------------------------------------------------- */ class GroupManager { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ private: using ElementGroups = std::map<std::string, ElementGroup *>; using NodeGroups = std::map<std::string, NodeGroup *>; public: typedef std::set<ElementType> GroupManagerTypeSet; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: GroupManager(const Mesh & mesh, const ID & id = "group_manager", const MemoryID & memory_id = 0); virtual ~GroupManager(); /* ------------------------------------------------------------------------ */ /* Groups iterators */ /* ------------------------------------------------------------------------ */ public: typedef NodeGroups::iterator node_group_iterator; typedef ElementGroups::iterator element_group_iterator; typedef NodeGroups::const_iterator const_node_group_iterator; typedef ElementGroups::const_iterator const_element_group_iterator; #ifndef SWIG #define AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(group_type, function, \ param_in, param_out) \ inline BOOST_PP_CAT(BOOST_PP_CAT(const_, group_type), _iterator) \ BOOST_PP_CAT(BOOST_PP_CAT(group_type, _), function)(param_in) const { \ return BOOST_PP_CAT(group_type, s).function(param_out); \ }; \ \ inline BOOST_PP_CAT(group_type, _iterator) \ BOOST_PP_CAT(BOOST_PP_CAT(group_type, _), function)(param_in) { \ return BOOST_PP_CAT(group_type, s).function(param_out); \ } #define AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(group_type, function) \ AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION( \ group_type, function, BOOST_PP_EMPTY(), BOOST_PP_EMPTY()) AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(node_group, begin); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(node_group, end); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(element_group, begin); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(element_group, end); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(element_group, find, const std::string & name, name); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(node_group, find, const std::string & name, name); #endif /* ------------------------------------------------------------------------ */ /* Clustering filter */ /* ------------------------------------------------------------------------ */ public: class ClusteringFilter { public: virtual bool operator()(const Element &) const { return true; } }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// create an empty node group NodeGroup & createNodeGroup(const std::string & group_name, bool replace_group = false); /// create a node group from another node group but filtered template <typename T> NodeGroup & createFilteredNodeGroup(const std::string & group_name, const NodeGroup & node_group, T & filter); /// destroy a node group void destroyNodeGroup(const std::string & group_name); /// create an element group and the associated node group ElementGroup & createElementGroup(const std::string & group_name, UInt dimension = _all_dimensions, bool replace_group = false); /// create an element group from another element group but filtered template <typename T> ElementGroup & createFilteredElementGroup(const std::string & group_name, UInt dimension, const NodeGroup & node_group, T & filter); /// destroy an element group and the associated node group void destroyElementGroup(const std::string & group_name, bool destroy_node_group = false); /// destroy all element groups and the associated node groups void destroyAllElementGroups(bool destroy_node_groups = false); /// create a element group using an existing node group ElementGroup & createElementGroup(const std::string & group_name, UInt dimension, NodeGroup & node_group); /// create groups based on values stored in a given mesh data template <typename T> void createGroupsFromMeshData(const std::string & dataset_name); /// create boundaries group by a clustering algorithm \todo extend to parallel UInt createBoundaryGroupFromGeometry(); + /// create element clusters for a given dimension + UInt createClusters(UInt element_dimension, Mesh & mesh_facets, + std::string cluster_name_prefix = "cluster", + const ClusteringFilter & filter = ClusteringFilter()); + /// create element clusters for a given dimension UInt createClusters(UInt element_dimension, std::string cluster_name_prefix = "cluster", - const ClusteringFilter & filter = ClusteringFilter(), - Mesh * mesh_facets = nullptr); + const ClusteringFilter & filter = ClusteringFilter()); +private: + /// create element clusters for a given dimension + UInt createClusters(UInt element_dimension, std::string cluster_name_prefix, + const ClusteringFilter & filter, Mesh & mesh_facets); + +public: /// Create an ElementGroup based on a NodeGroup void createElementGroupFromNodeGroup(const std::string & name, const std::string & node_group, UInt dimension = _all_dimensions); virtual void printself(std::ostream & stream, int indent = 0) const; /// this function insure that the group names are present on all processors /// /!\ it is a SMP call void synchronizeGroupNames(); /// register an elemental field to the given group name (overloading for /// ElementalPartionField) #ifndef SWIG template <typename T, template <bool> class dump_type> dumper::Field * createElementalField( const ElementTypeMapArray<T> & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem = ElementTypeMap<UInt>()); /// register an elemental field to the given group name (overloading for /// ElementalField) template <typename T, template <class> class ret_type, template <class, template <class> class, bool> class dump_type> dumper::Field * createElementalField( const ElementTypeMapArray<T> & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem = ElementTypeMap<UInt>()); /// register an elemental field to the given group name (overloading for /// MaterialInternalField) template <typename T, /// type of InternalMaterialField template <typename, bool filtered> class dump_type> dumper::Field * createElementalField(const ElementTypeMapArray<T> & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem); template <typename type, bool flag, template <class, bool> class ftype> dumper::Field * createNodalField(const ftype<type, flag> * field, const std::string & group_name, UInt padding_size = 0); template <typename type, bool flag, template <class, bool> class ftype> dumper::Field * createStridedNodalField(const ftype<type, flag> * field, const std::string & group_name, UInt size, UInt stride, UInt padding_size); protected: /// fill a buffer with all the group names void fillBufferWithGroupNames( CommunicationBufferTemplated<false> & comm_buffer) const; /// take a buffer and create the missing groups localy void checkAndAddGroups(CommunicationBufferTemplated<true> & buffer); /// register an elemental field to the given group name template <class dump_type, typename field_type> inline dumper::Field * createElementalField(const field_type & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem); /// register an elemental field to the given group name template <class dump_type, typename field_type> inline dumper::Field * createElementalFilteredField(const field_type & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap<UInt> nb_data_per_elem); #endif /* ------------------------------------------------------------------------ */ /* Accessor */ /* ------------------------------------------------------------------------ */ public: const ElementGroup & getElementGroup(const std::string & name) const; const NodeGroup & getNodeGroup(const std::string & name) const; ElementGroup & getElementGroup(const std::string & name); NodeGroup & getNodeGroup(const std::string & name); UInt getNbElementGroups(UInt dimension = _all_dimensions) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id to create element and node groups ID id; /// memory_id to create element and node groups MemoryID memory_id; /// list of the node groups managed NodeGroups node_groups; /// list of the element groups managed ElementGroups element_groups; /// Mesh to which the element belongs const Mesh & mesh; }; /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const GroupManager & _this) { _this.printself(stream); return stream; } } // namespace akantu #endif /* __AKANTU_GROUP_MANAGER_HH__ */ diff --git a/src/mesh/mesh.cc b/src/mesh/mesh.cc index 795934832..c06e28f3d 100644 --- a/src/mesh/mesh.cc +++ b/src/mesh/mesh.cc @@ -1,523 +1,429 @@ /** * @file mesh.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Jan 22 2016 * * @brief class handling meshes * * @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 <sstream> #include "aka_config.hh" /* -------------------------------------------------------------------------- */ #include "element_class.hh" #include "group_manager_inline_impl.cc" #include "mesh.hh" #include "mesh_io.hh" /* -------------------------------------------------------------------------- */ #include "element_synchronizer.hh" #include "mesh_utils_distribution.hh" #include "node_synchronizer.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #include "dumper_field.hh" #include "dumper_internal_material_field.hh" #endif /* -------------------------------------------------------------------------- */ namespace akantu { const Element ElementNull(_not_defined, 0); /* -------------------------------------------------------------------------- */ void Element::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "Element [" << type << ", " << element << ", " << ghost_type << "]"; } /* -------------------------------------------------------------------------- */ Mesh::Mesh(UInt spatial_dimension, const ID & id, const MemoryID & memory_id, StaticCommunicator & communicator) : Memory(id, memory_id), - GroupManager(*this, id + ":group_manager", memory_id), nodes(NULL), - nodes_global_ids(nullptr), nodes_type(0, 1, id + ":nodes_type"), - nb_global_nodes(0), created_nodes(true), + GroupManager(*this, id + ":group_manager", memory_id), + nodes_type(0, 1, id + ":nodes_type"), connectivities("connectivities", id, memory_id), normals("normals", id, memory_id), spatial_dimension(spatial_dimension), - types_offsets(Array<UInt>((UInt)_max_element_type + 1, 1)), - ghost_types_offsets(Array<UInt>((UInt)_max_element_type + 1, 1)), lower_bounds(spatial_dimension, 0.), upper_bounds(spatial_dimension, 0.), size(spatial_dimension, 0.), local_lower_bounds(spatial_dimension, 0.), local_upper_bounds(spatial_dimension, 0.), - mesh_data("mesh_data", id, memory_id), mesh_facets(nullptr), - mesh_parent(nullptr), is_mesh_facets(false), is_distributed(false), - communicator(&communicator), element_synchronizer(nullptr), - node_synchronizer(nullptr) { + mesh_data("mesh_data", id, memory_id), communicator(&communicator) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Mesh::Mesh(UInt spatial_dimension, StaticCommunicator & communicator, const ID & id, const MemoryID & memory_id) : Mesh(spatial_dimension, id, memory_id, communicator) { AKANTU_DEBUG_IN(); + this->nodes = - &(alloc<Real>(id + ":coordinates", memory_id, spatial_dimension)); + std::make_shared<Array<Real>>(0, spatial_dimension, id + ":coordinates"); + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Mesh::Mesh(UInt spatial_dimension, const ID & id, const MemoryID & memory_id) : Mesh(spatial_dimension, StaticCommunicator::getStaticCommunicator(), id, memory_id) {} -/* -------------------------------------------------------------------------- */ -Mesh::Mesh(UInt spatial_dimension, const ID & nodes_id, const ID & id, - const MemoryID & memory_id) - : Mesh(spatial_dimension, id, memory_id, - StaticCommunicator::getStaticCommunicator()) { - this->nodes = &(this->getArray<Real>(nodes_id)); - this->nb_global_nodes = this->nodes->getSize(); - this->computeBoundingBox(); -} +// /* -------------------------------------------------------------------------- +// */ Mesh::Mesh(UInt spatial_dimension, const ID & nodes_id, const ID & id, +// const MemoryID & memory_id) +// : Mesh(spatial_dimension, id, memory_id, +// StaticCommunicator::getStaticCommunicator()) { +// this->nodes = &(this->getArray<Real>(nodes_id)); +// this->nb_global_nodes = this->nodes->getSize(); +// this->computeBoundingBox(); +// } /* -------------------------------------------------------------------------- */ -Mesh::Mesh(UInt spatial_dimension, Array<Real> & nodes, const ID & id, - const MemoryID & memory_id) +Mesh::Mesh(UInt spatial_dimension, std::shared_ptr<Array<Real>> nodes, + const ID & id, const MemoryID & memory_id) : Mesh(spatial_dimension, id, memory_id, StaticCommunicator::getStaticCommunicator()) { - this->nodes = &nodes; + this->nodes = nodes; this->nb_global_nodes = this->nodes->getSize(); this->computeBoundingBox(); } /* -------------------------------------------------------------------------- */ Mesh & Mesh::initMeshFacets(const ID & id) { AKANTU_DEBUG_IN(); if (!mesh_facets) { - mesh_facets = new Mesh(spatial_dimension, *(this->nodes), - getID() + ":" + id, getMemoryID()); + mesh_facets = std::make_unique<Mesh>(spatial_dimension, this->nodes, + getID() + ":" + id, getMemoryID()); mesh_facets->mesh_parent = this; mesh_facets->is_mesh_facets = true; } AKANTU_DEBUG_OUT(); return *mesh_facets; } /* -------------------------------------------------------------------------- */ void Mesh::defineMeshParent(const Mesh & mesh) { AKANTU_DEBUG_IN(); this->mesh_parent = &mesh; this->is_mesh_facets = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -Mesh::~Mesh() { - AKANTU_DEBUG_IN(); - - delete mesh_facets; - - delete element_synchronizer; - delete node_synchronizer; - - AKANTU_DEBUG_OUT(); -} +Mesh::~Mesh() = default; /* -------------------------------------------------------------------------- */ void Mesh::read(const std::string & filename, const MeshIOType & mesh_io_type) { MeshIO mesh_io; mesh_io.read(filename, *this, mesh_io_type); type_iterator it = this->firstType(spatial_dimension, _not_ghost, _ek_not_defined); type_iterator last = this->lastType(spatial_dimension, _not_ghost, _ek_not_defined); if (it == last) AKANTU_EXCEPTION( "The mesh contained in the file " << filename << " does not seem to be of the good dimension." << " No element of dimension " << spatial_dimension << " where read."); + + this->computeBoundingBox(); } /* -------------------------------------------------------------------------- */ void Mesh::write(const std::string & filename, const MeshIOType & mesh_io_type) { MeshIO mesh_io; mesh_io.write(filename, *this, mesh_io_type); } /* -------------------------------------------------------------------------- */ void Mesh::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "Mesh [" << std::endl; stream << space << " + id : " << getID() << std::endl; stream << space << " + spatial dimension : " << this->spatial_dimension << std::endl; stream << space << " + nodes [" << std::endl; nodes->printself(stream, indent + 2); stream << space << " + connectivities [" << std::endl; connectivities.printself(stream, indent + 2); stream << space << " ]" << std::endl; GroupManager::printself(stream, indent + 1); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ void Mesh::computeBoundingBox() { AKANTU_DEBUG_IN(); for (UInt k = 0; k < spatial_dimension; ++k) { local_lower_bounds(k) = std::numeric_limits<double>::max(); local_upper_bounds(k) = -std::numeric_limits<double>::max(); } for (UInt i = 0; i < nodes->getSize(); ++i) { // if(!isPureGhostNode(i)) for (UInt k = 0; k < spatial_dimension; ++k) { local_lower_bounds(k) = std::min(local_lower_bounds[k], (*nodes)(i, k)); local_upper_bounds(k) = std::max(local_upper_bounds[k], (*nodes)(i, k)); } } if (this->is_distributed) { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Matrix<Real> reduce_bounds(spatial_dimension, 2); for (UInt k = 0; k < spatial_dimension; ++k) { reduce_bounds(k, 0) = local_lower_bounds(k); reduce_bounds(k, 1) = -local_upper_bounds(k); } comm.allReduce(reduce_bounds, _so_min); for (UInt k = 0; k < spatial_dimension; ++k) { lower_bounds(k) = reduce_bounds(k, 0); upper_bounds(k) = -reduce_bounds(k, 1); } } else { this->lower_bounds = this->local_lower_bounds; this->upper_bounds = this->local_upper_bounds; } size = upper_bounds - lower_bounds; AKANTU_DEBUG_OUT(); } -// /* -------------------------------------------------------------------------- -// */ template <typename T> void -// Mesh::initElementTypeMapArray(ElementTypeMapArray<T> & vect, -// UInt nb_component, UInt dim, GhostType gt, -// const T & default_value, -// const bool & -// flag_nb_node_per_elem_multiply, -// ElementKind element_kind, -// bool size_to_nb_element) const { -// AKANTU_DEBUG_IN(); - -// for (auto type : elementTypes(dim, gt, element_kind)) { -// // determines the number of component -// UInt nb_comp = nb_component; -// if (flag_nb_node_per_elem_multiply) -// nb_comp *= Mesh::getNbNodesPerElement(type); - -// // determines the size -// UInt size = 0; -// if (size_to_nb_element) -// size = this->getNbElement(type, gt); - -// // allocate -// if (not vect.exists(type, gt)) -// vect.alloc(size, nb_comp, type, gt, default_value); -// } -// AKANTU_DEBUG_OUT(); -// } - -// /* -------------------------------------------------------------------------- -// */ template <typename T> void -// Mesh::initElementTypeMapArray(ElementTypeMapArray<T> & vect, -// UInt nb_component, UInt dim, -// const bool & -// flag_nb_node_per_elem_multiply, -// ElementKind element_kind, -// bool size_to_nb_element) const { -// AKANTU_DEBUG_IN(); - -// for (auto ghost_type : ghost_types) { -// this->initElementTypeMapArray(vect, nb_component, dim, ghost_types, -// flag_nb_node_per_elem_multiply, -// element_kind, size_to_nb_element); -// } - -// AKANTU_DEBUG_OUT(); -// } - -// /* -------------------------------------------------------------------------- -// */ template <typename T> void -// Mesh::initElementTypeMapArray(ElementTypeMapArray<T> & vect, -// UInt nb_component, UInt dim, GhostType gt, -// const bool & -// flag_nb_node_per_elem_multiply, -// ElementKind element_kind, -// bool size_to_nb_element) const { -// AKANTU_DEBUG_IN(); - -// this->initElementTypeMapArray(vect, nb_component, dim, gt, T(), -// flag_nb_node_per_elem_multiply, element_kind, -// size_to_nb_element); - -// AKANTU_DEBUG_OUT(); -// } - -// /* -------------------------------------------------------------------------- -// */ template <typename T> void -// Mesh::initElementTypeMapArray(ElementTypeMapArray<T> & vect, -// UInt nb_component, UInt dim, GhostType gt, -// const T & default_value, -// const bool & -// flag_nb_node_per_elem_multiply, -// ElementKind element_kind, -// bool size_to_nb_element) const { -// AKANTU_DEBUG_IN(); - -// for (auto type : elementTypes(dim, gt, element_kind)) { -// // determines the number of component -// UInt nb_comp = nb_component; -// if (flag_nb_node_per_elem_multiply) -// nb_comp *= Mesh::getNbNodesPerElement(type); - -// // determines the size -// UInt size = 0; -// if (size_to_nb_element) -// size = this->getNbElement(type, gt); - -// // allocate -// if (not vect.exists(type, gt)) -// vect.alloc(size, nb_comp, type, gt, default_value); -// } -// AKANTU_DEBUG_OUT(); -// } - -// /* -------------------------------------------------------------------------- -// */ -/* -#define AKANTU_INSTANTIATE_INIT(type) \ - template void Mesh::initElementTypeMapArray<type>( \ - ElementTypeMapArray<type> & vect, UInt nb_component, UInt dim, \ - const bool & flag_nb_elem_multiply, ElementKind element_kind, \ - bool size_to_nb_element) const; \ - template void Mesh::initElementTypeMapArray<type>( \ - ElementTypeMapArray<type> & vect, UInt nb_component, UInt dim, \ - GhostType gt, const bool & flag_nb_elem_multiply, \ - ElementKind element_kind, bool size_to_nb_element) const; \ - template void Mesh::initElementTypeMapArray<type>( \ - ElementTypeMapArray<type> & vect, UInt nb_component, UInt dim, \ - GhostType gt, const type & default_value, \ - const bool & flag_nb_elem_multiply, ElementKind element_kind, \ bool -size_to_nb_element) const -*/ -// AKANTU_INSTANTIATE_INIT(Real); -// AKANTU_INSTANTIATE_INIT(UInt); -// AKANTU_INSTANTIATE_INIT(Int); -// AKANTU_INSTANTIATE_INIT(bool); - /* -------------------------------------------------------------------------- */ void Mesh::initNormals() { normals.initialize(*this, _nb_component = spatial_dimension, _spatial_dimension = spatial_dimension, _element_kind = _ek_not_defined); - // this->initElementTypeMapArray(normals, spatial_dimension, - // spatial_dimension, - // false, _ek_not_defined); } /* -------------------------------------------------------------------------- */ void Mesh::getGlobalConnectivity( ElementTypeMapArray<UInt> & global_connectivity, UInt dimension, GhostType ghost_type) { AKANTU_DEBUG_IN(); for (auto type : elementTypes(dimension, ghost_type)) { - Array<UInt> & local_conn = connectivities(type, ghost_type); - Array<UInt> & g_connectivity = global_connectivity(type, ghost_type); - - if (!nodes_global_ids) - nodes_global_ids = mesh_parent->nodes_global_ids; - - UInt * local_c = local_conn.storage(); - UInt * global_c = g_connectivity.storage(); - - UInt nb_terms = local_conn.getSize() * local_conn.getNbComponent(); - - for (UInt i = 0; i < nb_terms; ++i, ++local_c, ++global_c) - *global_c = (*nodes_global_ids)(*local_c); + auto & local_conn = connectivities(type, ghost_type); + auto & g_connectivity = global_connectivity(type, ghost_type); + + UInt nb_nodes = local_conn.getSize() * local_conn.getNbComponent(); + + if (!nodes_global_ids && is_mesh_facets) { + std::transform( + local_conn.begin_reinterpret(nb_nodes), + local_conn.end_reinterpret(nb_nodes), + g_connectivity.begin_reinterpret(nb_nodes), + [& node_ids = *mesh_parent->nodes_global_ids](UInt l)->UInt { + return node_ids(l); + }); + } else { + std::transform(local_conn.begin_reinterpret(nb_nodes), + local_conn.end_reinterpret(nb_nodes), + g_connectivity.begin_reinterpret(nb_nodes), + [& node_ids = *nodes_global_ids](UInt l)->UInt { + return node_ids(l); + }); + } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ - DumperIOHelper & Mesh::getGroupDumper(const std::string & dumper_name, const std::string & group_name) { - if (group_name == "all") return this->getDumper(dumper_name); else return element_groups[group_name]->getDumper(dumper_name); } /* -------------------------------------------------------------------------- */ template <typename T> ElementTypeMap<UInt> Mesh::getNbDataPerElem(ElementTypeMapArray<T> & arrays, const ElementKind & element_kind) { - ElementTypeMap<UInt> nb_data_per_elem; for (auto type : elementTypes(spatial_dimension, _not_ghost, element_kind)) { UInt nb_elements = this->getNbElement(type); auto & array = arrays(type); nb_data_per_elem(type) = array.getNbComponent() * array.getSize(); nb_data_per_elem(type) /= nb_elements; } return nb_data_per_elem; } /* -------------------------------------------------------------------------- */ - template ElementTypeMap<UInt> Mesh::getNbDataPerElem(ElementTypeMapArray<Real> & array, const ElementKind & element_kind); template ElementTypeMap<UInt> Mesh::getNbDataPerElem(ElementTypeMapArray<UInt> & array, const ElementKind & element_kind); /* -------------------------------------------------------------------------- */ - #ifdef AKANTU_USE_IOHELPER - template <typename T> dumper::Field * Mesh::createFieldFromAttachedData(const std::string & field_id, const std::string & group_name, const ElementKind & element_kind) { dumper::Field * field = nullptr; ElementTypeMapArray<T> * internal = nullptr; try { internal = &(this->getData<T>(field_id)); } catch (...) { return nullptr; } ElementTypeMap<UInt> nb_data_per_elem = this->getNbDataPerElem(*internal, element_kind); field = this->createElementalField<T, dumper::InternalMaterialField>( *internal, group_name, this->spatial_dimension, element_kind, nb_data_per_elem); return field; } template dumper::Field * Mesh::createFieldFromAttachedData<Real>(const std::string & field_id, const std::string & group_name, const ElementKind & element_kind); template dumper::Field * Mesh::createFieldFromAttachedData<UInt>(const std::string & field_id, const std::string & group_name, const ElementKind & element_kind); - #endif /* -------------------------------------------------------------------------- */ void Mesh::distribute() { this->distribute(StaticCommunicator::getStaticCommunicator()); } /* -------------------------------------------------------------------------- */ void Mesh::distribute(StaticCommunicator & communicator) { AKANTU_DEBUG_ASSERT(is_distributed == false, "This mesh is already distribute"); this->communicator = &communicator; - this->element_synchronizer = - new ElementSynchronizer(*this, this->getID() + ":element_synchronizer", - this->getMemoryID(), true); + this->element_synchronizer = std::make_unique<ElementSynchronizer>( + *this, this->getID() + ":element_synchronizer", this->getMemoryID(), + true); - this->node_synchronizer = new NodeSynchronizer( + this->node_synchronizer = std::make_unique<NodeSynchronizer>( *this, this->getID() + ":node_synchronizer", this->getMemoryID(), true); Int psize = this->communicator->getNbProc(); #ifdef AKANTU_USE_SCOTCH Int prank = this->communicator->whoAmI(); if (prank == 0) { MeshPartitionScotch partition(*this, spatial_dimension); partition.partitionate(psize); MeshUtilsDistribution::distributeMeshCentralized(*this, 0, partition); } else { MeshUtilsDistribution::distributeMeshCentralized(*this, 0); } #else if (!(psize == 1)) { AKANTU_DEBUG_ERROR("Cannot distribute a mesh without a partitioning tool"); } #endif this->is_distributed = true; this->element_synchronizer->buildPrankToElement(); this->computeBoundingBox(); } /* -------------------------------------------------------------------------- */ +void Mesh::getAssociatedElements(const Array<UInt> & node_list, + Array<Element> & elements) { + for(const auto & node : node_list) + for(const auto & element : *nodes_to_elements[node]) + elements.push_back(element); +} + +/* -------------------------------------------------------------------------- */ +void Mesh::fillNodesToElements() { + Element e; + + UInt nb_nodes = nodes->getSize(); + for (UInt n = 0; n < nb_nodes; ++n) { + this->nodes_to_elements[n]->clear(); + } + + for (auto ghost_type : ghost_types) { + e.ghost_type = ghost_type; + for (const auto & type : + elementTypes(spatial_dimension, ghost_type, _ek_not_defined)) { + e.type = type; + e.kind = getKind(type); + + UInt nb_element = this->getNbElement(type, ghost_type); + Array<UInt>::const_iterator<Vector<UInt>> conn_it = + connectivities(type, ghost_type).begin(Mesh::getNbNodesPerElement(type)); + + for (UInt el = 0; el < nb_element; ++el, ++conn_it) { + e.element = el; + const Vector<UInt> & conn = *conn_it; + for (UInt n = 0; n < conn.size(); ++n) + nodes_to_elements[conn(n)]->insert(e); + } + } + } +} } // namespace akantu diff --git a/src/mesh/mesh.hh b/src/mesh/mesh.hh index 16aac2d0f..312202a7b 100644 --- a/src/mesh/mesh.hh +++ b/src/mesh/mesh.hh @@ -1,613 +1,595 @@ /** * @file mesh.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Jan 14 2016 * * @brief the class representing the meshes * * @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_MESH_HH__ #define __AKANTU_MESH_HH__ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" #include "aka_event_handler_manager.hh" #include "aka_memory.hh" #include "dumpable.hh" #include "element.hh" #include "element_class.hh" #include "element_type_map.hh" #include "group_manager.hh" #include "mesh_data.hh" #include "mesh_events.hh" /* -------------------------------------------------------------------------- */ #include <set> /* -------------------------------------------------------------------------- */ namespace akantu { class StaticCommunicator; class ElementSynchronizer; class NodeSynchronizer; -} // akantu +} // namespace akantu namespace akantu { /* -------------------------------------------------------------------------- */ /* Mesh */ /* -------------------------------------------------------------------------- */ /** * @class Mesh this contain the coordinates of the nodes in the Mesh.nodes * Array, and the connectivity. The connectivity are stored in by element * types. * * In order to loop on all element you have to loop on all types like this : * @code{.cpp} Mesh::type_iterator it = mesh.firstType(dim, ghost_type); Mesh::type_iterator end = mesh.lastType(dim, ghost_type); for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it); const Array<UInt> & conn = mesh.getConnectivity(*it); for(UInt e = 0; e < nb_element; ++e) { ... } } @endcode */ class Mesh : protected Memory, public EventHandlerManager<MeshEventHandler>, public GroupManager, public Dumpable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ private: /// default constructor used for chaining, the last parameter is just to /// differentiate constructors Mesh(UInt spatial_dimension, const ID & id, const MemoryID & memory_id, StaticCommunicator & communicator); public: /// constructor that create nodes coordinates array Mesh(UInt spatial_dimension, const ID & id = "mesh", const MemoryID & memory_id = 0); /// mesh not distributed and not using the default communicator Mesh(UInt spatial_dimension, StaticCommunicator & communicator, const ID & id = "mesh", const MemoryID & memory_id = 0); /// constructor that use an existing nodes coordinates array, by knowing its /// ID - Mesh(UInt spatial_dimension, const ID & nodes_id, const ID & id, - const MemoryID & memory_id = 0); + // Mesh(UInt spatial_dimension, const ID & nodes_id, const ID & id, + // const MemoryID & memory_id = 0); /** * constructor that use an existing nodes coordinates * array, by getting the vector of coordinates */ - Mesh(UInt spatial_dimension, Array<Real> & nodes, const ID & id = "mesh", + Mesh(UInt spatial_dimension, std::shared_ptr<Array<Real>> nodes, const ID & id = "mesh", const MemoryID & memory_id = 0); virtual ~Mesh(); /// @typedef ConnectivityTypeList list of the types present in a Mesh typedef std::set<ElementType> ConnectivityTypeList; /// read the mesh from a file void read(const std::string & filename, const MeshIOType & mesh_io_type = _miot_auto); /// write the mesh to a file void write(const std::string & filename, const MeshIOType & mesh_io_type = _miot_auto); private: /// initialize the connectivity to NULL and other stuff void init(); + /// function that computes the bounding box (fills xmin, xmax) + void computeBoundingBox(); + /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// patitionate the mesh among the processors involved in their computation virtual void distribute(StaticCommunicator & communicator); virtual void distribute(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; - /// function that computes the bounding box (fills xmin, xmax) - void computeBoundingBox(); - - // /// init a by-element-type real vector with provided ids - // template <typename T> - // void - // initElementTypeMapArray(ElementTypeMapArray<T> & v, UInt nb_component, - // UInt spatial_dimension, - // const bool & flag_nb_node_per_elem_multiply = false, - // ElementKind element_kind = _ek_regular, - // bool size_to_nb_element = false) - // const; /// @todo: think about nicer way to do it - // template <typename T> - // void - // initElementTypeMapArray(ElementTypeMapArray<T> & v, UInt nb_component, - // UInt spatial_dimension, GhostType ghost_type, - // const bool & flag_nb_node_per_elem_multiply = false, - // ElementKind element_kind = _ek_regular, - // bool size_to_nb_element = false) - // const; /// @todo: think about nicer way to do it - - // template <typename T> - // void - // initElementTypeMapArray(ElementTypeMapArray<T> & v, UInt nb_component, - // UInt spatial_dimension, GhostType ghost_type, - // const T & default_value, - // const bool & flag_nb_node_per_elem_multiply = false, - // ElementKind element_kind = _ek_regular, - // bool size_to_nb_element = false) - // const; /// @todo: think about nicer way to do it - /// extract coordinates of nodes from an element template <typename T> inline void extractNodalValuesFromElement(const Array<T> & nodal_values, T * elemental_values, UInt * connectivity, UInt n_nodes, UInt nb_degree_of_freedom) const; // /// extract coordinates of nodes from a reversed element // inline void extractNodalCoordinatesFromPBCElement(Real * local_coords, // UInt * connectivity, // UInt n_nodes); /// convert a element to a linearized element inline UInt elementToLinearized(const Element & elem) const; /// convert a linearized element to an element inline Element linearizedToElement(UInt linearized_element) const; /// update the types offsets array for the conversions - inline void updateTypesOffsets(const GhostType & ghost_type); + //inline void updateTypesOffsets(const GhostType & ghost_type); /// add a Array of connectivity for the type <type>. inline void addConnectivityType(const ElementType & type, const GhostType & ghost_type = _not_ghost); /* ------------------------------------------------------------------------ */ template <class Event> inline void sendEvent(Event & event) { // if(event.getList().getSize() != 0) EventHandlerManager<MeshEventHandler>::sendEvent<Event>(event); } /* ------------------------------------------------------------------------ */ template <typename T> inline void removeNodesFromArray(Array<T> & vect, const Array<UInt> & new_numbering); /// initialize normals void initNormals(); /// init facets' mesh Mesh & initMeshFacets(const ID & id = "mesh_facets"); /// define parent mesh void defineMeshParent(const Mesh & mesh); /// get global connectivity array void getGlobalConnectivity(ElementTypeMapArray<UInt> & global_connectivity, UInt dimension, GhostType ghost_type); +public: + void getAssociatedElements(const Array<UInt> & node_list, + Array<Element> & elements); + +private: + /// fills the nodes_to_elements structure + void fillNodesToElements(); + /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the id of the mesh AKANTU_GET_MACRO(ID, Memory::id, const ID &); /// get the id of the mesh AKANTU_GET_MACRO(MemoryID, Memory::memory_id, const MemoryID &); /// get the spatial dimension of the mesh = number of component of the /// coordinates AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); /// get the nodes Array aka coordinates AKANTU_GET_MACRO(Nodes, *nodes, const Array<Real> &); AKANTU_GET_MACRO_NOT_CONST(Nodes, *nodes, Array<Real> &); /// get the normals for the elements AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Normals, normals, Real); /// get the number of nodes AKANTU_GET_MACRO(NbNodes, nodes->getSize(), UInt); /// get the Array of global ids of the nodes (only used in parallel) AKANTU_GET_MACRO(GlobalNodesIds, *nodes_global_ids, const Array<UInt> &); AKANTU_GET_MACRO_NOT_CONST(GlobalNodesIds, *nodes_global_ids, Array<UInt> &); /// get the global id of a node inline UInt getNodeGlobalId(UInt local_id) const; /// get the global id of a node inline UInt getNodeLocalId(UInt global_id) const; /// get the global number of nodes inline UInt getNbGlobalNodes() const; /// get the nodes type Array AKANTU_GET_MACRO(NodesType, nodes_type, const Array<NodeType> &); protected: AKANTU_GET_MACRO_NOT_CONST(NodesType, nodes_type, Array<NodeType> &); public: inline NodeType getNodeType(UInt local_id) const; /// say if a node is a pure ghost node inline bool isPureGhostNode(UInt n) const; /// say if a node is pur local or master node inline bool isLocalOrMasterNode(UInt n) const; inline bool isLocalNode(UInt n) const; inline bool isMasterNode(UInt n) const; inline bool isSlaveNode(UInt n) const; AKANTU_GET_MACRO(LowerBounds, lower_bounds, const Vector<Real> &); AKANTU_GET_MACRO(UpperBounds, upper_bounds, const Vector<Real> &); AKANTU_GET_MACRO(LocalLowerBounds, local_lower_bounds, const Vector<Real> &); AKANTU_GET_MACRO(LocalUpperBounds, local_upper_bounds, const Vector<Real> &); /// get the connectivity Array for a given type AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Connectivity, connectivities, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Connectivity, connectivities, UInt); AKANTU_GET_MACRO(Connectivities, connectivities, const ElementTypeMapArray<UInt> &); /// get the number of element of a type in the mesh inline UInt getNbElement(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /// get the number of element for a given ghost_type and a given dimension inline UInt getNbElement(const UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & kind = _ek_not_defined) const; - /// get the connectivity list either for the elements or the ghost elements - inline const ConnectivityTypeList & - getConnectivityTypeList(const GhostType & ghost_type = _not_ghost) const; + // /// get the connectivity list either for the elements or the ghost elements + // inline const ConnectivityTypeList & + // getConnectivityTypeList(const GhostType & ghost_type = _not_ghost) const; /// compute the barycenter of a given element inline void getBarycenter(UInt element, const ElementType & type, Real * barycenter, GhostType ghost_type = _not_ghost) const; inline void getBarycenter(const Element & element, Vector<Real> & barycenter) const; /// get the element connected to a subelement const Array<std::vector<Element>> & getElementToSubelement(const ElementType & el_type, const GhostType & ghost_type = _not_ghost) const; /// get the element connected to a subelement Array<std::vector<Element>> & getElementToSubelement(const ElementType & el_type, const GhostType & ghost_type = _not_ghost); /// get the subelement connected to an element const Array<Element> & getSubelementToElement(const ElementType & el_type, const GhostType & ghost_type = _not_ghost) const; /// get the subelement connected to an element Array<Element> & getSubelementToElement(const ElementType & el_type, const GhostType & ghost_type = _not_ghost); /// get a name field associated to the mesh template <typename T> inline const Array<T> & getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type = _not_ghost) const; /// get a name field associated to the mesh template <typename T> inline Array<T> & getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type = _not_ghost); /// register a new ElementalTypeMap in the MeshData template <typename T> inline ElementTypeMapArray<T> & registerData(const std::string & data_name); /// get a name field associated to the mesh template <typename T> inline const ElementTypeMapArray<T> & getData(const std::string & data_name) const; /// get a name field associated to the mesh template <typename T> inline ElementTypeMapArray<T> & getData(const std::string & data_name); template <typename T> ElementTypeMap<UInt> getNbDataPerElem(ElementTypeMapArray<T> & array, const ElementKind & element_kind); template <typename T> dumper::Field * createFieldFromAttachedData(const std::string & field_id, const std::string & group_name, const ElementKind & element_kind); /// templated getter returning the pointer to data in MeshData (modifiable) template <typename T> - inline Array<T> * + inline Array<T> & getDataPointer(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type = _not_ghost, UInt nb_component = 1, bool size_to_nb_element = true, bool resize_with_parent = false); /// Facets mesh accessor inline const Mesh & getMeshFacets() const; inline Mesh & getMeshFacets(); /// Parent mesh accessor inline const Mesh & getMeshParent() const; inline bool isMeshFacets() const { return this->is_mesh_facets; } /// defines is the mesh is distributed or not inline bool isDistributed() const { return this->is_distributed; } #ifndef SWIG /// return the dumper from a group and and a dumper name DumperIOHelper & getGroupDumper(const std::string & dumper_name, const std::string & group_name); #endif /* ------------------------------------------------------------------------ */ /* Wrappers on ElementClass functions */ /* ------------------------------------------------------------------------ */ public: /// get the number of nodes per element for a given element type static inline UInt getNbNodesPerElement(const ElementType & type); /// get the number of nodes per element for a given element type considered as /// a first order element static inline ElementType getP1ElementType(const ElementType & type); /// get the kind of the element type static inline ElementKind getKind(const ElementType & type); /// get spatial dimension of a type of element static inline UInt getSpatialDimension(const ElementType & type); /// get number of facets of a given element type static inline UInt getNbFacetsPerElement(const ElementType & type); /// get number of facets of a given element type static inline UInt getNbFacetsPerElement(const ElementType & type, UInt t); /// get local connectivity of a facet for a given facet type static inline MatrixProxy<UInt> getFacetLocalConnectivity(const ElementType & type, UInt t = 0); /// get connectivity of facets for a given element inline Matrix<UInt> getFacetConnectivity(const Element & element, UInt t = 0) const; /// get the number of type of the surface element associated to a given /// element type static inline UInt getNbFacetTypes(const ElementType & type, UInt t = 0); /// get the type of the surface element associated to a given element static inline ElementType getFacetType(const ElementType & type, UInt t = 0); /// get all the type of the surface element associated to a given element static inline VectorProxy<ElementType> getAllFacetTypes(const ElementType & type); /// get the number of nodes in the given element list static inline UInt getNbNodesPerElementList(const Array<Element> & elements); /* ------------------------------------------------------------------------ */ /* Element type Iterator */ /* ------------------------------------------------------------------------ */ - typedef ElementTypeMapArray<UInt, ElementType>::type_iterator type_iterator; - typedef ElementTypeMapArray<UInt, ElementType>::ElementTypesIteratorHelper - ElementTypesIteratorHelper; + using type_iterator = ElementTypeMapArray<UInt, ElementType>::type_iterator; + using ElementTypesIteratorHelper = + ElementTypeMapArray<UInt, ElementType>::ElementTypesIteratorHelper; inline ElementTypesIteratorHelper elementTypes(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) const { return connectivities.elementTypes(dim, ghost_type, kind); } inline type_iterator firstType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) const { return connectivities.firstType(dim, ghost_type, kind); } inline type_iterator lastType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) const { return connectivities.lastType(dim, ghost_type, kind); } AKANTU_GET_MACRO(ElementSynchronizer, *element_synchronizer, const ElementSynchronizer &); AKANTU_GET_MACRO_NOT_CONST(ElementSynchronizer, *element_synchronizer, ElementSynchronizer &); AKANTU_GET_MACRO(NodeSynchronizer, *node_synchronizer, const NodeSynchronizer &); AKANTU_GET_MACRO_NOT_CONST(NodeSynchronizer, *node_synchronizer, NodeSynchronizer &); // AKANTU_GET_MACRO_NOT_CONST(Communicator, *communicator, StaticCommunicator // &); AKANTU_GET_MACRO(Communicator, *communicator, const StaticCommunicator &); /* ------------------------------------------------------------------------ */ /* Private methods for friends */ /* ------------------------------------------------------------------------ */ private: friend class MeshAccessor; //#if defined(AKANTU_COHESIVE_ELEMENT) // friend class CohesiveElementInserter; //#endif //#if defined(AKANTU_IGFEM) // template <UInt dim> friend class MeshIgfemSphericalGrowingGel; //#endif - AKANTU_GET_MACRO(NodesPointer, nodes, Array<Real> *); + AKANTU_GET_MACRO(NodesPointer, *nodes, Array<Real> &); /// get a pointer to the nodes_global_ids Array<UInt> and create it if /// necessary - inline Array<UInt> * getNodesGlobalIdsPointer(); + inline Array<UInt> & getNodesGlobalIdsPointer(); /// get a pointer to the nodes_type Array<Int> and create it if necessary - inline Array<NodeType> * getNodesTypePointer(); + inline Array<NodeType> & getNodesTypePointer(); /// get a pointer to the connectivity Array for the given type and create it /// if necessary - inline Array<UInt> * + inline Array<UInt> & getConnectivityPointer(const ElementType & type, const GhostType & ghost_type = _not_ghost); /// get a pointer to the element_to_subelement Array for the given type and /// create it if necessary - inline Array<std::vector<Element>> * + inline Array<std::vector<Element>> & getElementToSubelementPointer(const ElementType & type, const GhostType & ghost_type = _not_ghost); /// get a pointer to the subelement_to_element Array for the given type and /// create it if necessary - inline Array<Element> * + inline Array<Element> & getSubelementToElementPointer(const ElementType & type, const GhostType & ghost_type = _not_ghost); AKANTU_GET_MACRO_NOT_CONST(MeshData, mesh_data, MeshData &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// array of the nodes coordinates - Array<Real> * nodes; + std::shared_ptr<Array<Real>> nodes; /// global node ids - Array<UInt> * nodes_global_ids; + std::unique_ptr<Array<UInt>> nodes_global_ids; /// node type, -3 pure ghost, -2 master for the node, -1 normal node, i in /// [0-N] slave node and master is proc i Array<NodeType> nodes_type; /// global number of nodes; - UInt nb_global_nodes; - - /// boolean to know if the nodes have to be deleted with the mesh or not - bool created_nodes; + UInt nb_global_nodes{0}; /// all class of elements present in this mesh (for heterogenous meshes) ElementTypeMapArray<UInt> connectivities; /// map to normals for all class of elements present in this mesh ElementTypeMapArray<Real> normals; /// list of all existing types in the mesh - ConnectivityTypeList type_set; + // ConnectivityTypeList type_set; /// the spatial dimension of this mesh - UInt spatial_dimension; + UInt spatial_dimension{0}; /// types offsets - Array<UInt> types_offsets; + // Array<UInt> types_offsets; - /// list of all existing types in the mesh - ConnectivityTypeList ghost_type_set; - /// ghost types offsets - Array<UInt> ghost_types_offsets; + // /// list of all existing types in the mesh + // ConnectivityTypeList ghost_type_set; + // /// ghost types offsets + // Array<UInt> ghost_types_offsets; /// min of coordinates Vector<Real> lower_bounds; /// max of coordinates Vector<Real> upper_bounds; /// size covered by the mesh on each direction Vector<Real> size; /// local min of coordinates Vector<Real> local_lower_bounds; /// local max of coordinates Vector<Real> local_upper_bounds; /// Extra data loaded from the mesh file MeshData mesh_data; /// facets' mesh - Mesh * mesh_facets; + std::unique_ptr<Mesh> mesh_facets; /// parent mesh (this is set for mesh_facets meshes) - const Mesh * mesh_parent; + const Mesh * mesh_parent{nullptr}; /// defines if current mesh is mesh_facets or not - bool is_mesh_facets; + bool is_mesh_facets{false}; /// defines if the mesh is centralized or distributed - bool is_distributed; + bool is_distributed{false}; /// Communicator on which mesh is distributed - StaticCommunicator * communicator; + const StaticCommunicator * communicator; /// Element synchronizer - ElementSynchronizer * element_synchronizer; + std::unique_ptr<ElementSynchronizer> element_synchronizer; /// Node synchronizer - NodeSynchronizer * node_synchronizer; + std::unique_ptr<NodeSynchronizer> node_synchronizer; + + using NodesToElements = std::vector<std::unique_ptr<std::set<Element>>>; + + /// This info is stored to simplify the dynamic changes + NodesToElements nodes_to_elements; }; /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const Element & _this) { _this.printself(stream); return stream; } /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const Mesh & _this) { _this.printself(stream); return stream; } -} // akantu +} // namespace akantu /* -------------------------------------------------------------------------- */ /* Inline functions */ /* -------------------------------------------------------------------------- */ #include "element_type_map_tmpl.hh" #include "mesh_inline_impl.cc" #endif /* __AKANTU_MESH_HH__ */ diff --git a/src/mesh/mesh_accessor.hh b/src/mesh/mesh_accessor.hh index abf01fe45..061f20a3b 100644 --- a/src/mesh/mesh_accessor.hh +++ b/src/mesh/mesh_accessor.hh @@ -1,129 +1,132 @@ /** * @file mesh_accessor.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Jun 30 2015 * * @brief this class allow to access some private member of mesh it is used for * IO for examples * * @section LICENSE * * Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory * (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "mesh.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_ACCESSOR_HH__ #define __AKANTU_MESH_ACCESSOR_HH__ namespace akantu { class NodeSynchronizer; class ElementSynchronizer; -} // akantu +} // namespace akantu namespace akantu { class MeshAccessor { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - MeshAccessor(Mesh & mesh) : _mesh(mesh){}; - virtual ~MeshAccessor(){}; + explicit MeshAccessor(Mesh & mesh) : _mesh(mesh){}; + virtual ~MeshAccessor() = default; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the global number of nodes inline UInt getNbGlobalNodes() const { return this->_mesh.nb_global_nodes; }; /// set the global number of nodes inline void setNbGlobalNodes(UInt nb_global_nodes) { this->_mesh.nb_global_nodes = nb_global_nodes; }; /// set the mesh as being distributed inline void setDistributed() { this->_mesh.is_distributed = true; } /// get a pointer to the nodes_global_ids Array<UInt> and create it if /// necessary inline Array<UInt> & getNodesGlobalIds() { - return *(this->_mesh.getNodesGlobalIdsPointer()); + return this->_mesh.getNodesGlobalIdsPointer(); } /// get a pointer to the nodes_type Array<Int> and create it if necessary inline Array<NodeType> & getNodesType() { - return *(this->_mesh.getNodesTypePointer()); + return this->_mesh.getNodesTypePointer(); } /// get a pointer to the coordinates Array - inline Array<Real> & getNodes() { return *(this->_mesh.getNodesPointer()); } + inline Array<Real> & getNodes() { return this->_mesh.getNodesPointer(); } + + /// get a pointer to the coordinates Array + inline std::shared_ptr<Array<Real>> getNodesSharedPtr() { return this->_mesh.nodes; } /// get a pointer to the connectivity Array for the given type and create it /// if necessary inline Array<UInt> & getConnectivity(const ElementType & type, const GhostType & ghost_type = _not_ghost) { - return *(this->_mesh.getConnectivityPointer(type, ghost_type)); + return this->_mesh.getConnectivityPointer(type, ghost_type); } /// get a pointer to the element_to_subelement Array for the given type and /// create it if necessary - inline Array<std::vector<Element> > & + inline Array<std::vector<Element>> & getElementToSubelement(const ElementType & type, const GhostType & ghost_type = _not_ghost) { - return *(this->_mesh.getElementToSubelementPointer(type, ghost_type)); + return this->_mesh.getElementToSubelementPointer(type, ghost_type); } /// get a pointer to the subelement_to_element Array for the given type and /// create it if necessary inline Array<Element> & getSubelementToElement(const ElementType & type, const GhostType & ghost_type = _not_ghost) { - return *(this->_mesh.getSubelementToElementPointer(type, ghost_type)); + return this->_mesh.getSubelementToElementPointer(type, ghost_type); } template <typename T> inline Array<T> & getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type = _not_ghost, UInt nb_component = 1, bool size_to_nb_element = true, bool resize_with_parent = false) { - return *(this->_mesh.getDataPointer<T>(data_name, el_type, ghost_type, - nb_component, size_to_nb_element, - resize_with_parent)); + return this->_mesh.getDataPointer<T>(data_name, el_type, ghost_type, + nb_component, size_to_nb_element, + resize_with_parent); } MeshData & getMeshData() { return this->_mesh.getMeshData(); } /// get the node synchonizer NodeSynchronizer & getNodeSynchronizer(); /// get the element synchonizer ElementSynchronizer & getElementSynchronizer(); private: Mesh & _mesh; }; -} // akantu +} // namespace akantu #endif /* __AKANTU_MESH_ACCESSOR_HH__ */ diff --git a/src/mesh/mesh_inline_impl.cc b/src/mesh/mesh_inline_impl.cc index 3e74a8532..612d3fe5c 100644 --- a/src/mesh/mesh_inline_impl.cc +++ b/src/mesh/mesh_inline_impl.cc @@ -1,630 +1,681 @@ /** * @file mesh_inline_impl.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Thu Jul 15 2010 * @date last modification: Thu Jan 21 2016 * * @brief Implementation of the inline functions of the mesh class * * @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/>. * */ /* -------------------------------------------------------------------------- */ #if defined(AKANTU_COHESIVE_ELEMENT) #include "cohesive_element.hh" #endif #ifndef __AKANTU_MESH_INLINE_IMPL_CC__ #define __AKANTU_MESH_INLINE_IMPL_CC__ namespace akantu { /* -------------------------------------------------------------------------- */ inline RemovedNodesEvent::RemovedNodesEvent(const Mesh & mesh) : new_numbering(mesh.getNbNodes(), 1, "new_numbering") {} /* -------------------------------------------------------------------------- */ inline RemovedElementsEvent::RemovedElementsEvent(const Mesh & mesh, ID new_numbering_id) : new_numbering(new_numbering_id, mesh.getID(), mesh.getMemoryID()) {} +/* -------------------------------------------------------------------------- */ +template <> +inline void Mesh::sendEvent<NewElementsEvent>(NewElementsEvent & event) { + this->nodes_to_elements.resize(nodes->getSize()); + for (const auto & elem : event.getList()) { + const Array<UInt> & conn = connectivities(elem.type, elem.ghost_type); + + UInt nb_nodes_per_elem = this->getNbNodesPerElement(elem.type); + + for (UInt n = 0; n < nb_nodes_per_elem; ++n) { + UInt node = conn(elem.element, n); + if (not nodes_to_elements[node]) + nodes_to_elements[node] = std::make_unique<std::set<Element>>(); + nodes_to_elements[node]->insert(elem); + } + } + + EventHandlerManager<MeshEventHandler>::sendEvent(event); +} + +/* -------------------------------------------------------------------------- */ +template <> inline void Mesh::sendEvent<NewNodesEvent>(NewNodesEvent & event) { + this->computeBoundingBox(); + + EventHandlerManager<MeshEventHandler>::sendEvent(event); +} + /* -------------------------------------------------------------------------- */ template <> inline void Mesh::sendEvent<RemovedElementsEvent>(RemovedElementsEvent & event) { this->connectivities.onElementsRemoved(event.getNewNumbering()); + this->fillNodesToElements(); + this->computeBoundingBox(); + EventHandlerManager<MeshEventHandler>::sendEvent(event); } /* -------------------------------------------------------------------------- */ template <> inline void Mesh::sendEvent<RemovedNodesEvent>(RemovedNodesEvent & event) { - if (created_nodes) - this->removeNodesFromArray(*nodes, event.getNewNumbering()); + const auto & new_numbering = event.getNewNumbering(); + this->removeNodesFromArray(*nodes, new_numbering); if (nodes_global_ids) - this->removeNodesFromArray(*nodes_global_ids, event.getNewNumbering()); + this->removeNodesFromArray(*nodes_global_ids, new_numbering); if (nodes_type.getSize() != 0) - this->removeNodesFromArray(nodes_type, event.getNewNumbering()); + this->removeNodesFromArray(nodes_type, new_numbering); + + std::vector<std::unique_ptr<std::set<Element>>> tmp(nodes_to_elements.size()); + auto it = nodes_to_elements.begin(); + + UInt new_nb_nodes = 0; + for (auto new_i : new_numbering) { + if (new_i != UInt(-1)) { + tmp[new_i] = std::move(*it); + ++new_nb_nodes; + } + ++it; + } + + tmp.resize(new_nb_nodes); + std::move(tmp.begin(), tmp.end(), nodes_to_elements.begin()); + + computeBoundingBox(); EventHandlerManager<MeshEventHandler>::sendEvent(event); } /* -------------------------------------------------------------------------- */ template <typename T> inline void Mesh::removeNodesFromArray(Array<T> & vect, const Array<UInt> & new_numbering) { Array<T> tmp(vect.getSize(), vect.getNbComponent()); UInt nb_component = vect.getNbComponent(); UInt new_nb_nodes = 0; for (UInt i = 0; i < new_numbering.getSize(); ++i) { UInt new_i = new_numbering(i); if (new_i != UInt(-1)) { T * to_copy = vect.storage() + i * nb_component; std::uninitialized_copy(to_copy, to_copy + nb_component, tmp.storage() + new_i * nb_component); ++new_nb_nodes; } } tmp.resize(new_nb_nodes); vect.copy(tmp); } /* -------------------------------------------------------------------------- */ -inline UInt Mesh::elementToLinearized(const Element & elem) const { - AKANTU_DEBUG_ASSERT(elem.type < _max_element_type && - elem.element < types_offsets.storage()[elem.type + 1], - "The element " << elem << "does not exists in the mesh " - << getID()); - - return types_offsets.storage()[elem.type] + elem.element; -} - -/* -------------------------------------------------------------------------- */ -inline Element Mesh::linearizedToElement(UInt linearized_element) const { - - UInt t; - - for (t = _not_defined; - t != _max_element_type && linearized_element >= types_offsets(t); ++t) - ; - - AKANTU_DEBUG_ASSERT(linearized_element < types_offsets(t), - "The linearized element " - << linearized_element - << "does not exists in the mesh " << getID()); - - --t; - ElementType type = ElementType(t); - return Element(type, linearized_element - types_offsets.storage()[t], - _not_ghost, getKind(type)); -} - -/* -------------------------------------------------------------------------- */ -inline void Mesh::updateTypesOffsets(const GhostType & ghost_type) { - Array<UInt> * types_offsets_ptr = &this->types_offsets; - if (ghost_type == _ghost) - types_offsets_ptr = &this->ghost_types_offsets; - Array<UInt> & types_offsets = *types_offsets_ptr; - - types_offsets.clear(); - for (auto type : elementTypes(_all_dimensions, ghost_type, _ek_not_defined)) - types_offsets(type) = connectivities(type, ghost_type).getSize(); - - for (UInt t = _not_defined + 1; t < _max_element_type; ++t) - types_offsets(t) += types_offsets(t - 1); - for (UInt t = _max_element_type; t > _not_defined; --t) - types_offsets(t) = types_offsets(t - 1); - types_offsets(0) = 0; -} - -/* -------------------------------------------------------------------------- */ -inline const Mesh::ConnectivityTypeList & -Mesh::getConnectivityTypeList(const GhostType & ghost_type) const { - if (ghost_type == _not_ghost) - return type_set; - else - return ghost_type_set; -} - -/* -------------------------------------------------------------------------- */ -inline Array<UInt> * Mesh::getNodesGlobalIdsPointer() { +// inline UInt Mesh::elementToLinearized(const Element & elem) const { +// AKANTU_DEBUG_ASSERT(elem.type < _max_element_type && +// elem.element < types_offsets.storage()[elem.type + +// 1], +// "The element " << elem << "does not exists in the mesh +// " +// << getID()); + +// return types_offsets.storage()[elem.type] + elem.element; +// } + +// /* -------------------------------------------------------------------------- +// */ inline Element Mesh::linearizedToElement(UInt linearized_element) const { + +// UInt t; + +// for (t = _not_defined; +// t != _max_element_type && linearized_element >= types_offsets(t); ++t) +// ; + +// AKANTU_DEBUG_ASSERT(linearized_element < types_offsets(t), +// "The linearized element " +// << linearized_element +// << "does not exists in the mesh " << getID()); + +// --t; +// ElementType type = ElementType(t); +// return Element(type, linearized_element - types_offsets.storage()[t], +// _not_ghost, getKind(type)); +// } + +// /* -------------------------------------------------------------------------- +// */ inline void Mesh::updateTypesOffsets(const GhostType & ghost_type) { +// Array<UInt> * types_offsets_ptr = &this->types_offsets; +// if (ghost_type == _ghost) +// types_offsets_ptr = &this->ghost_types_offsets; +// Array<UInt> & types_offsets = *types_offsets_ptr; + +// types_offsets.clear(); +// for (auto type : elementTypes(_all_dimensions, ghost_type, +// _ek_not_defined)) +// types_offsets(type) = connectivities(type, ghost_type).getSize(); + +// for (UInt t = _not_defined + 1; t < _max_element_type; ++t) +// types_offsets(t) += types_offsets(t - 1); +// for (UInt t = _max_element_type; t > _not_defined; --t) +// types_offsets(t) = types_offsets(t - 1); +// types_offsets(0) = 0; +// } + +// /* -------------------------------------------------------------------------- +// */ inline const Mesh::ConnectivityTypeList & +// Mesh::getConnectivityTypeList(const GhostType & ghost_type) const { +// if (ghost_type == _not_ghost) +// return type_set; +// else +// return ghost_type_set; +// } + +/* -------------------------------------------------------------------------- */ +inline Array<UInt> & Mesh::getNodesGlobalIdsPointer() { AKANTU_DEBUG_IN(); - if (nodes_global_ids == NULL) { - std::stringstream sstr; - sstr << getID() << ":nodes_global_ids"; - nodes_global_ids = &(alloc<UInt>(sstr.str(), nodes->getSize(), 1)); - for (UInt i = 0; i < nodes->getSize(); ++i) { - (*nodes_global_ids)(i) = i; + if (not nodes_global_ids) { + auto nb_nodes = nodes->getSize(); + nodes_global_ids = std::make_unique<Array<UInt>>( + nb_nodes, 1, getID() + ":nodes_global_ids"); + + UInt i = 0; + for (auto & global_id : *nodes_global_ids) { + global_id = ++i; } } + AKANTU_DEBUG_OUT(); - return nodes_global_ids; + return *nodes_global_ids; } /* -------------------------------------------------------------------------- */ -inline Array<NodeType> * Mesh::getNodesTypePointer() { +inline Array<NodeType> & Mesh::getNodesTypePointer() { AKANTU_DEBUG_IN(); if (nodes_type.getSize() == 0) { nodes_type.resize(nodes->getSize()); nodes_type.set(_nt_normal); } + AKANTU_DEBUG_OUT(); - return &nodes_type; + return nodes_type; } /* -------------------------------------------------------------------------- */ -inline Array<UInt> * +inline Array<UInt> & Mesh::getConnectivityPointer(const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Array<UInt> * tmp; if (!connectivities.exists(type, ghost_type)) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); tmp = &(connectivities.alloc(0, nb_nodes_per_element, type, ghost_type)); AKANTU_DEBUG_INFO("The connectivity vector for the type " << type << " created"); + // if (ghost_type == _not_ghost) + // type_set.insert(type); + // else + // ghost_type_set.insert(type); - if (ghost_type == _not_ghost) - type_set.insert(type); - else - ghost_type_set.insert(type); - - updateTypesOffsets(ghost_type); + // updateTypesOffsets(ghost_type); } else { tmp = &connectivities(type, ghost_type); } AKANTU_DEBUG_OUT(); - return tmp; + return *tmp; } /* -------------------------------------------------------------------------- */ -inline Array<std::vector<Element>> * +inline Array<std::vector<Element>> & Mesh::getElementToSubelementPointer(const ElementType & type, const GhostType & ghost_type) { - Array<std::vector<Element>> * tmp = getDataPointer<std::vector<Element>>( - "element_to_subelement", type, ghost_type, 1, true); - return tmp; + return getDataPointer<std::vector<Element>>("element_to_subelement", type, + ghost_type, 1, true); } /* -------------------------------------------------------------------------- */ -inline Array<Element> * +inline Array<Element> & Mesh::getSubelementToElementPointer(const ElementType & type, const GhostType & ghost_type) { - Array<Element> * tmp = getDataPointer<Element>( - "subelement_to_element", type, ghost_type, getNbFacetsPerElement(type), - true, is_mesh_facets); - return tmp; + return getDataPointer<Element>("subelement_to_element", type, ghost_type, + getNbFacetsPerElement(type), true, + is_mesh_facets); } /* -------------------------------------------------------------------------- */ inline const Array<std::vector<Element>> & Mesh::getElementToSubelement(const ElementType & type, const GhostType & ghost_type) const { return getData<std::vector<Element>>("element_to_subelement", type, ghost_type); } /* -------------------------------------------------------------------------- */ inline Array<std::vector<Element>> & Mesh::getElementToSubelement(const ElementType & type, const GhostType & ghost_type) { return getData<std::vector<Element>>("element_to_subelement", type, ghost_type); } /* -------------------------------------------------------------------------- */ inline const Array<Element> & Mesh::getSubelementToElement(const ElementType & type, const GhostType & ghost_type) const { return getData<Element>("subelement_to_element", type, ghost_type); } /* -------------------------------------------------------------------------- */ inline Array<Element> & Mesh::getSubelementToElement(const ElementType & type, const GhostType & ghost_type) { return getData<Element>("subelement_to_element", type, ghost_type); } /* -------------------------------------------------------------------------- */ template <typename T> -inline Array<T> * +inline Array<T> & Mesh::getDataPointer(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type, UInt nb_component, bool size_to_nb_element, bool resize_with_parent) { Array<T> & tmp = mesh_data.getElementalDataArrayAlloc<T>( data_name, el_type, ghost_type, nb_component); if (size_to_nb_element) { if (resize_with_parent) tmp.resize(mesh_parent->getNbElement(el_type, ghost_type)); else tmp.resize(this->getNbElement(el_type, ghost_type)); } else { tmp.resize(0); } - return &tmp; + return tmp; } /* -------------------------------------------------------------------------- */ template <typename T> inline const Array<T> & Mesh::getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type) const { return mesh_data.getElementalDataArray<T>(data_name, el_type, ghost_type); } /* -------------------------------------------------------------------------- */ template <typename T> inline Array<T> & Mesh::getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type) { return mesh_data.getElementalDataArray<T>(data_name, el_type, ghost_type); } /* -------------------------------------------------------------------------- */ template <typename T> inline const ElementTypeMapArray<T> & Mesh::getData(const std::string & data_name) const { return mesh_data.getElementalData<T>(data_name); } /* -------------------------------------------------------------------------- */ template <typename T> inline ElementTypeMapArray<T> & Mesh::getData(const std::string & data_name) { return mesh_data.getElementalData<T>(data_name); } /* -------------------------------------------------------------------------- */ template <typename T> inline ElementTypeMapArray<T> & Mesh::registerData(const std::string & data_name) { this->mesh_data.registerElementalData<T>(data_name); return this->getData<T>(data_name); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbElement(const ElementType & type, const GhostType & ghost_type) const { try { const Array<UInt> & conn = connectivities(type, ghost_type); return conn.getSize(); } catch (...) { return 0; } } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbElement(const UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & kind) const { AKANTU_DEBUG_ASSERT(spatial_dimension <= 3 || spatial_dimension == UInt(-1), "spatial_dimension is " << spatial_dimension << " and is greater than 3 !"); UInt nb_element = 0; for (auto type : elementTypes(spatial_dimension, ghost_type, kind)) nb_element += getNbElement(type, ghost_type); return nb_element; } /* -------------------------------------------------------------------------- */ inline void Mesh::getBarycenter(UInt element, const ElementType & type, Real * barycenter, GhostType ghost_type) const { UInt * conn_val = getConnectivity(type, ghost_type).storage(); UInt nb_nodes_per_element = getNbNodesPerElement(type); Real * local_coord = new Real[spatial_dimension * nb_nodes_per_element]; UInt offset = element * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { memcpy(local_coord + n * spatial_dimension, nodes->storage() + conn_val[offset + n] * spatial_dimension, spatial_dimension * sizeof(Real)); } Math::barycenter(local_coord, nb_nodes_per_element, spatial_dimension, barycenter); delete[] local_coord; } /* -------------------------------------------------------------------------- */ inline void Mesh::getBarycenter(const Element & element, Vector<Real> & barycenter) const { getBarycenter(element.element, element.type, barycenter.storage(), element.ghost_type); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbNodesPerElement(const ElementType & type) { UInt nb_nodes_per_element = 0; #define GET_NB_NODES_PER_ELEMENT(type) \ nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_NODES_PER_ELEMENT); #undef GET_NB_NODES_PER_ELEMENT return nb_nodes_per_element; } /* -------------------------------------------------------------------------- */ inline ElementType Mesh::getP1ElementType(const ElementType & type) { ElementType p1_type = _not_defined; #define GET_P1_TYPE(type) p1_type = ElementClass<type>::getP1ElementType() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_P1_TYPE); #undef GET_P1_TYPE return p1_type; } /* -------------------------------------------------------------------------- */ inline ElementKind Mesh::getKind(const ElementType & type) { ElementKind kind = _ek_not_defined; #define GET_KIND(type) kind = ElementClass<type>::getKind() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_KIND); #undef GET_KIND return kind; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getSpatialDimension(const ElementType & type) { UInt spatial_dimension = 0; #define GET_SPATIAL_DIMENSION(type) \ spatial_dimension = ElementClass<type>::getSpatialDimension() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_SPATIAL_DIMENSION); #undef GET_SPATIAL_DIMENSION return spatial_dimension; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbFacetTypes(const ElementType & type, __attribute__((unused)) UInt t) { UInt nb = 0; #define GET_NB_FACET_TYPE(type) nb = ElementClass<type>::getNbFacetTypes() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_FACET_TYPE); #undef GET_NB_FACET_TYPE return nb; } /* -------------------------------------------------------------------------- */ inline ElementType Mesh::getFacetType(const ElementType & type, UInt t) { ElementType surface_type = _not_defined; #define GET_FACET_TYPE(type) surface_type = ElementClass<type>::getFacetType(t) AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_FACET_TYPE); #undef GET_FACET_TYPE return surface_type; } /* -------------------------------------------------------------------------- */ inline VectorProxy<ElementType> Mesh::getAllFacetTypes(const ElementType & type) { #define GET_FACET_TYPE(type) \ UInt nb = ElementClass<type>::getNbFacetTypes(); \ ElementType * elt_ptr = \ const_cast<ElementType *>(ElementClass<type>::getFacetTypeInternal()); \ return VectorProxy<ElementType>(elt_ptr, nb); AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_FACET_TYPE); #undef GET_FACET_TYPE } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbFacetsPerElement(const ElementType & type) { AKANTU_DEBUG_IN(); UInt n_facet = 0; #define GET_NB_FACET(type) n_facet = ElementClass<type>::getNbFacetsPerElement() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_FACET); #undef GET_NB_FACET AKANTU_DEBUG_OUT(); return n_facet; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbFacetsPerElement(const ElementType & type, UInt t) { AKANTU_DEBUG_IN(); UInt n_facet = 0; #define GET_NB_FACET(type) \ n_facet = ElementClass<type>::getNbFacetsPerElement(t) AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_FACET); #undef GET_NB_FACET AKANTU_DEBUG_OUT(); return n_facet; } /* -------------------------------------------------------------------------- */ inline MatrixProxy<UInt> Mesh::getFacetLocalConnectivity(const ElementType & type, UInt t) { AKANTU_DEBUG_IN(); #define GET_FACET_CON(type) \ AKANTU_DEBUG_OUT(); \ return ElementClass<type>::getFacetLocalConnectivityPerElement(t) AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_FACET_CON); #undef GET_FACET_CON AKANTU_DEBUG_OUT(); return MatrixProxy<UInt>( nullptr, 0, 0); // This avoid a compilation warning but will certainly // also cause a segfault if reached } /* -------------------------------------------------------------------------- */ inline Matrix<UInt> Mesh::getFacetConnectivity(const Element & element, UInt t) const { AKANTU_DEBUG_IN(); Matrix<UInt> local_facets(getFacetLocalConnectivity(element.type, t), false); Matrix<UInt> facets(local_facets.rows(), local_facets.cols()); const Array<UInt> & conn = connectivities(element.type, element.ghost_type); for (UInt f = 0; f < facets.rows(); ++f) { for (UInt n = 0; n < facets.cols(); ++n) { facets(f, n) = conn(element.element, local_facets(f, n)); } } AKANTU_DEBUG_OUT(); return facets; } /* -------------------------------------------------------------------------- */ template <typename T> inline void Mesh::extractNodalValuesFromElement( const Array<T> & nodal_values, T * local_coord, UInt * connectivity, UInt n_nodes, UInt nb_degree_of_freedom) const { for (UInt n = 0; n < n_nodes; ++n) { memcpy(local_coord + n * nb_degree_of_freedom, nodal_values.storage() + connectivity[n] * nb_degree_of_freedom, nb_degree_of_freedom * sizeof(T)); } } /* -------------------------------------------------------------------------- */ inline void Mesh::addConnectivityType(const ElementType & type, const GhostType & ghost_type) { getConnectivityPointer(type, ghost_type); } /* -------------------------------------------------------------------------- */ inline bool Mesh::isPureGhostNode(UInt n) const { return nodes_type.getSize() ? (nodes_type(n) == _nt_pure_gost) : false; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isLocalOrMasterNode(UInt n) const { return nodes_type.getSize() ? (nodes_type(n) == _nt_master) || (nodes_type(n) == _nt_normal) : true; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isLocalNode(UInt n) const { return nodes_type.getSize() ? nodes_type(n) == _nt_normal : true; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isMasterNode(UInt n) const { return nodes_type.getSize() ? nodes_type(n) == _nt_master : false; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isSlaveNode(UInt n) const { return nodes_type.getSize() ? nodes_type(n) >= 0 : false; } /* -------------------------------------------------------------------------- */ inline NodeType Mesh::getNodeType(UInt local_id) const { return nodes_type.getSize() ? nodes_type(local_id) : _nt_normal; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNodeGlobalId(UInt local_id) const { return nodes_global_ids ? (*nodes_global_ids)(local_id) : local_id; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNodeLocalId(UInt global_id) const { AKANTU_DEBUG_ASSERT(nodes_global_ids != NULL, "The global ids are note set."); return nodes_global_ids->find(global_id); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbGlobalNodes() const { return nodes_global_ids ? nb_global_nodes : nodes->getSize(); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbNodesPerElementList(const Array<Element> & elements) { UInt nb_nodes_per_element = 0; UInt nb_nodes = 0; ElementType current_element_type = _not_defined; Array<Element>::const_iterator<Element> el_it = elements.begin(); Array<Element>::const_iterator<Element> el_end = elements.end(); for (; el_it != el_end; ++el_it) { const Element & el = *el_it; if (el.type != current_element_type) { current_element_type = el.type; nb_nodes_per_element = Mesh::getNbNodesPerElement(current_element_type); } nb_nodes += nb_nodes_per_element; } return nb_nodes; } /* -------------------------------------------------------------------------- */ inline Mesh & Mesh::getMeshFacets() { if (!this->mesh_facets) AKANTU_EXCEPTION( "No facet mesh is defined yet! check the buildFacets functions"); return *this->mesh_facets; } /* -------------------------------------------------------------------------- */ inline const Mesh & Mesh::getMeshFacets() const { if (!this->mesh_facets) AKANTU_EXCEPTION( "No facet mesh is defined yet! check the buildFacets functions"); return *this->mesh_facets; } /* -------------------------------------------------------------------------- */ inline const Mesh & Mesh::getMeshParent() const { if (!this->mesh_parent) AKANTU_EXCEPTION( "No parent mesh is defined! This is only valid in a mesh_facets"); return *this->mesh_parent; } /* -------------------------------------------------------------------------- */ -} // akantu +} // namespace akantu #endif /* __AKANTU_MESH_INLINE_IMPL_CC__ */ diff --git a/src/mesh/node_group.hh b/src/mesh/node_group.hh index a1602815a..40af0023e 100644 --- a/src/mesh/node_group.hh +++ b/src/mesh/node_group.hh @@ -1,137 +1,141 @@ /** * @file node_group.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Dec 08 2015 * * @brief Node group definition * * @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_common.hh" #include "aka_array.hh" #include "aka_memory.hh" #include "mesh_filter.hh" #include "dumpable.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NODE_GROUP_HH__ #define __AKANTU_NODE_GROUP_HH__ namespace akantu { class NodeGroup : public Memory, public Dumpable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NodeGroup(const std::string & name, const Mesh & mesh, const std::string & id = "node_group", const MemoryID & memory_id = 0); virtual ~NodeGroup(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: typedef Array<UInt>::const_iterator<UInt> const_node_iterator; /// empty the node group void empty(); /// iterator to the beginning of the node group inline const_node_iterator begin() const; /// iterator to the end of the node group inline const_node_iterator end() const; /// add a node and give the local position through an iterator inline const_node_iterator add(UInt node, bool check_for_duplicate = true); /// remove a node inline void remove(UInt node); + inline decltype(auto) find(UInt node) const { + return node_group.find(node); + } + /// remove duplicated nodes void optimize(); /// append a group to current one void append(const NodeGroup & other_group); /// apply a filter on current node group template <typename T> void applyNodeFilter(T & filter); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO_NOT_CONST(Nodes, node_group, Array<UInt> &); AKANTU_GET_MACRO(Nodes, node_group, const Array<UInt> &); AKANTU_GET_MACRO(Name, name, const std::string &); /// give the number of nodes in the current group inline UInt getSize() const; UInt * storage(){return node_group.storage();}; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// name of the group std::string name; /// list of nodes in the group Array<UInt> & node_group; /// reference to the mesh in question //const Mesh & mesh; }; /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const NodeGroup & _this) { _this.printself(stream); return stream; } } // akantu /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "node_group_inline_impl.cc" #endif /* __AKANTU_NODE_GROUP_HH__ */ diff --git a/src/mesh_utils/cohesive_element_inserter.cc b/src/mesh_utils/cohesive_element_inserter.cc index 1e282c93f..587afc25c 100644 --- a/src/mesh_utils/cohesive_element_inserter.cc +++ b/src/mesh_utils/cohesive_element_inserter.cc @@ -1,451 +1,458 @@ /** * @file cohesive_element_inserter.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Dec 04 2013 * @date last modification: Sun Oct 04 2015 * * @brief Cohesive element inserter functions * * @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 "cohesive_element_inserter.hh" #include "element_group.hh" #include <algorithm> #include <limits> /* -------------------------------------------------------------------------- */ namespace akantu { CohesiveElementInserter::CohesiveElementInserter(Mesh & mesh, bool is_extrinsic, const ID & id) : id(id), mesh(mesh), mesh_facets(mesh.initMeshFacets()), insertion_facets("insertion_facets", id), insertion_limits(mesh.getSpatialDimension(), 2), check_facets("check_facets", id) { MeshUtils::buildAllFacets(mesh, mesh_facets, 0); init(is_extrinsic); } /* -------------------------------------------------------------------------- */ CohesiveElementInserter::~CohesiveElementInserter() { #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) delete global_ids_updater; #endif } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::init(bool is_extrinsic) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); MeshUtils::resetFacetToDouble(mesh_facets); /// initialize facet insertion array insertion_facets.initialize(mesh_facets, _spatial_dimension = (spatial_dimension - 1), _with_nb_element = true); // mesh_facets.initElementTypeMapArray( // insertion_facets, 1, spatial_dimension - 1, false, _ek_regular, true); /// init insertion limits for (UInt dim = 0; dim < spatial_dimension; ++dim) { insertion_limits(dim, 0) = std::numeric_limits<Real>::max() * (-1.); insertion_limits(dim, 1) = std::numeric_limits<Real>::max(); } if (is_extrinsic) { check_facets.initialize(mesh_facets, _spatial_dimension = spatial_dimension - 1); // mesh_facets.initElementTypeMapArray(check_facets, 1, spatial_dimension - // 1); initFacetsCheck(); } #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) facet_synchronizer = NULL; global_ids_updater = NULL; #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::initFacetsCheck() { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType facet_gt = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, facet_gt); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1, facet_gt); for (; it != last; ++it) { ElementType facet_type = *it; Array<bool> & f_check = check_facets(facet_type, facet_gt); const Array<std::vector<Element>> & element_to_facet = mesh_facets.getElementToSubelement(facet_type, facet_gt); UInt nb_facet = element_to_facet.getSize(); f_check.resize(nb_facet); for (UInt f = 0; f < nb_facet; ++f) { if (element_to_facet(f)[1] == ElementNull || (element_to_facet(f)[0].ghost_type == _ghost && element_to_facet(f)[1].ghost_type == _ghost)) { f_check(f) = false; } else f_check(f) = true; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::limitCheckFacets() { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); Vector<Real> bary_facet(spatial_dimension); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, ghost_type); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, ghost_type); for (; it != end; ++it) { ElementType type = *it; Array<bool> & f_check = check_facets(type, ghost_type); UInt nb_facet = mesh_facets.getNbElement(type, ghost_type); for (UInt f = 0; f < nb_facet; ++f) { if (f_check(f)) { mesh_facets.getBarycenter(f, type, bary_facet.storage(), ghost_type); UInt coord_in_limit = 0; while (coord_in_limit < spatial_dimension && bary_facet(coord_in_limit) > insertion_limits(coord_in_limit, 0) && bary_facet(coord_in_limit) < insertion_limits(coord_in_limit, 1)) ++coord_in_limit; if (coord_in_limit != spatial_dimension) f_check(f) = false; } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::setLimit(SpacialDirection axis, Real first_limit, Real second_limit) { AKANTU_DEBUG_ASSERT( axis < mesh.getSpatialDimension(), "You are trying to limit insertion in a direction that doesn't exist"); insertion_limits(axis, 0) = std::min(first_limit, second_limit); insertion_limits(axis, 1) = std::max(first_limit, second_limit); } /* -------------------------------------------------------------------------- */ UInt CohesiveElementInserter::insertIntrinsicElements() { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); Vector<Real> bary_facet(spatial_dimension); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, ghost_type); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, ghost_type); for (; it != end; ++it) { const ElementType type_facet = *it; Array<bool> & f_insertion = insertion_facets(type_facet, ghost_type); Array<std::vector<Element>> & element_to_facet = mesh_facets.getElementToSubelement(type_facet, ghost_type); UInt nb_facet = mesh_facets.getNbElement(type_facet, ghost_type); for (UInt f = 0; f < nb_facet; ++f) { if (element_to_facet(f)[1] == ElementNull) continue; mesh_facets.getBarycenter(f, type_facet, bary_facet.storage(), ghost_type); UInt coord_in_limit = 0; while (coord_in_limit < spatial_dimension && bary_facet(coord_in_limit) > insertion_limits(coord_in_limit, 0) && bary_facet(coord_in_limit) < insertion_limits(coord_in_limit, 1)) ++coord_in_limit; if (coord_in_limit == spatial_dimension) f_insertion(f) = true; } } } AKANTU_DEBUG_OUT(); return insertElements(); } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::insertIntrinsicElements(std::string physname, UInt material_index) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); ElementTypeMapArray<UInt> * phys_data; try { phys_data = &(mesh_facets.getData<UInt>("physical_names")); } catch (...) { phys_data = &(mesh_facets.registerData<UInt>("physical_names")); phys_data->initialize(mesh_facets, _spatial_dimension = spatial_dimension - 1, _with_nb_element = true); // mesh_facets.initElementTypeMapArray(*phys_data, 1, spatial_dimension - 1, // false, _ek_regular, true); } Vector<Real> bary_facet(spatial_dimension); mesh_facets.createElementGroup(physname); GhostType ghost_type = _not_ghost; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, ghost_type); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, ghost_type); for (; it != end; ++it) { const ElementType type_facet = *it; Array<bool> & f_insertion = insertion_facets(type_facet, ghost_type); Array<std::vector<Element>> & element_to_facet = mesh_facets.getElementToSubelement(type_facet, ghost_type); UInt nb_facet = mesh_facets.getNbElement(type_facet, ghost_type); UInt coord_in_limit = 0; ElementGroup & group = mesh.getElementGroup(physname); ElementGroup & group_facet = mesh_facets.getElementGroup(physname); Vector<Real> bary_physgroup(spatial_dimension); Real norm_bary; for (ElementGroup::const_element_iterator el_it( - group.element_begin(type_facet, ghost_type)); - el_it != group.element_end(type_facet, ghost_type); ++el_it) { + group.begin(type_facet, ghost_type)); + el_it != group.end(type_facet, ghost_type); ++el_it) { UInt e = *el_it; mesh.getBarycenter(e, type_facet, bary_physgroup.storage(), ghost_type); #ifndef AKANTU_NDEBUG bool find_a_partner = false; #endif norm_bary = bary_physgroup.norm(); Array<UInt> & material_id = (*phys_data)(type_facet, ghost_type); for (UInt f = 0; f < nb_facet; ++f) { if (element_to_facet(f)[1] == ElementNull) continue; mesh_facets.getBarycenter(f, type_facet, bary_facet.storage(), ghost_type); coord_in_limit = 0; while (coord_in_limit < spatial_dimension && (std::abs(bary_facet(coord_in_limit) - bary_physgroup(coord_in_limit)) / norm_bary < Math::getTolerance())) ++coord_in_limit; if (coord_in_limit == spatial_dimension) { f_insertion(f) = true; #ifndef AKANTU_NDEBUG find_a_partner = true; #endif group_facet.add(type_facet, f, ghost_type, false); material_id(f) = material_index; break; } } AKANTU_DEBUG_ASSERT(find_a_partner, "The element nO " << e << " of physical group " << physname << " did not find its associated facet!" << " Try to decrease math tolerance. " << std::endl); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ UInt CohesiveElementInserter::insertElements(bool only_double_facets) { - NewNodesEvent node_event; - node_event.getList().extendComponentsInterlaced(2, 1); + CohesiveNewNodesEvent node_event; NewElementsEvent element_event; + Array<UInt> new_pairs(0, 2); + UInt nb_new_elements = MeshUtils::insertCohesiveElements( - mesh, mesh_facets, insertion_facets, node_event.getList(), + mesh, mesh_facets, insertion_facets, new_pairs, element_event.getList(), only_double_facets); - UInt nb_new_nodes = node_event.getList().getSize(); + UInt nb_new_nodes = new_pairs.getSize(); + node_event.getList().reserve(nb_new_nodes); + node_event.getOldNodesList().reserve(nb_new_nodes); + for(UInt n = 0; n < nb_new_nodes; ++n) { + node_event.getList().push_back(new_pairs(n, 1)); + node_event.getOldNodesList().push_back(new_pairs(n, 0)); + } #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (mesh.getNodesType().getSize()) { /// update nodes type updateNodesType(mesh, node_event); updateNodesType(mesh_facets, node_event); /// update global ids nb_new_nodes = this->updateGlobalIDs(node_event); /// compute total number of new elements StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); comm.allReduce(&nb_new_elements, 1, _so_sum); } #endif if (nb_new_nodes > 0) mesh.sendEvent(node_event); if (nb_new_elements > 0) { updateInsertionFacets(); - mesh.updateTypesOffsets(_not_ghost); + //mesh.updateTypesOffsets(_not_ghost); mesh.sendEvent(element_event); MeshUtils::resetFacetToDouble(mesh_facets); } #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (mesh.getNodesType().getSize()) { /// update global ids this->synchronizeGlobalIDs(node_event); } #endif return nb_new_elements; } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::updateInsertionFacets() { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType facet_gt = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, facet_gt); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1, facet_gt); for (; it != last; ++it) { ElementType facet_type = *it; Array<bool> & ins_facets = insertion_facets(facet_type, facet_gt); // this is the extrinsic case if (check_facets.exists(facet_type, facet_gt)) { Array<bool> & f_check = check_facets(facet_type, facet_gt); UInt nb_facets = f_check.getSize(); for (UInt f = 0; f < ins_facets.getSize(); ++f) { if (ins_facets(f)) { ++nb_facets; ins_facets(f) = false; f_check(f) = false; } } f_check.resize(nb_facets); } // and this the intrinsic one else { ins_facets.resize(mesh_facets.getNbElement(facet_type, facet_gt)); ins_facets.set(false); } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void CohesiveElementInserter::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "CohesiveElementInserter [" << std::endl; stream << space << " + mesh [" << std::endl; mesh.printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + mesh_facets [" << std::endl; mesh_facets.printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << "]" << std::endl; } } // namespace akantu diff --git a/src/mesh_utils/cohesive_element_inserter.hh b/src/mesh_utils/cohesive_element_inserter.hh index 14620c62a..0377b3191 100644 --- a/src/mesh_utils/cohesive_element_inserter.hh +++ b/src/mesh_utils/cohesive_element_inserter.hh @@ -1,211 +1,223 @@ /** * @file cohesive_element_inserter.hh * * @author Fabian Barras <fabian.barras@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Dec 04 2013 * @date last modification: Fri Oct 02 2015 * * @brief Cohesive element inserter * * @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/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COHESIVE_ELEMENT_INSERTER_HH__ #define __AKANTU_COHESIVE_ELEMENT_INSERTER_HH__ /* -------------------------------------------------------------------------- */ #include "data_accessor.hh" #include "mesh_utils.hh" #include <numeric> #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) #include "facet_synchronizer.hh" #include "global_ids_updater.hh" #endif /* -------------------------------------------------------------------------- */ namespace akantu { class CohesiveElementInserter : public DataAccessor<Element> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: CohesiveElementInserter(Mesh & mesh, bool is_extrinsic = false, const ID & id = "cohesive_element_inserter"); virtual ~CohesiveElementInserter(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// init function void init(bool is_extrinsic); /// set range limitation for intrinsic cohesive element insertion void setLimit(SpacialDirection axis, Real first_limit, Real second_limit); /// insert intrinsic cohesive elements in a predefined range UInt insertIntrinsicElements(); /// preset insertion of intrinsic cohesive elements along /// a predefined group of facet and assign them a defined material index. /// insertElement() method has to be called to finalize insertion. void insertIntrinsicElements(std::string physname, UInt material_index); /// insert extrinsic cohesive elements (returns the number of new /// cohesive elements) UInt insertElements(bool only_double_facets = false); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /// limit check facets to match given insertion limits void limitCheckFacets(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) /// init parallel variables void initParallel(FacetSynchronizer * facet_synchronizer, ElementSynchronizer * element_synchronizer); #endif protected: /// init facets check void initFacetsCheck(); /// update facet insertion arrays after facets doubling void updateInsertionFacets(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) /// update nodes type and global ids for parallel simulations /// (locally, within each processor) UInt updateGlobalIDs(NewNodesEvent & node_event); /// synchronize the global ids among the processors in parallel simulations void synchronizeGlobalIDs(NewNodesEvent & node_event); /// update nodes type void updateNodesType(Mesh & mesh, NewNodesEvent & node_event); /// functions for parallel communications inline UInt getNbData(const Array<Element> & elements, const SynchronizationTag & tag) const override; inline void packData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) const override; inline void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) override; template <bool pack_mode> inline void packUnpackGlobalConnectivity(CommunicationBuffer & buffer, const Array<Element> & elements) const; template <bool pack_mode> inline void packUnpackGroupedInsertionData(CommunicationBuffer & buffer, const Array<Element> & elements) const; #else /// functions for parallel communications inline UInt getNbData(const Array<Element> &, const SynchronizationTag &) const override { return 0; } inline void packData(CommunicationBuffer &, const Array<Element> &, const SynchronizationTag &) const override {} inline void unpackData(CommunicationBuffer &, const Array<Element> &, const SynchronizationTag &) override {} #endif /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO_NOT_CONST(InsertionFacetsByElement, insertion_facets, ElementTypeMapArray<bool> &); AKANTU_GET_MACRO(InsertionFacetsByElement, insertion_facets, const ElementTypeMapArray<bool> &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(InsertionFacets, insertion_facets, bool); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(CheckFacets, check_facets, bool); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(CheckFacets, check_facets, bool); AKANTU_GET_MACRO(MeshFacets, mesh_facets, const Mesh &); AKANTU_GET_MACRO_NOT_CONST(MeshFacets, mesh_facets, Mesh &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// object id ID id; /// main mesh where to insert cohesive elements Mesh & mesh; /// mesh containing facets Mesh & mesh_facets; /// list of facets where to insert elements ElementTypeMapArray<bool> insertion_facets; /// limits for element insertion Array<Real> insertion_limits; /// vector containing facets in which extrinsic cohesive elements can be /// inserted ElementTypeMapArray<bool> check_facets; #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) /// facet synchronizer FacetSynchronizer * facet_synchronizer; /// global connectivity ids updater GlobalIdsUpdater * global_ids_updater; #endif }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) #include "cohesive_element_inserter_inline_impl.cc" #endif /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const CohesiveElementInserter & _this) { _this.printself(stream); return stream; } +class CohesiveNewNodesEvent : public NewNodesEvent{ +public: + CohesiveNewNodesEvent() = default; + virtual ~CohesiveNewNodesEvent() = default; + + AKANTU_GET_MACRO_NOT_CONST(OldNodesList, old_nodes, Array<UInt> &); + AKANTU_GET_MACRO(OldNodesList, old_nodes, const Array<UInt> &); +private: + Array<UInt> old_nodes; +}; + + } // akantu #endif /* __AKANTU_COHESIVE_ELEMENT_INSERTER_HH__ */ diff --git a/src/mesh_utils/mesh_partition.cc b/src/mesh_utils/mesh_partition.cc index 648214182..01ee4574f 100644 --- a/src/mesh_utils/mesh_partition.cc +++ b/src/mesh_utils/mesh_partition.cc @@ -1,441 +1,410 @@ /** * @file mesh_partition.cc * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Aug 17 2010 * @date last modification: Fri Jan 22 2016 * * @brief implementation of common part of all partitioner * * @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 "mesh_partition.hh" -#include "mesh_utils.hh" #include "aka_types.hh" +#include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ #include <unordered_map> /* -------------------------------------------------------------------------- */ - namespace akantu { /* -------------------------------------------------------------------------- */ MeshPartition::MeshPartition(const Mesh & mesh, UInt spatial_dimension, const ID & id, const MemoryID & memory_id) : Memory(id, memory_id), mesh(mesh), spatial_dimension(spatial_dimension), partitions("partition", id, memory_id), ghost_partitions("ghost_partition", id, memory_id), ghost_partitions_offset("ghost_partition_offset", id, memory_id), saved_connectivity("saved_connectivity", id, memory_id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ MeshPartition::~MeshPartition() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * TODO this function should most probably be rewritten in a more modern way * conversion in c++ of the GENDUALMETIS (mesh.c) function wrote by George in * Metis (University of Minnesota) */ void MeshPartition::buildDualGraph(Array<Int> & dxadj, Array<Int> & dadjncy, Array<Int> & edge_loads, const EdgeLoadFunctor & edge_load_func) { AKANTU_DEBUG_IN(); // tweak mesh; - const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); - UInt nb_types = type_list.size(); UInt nb_good_types = 0; - Vector<UInt> nb_nodes_per_element_p1(nb_types); - - Vector<UInt> magic_number(nb_types); - - // UInt * conn_val[nb_types]; - Vector<UInt> nb_element(nb_types); - - Array<UInt> ** conn = new Array<UInt> *[nb_types]; - - Array<Element> lin_to_element; + std::vector<UInt> nb_nodes_per_element_p1; + std::vector<UInt> magic_number; + std::vector<UInt> nb_element; + std::vector<Array<UInt> *> conn; Element elem; elem.ghost_type = _not_ghost; - const_cast<Mesh &>(mesh).updateTypesOffsets(_not_ghost); - const_cast<Mesh &>(mesh).updateTypesOffsets(_ghost); + UInt spatial_dimension = mesh.getSpatialDimension(); - Mesh::ConnectivityTypeList::const_iterator it; - for (it = type_list.begin(); it != type_list.end(); ++it) { - ElementType type = *it; - if (Mesh::getSpatialDimension(type) != mesh.getSpatialDimension()) - continue; + for (auto & type : + mesh.elementTypes(spatial_dimension, _not_ghost, _ek_not_defined)) { elem.type = type; ElementType type_p1 = Mesh::getP1ElementType(type); - nb_nodes_per_element_p1[nb_good_types] = - Mesh::getNbNodesPerElement(type_p1); - nb_element[nb_good_types] = - mesh.getConnectivity(type, _not_ghost).getSize(); - magic_number[nb_good_types] = - Mesh::getNbNodesPerElement(Mesh::getFacetType(type_p1)); - - conn[nb_good_types] = - &const_cast<Array<UInt> &>(mesh.getConnectivity(type, _not_ghost)); + conn.push_back( + &const_cast<Array<UInt> &>(mesh.getConnectivity(type, _not_ghost))); + nb_nodes_per_element_p1.push_back(Mesh::getNbNodesPerElement(type_p1)); + nb_element.push_back(conn.back()->getSize()); + magic_number.push_back( + Mesh::getNbNodesPerElement(Mesh::getFacetType(type_p1))); - for (UInt i = 0; i < nb_element[nb_good_types]; ++i) { + for (UInt i = 0; i < nb_element.back(); ++i) { elem.element = i; lin_to_element.push_back(elem); } - nb_good_types++; + ++nb_good_types; } - CSR<UInt> node_to_elem; + CSR<Element> node_to_elem; MeshUtils::buildNode2Elements(mesh, node_to_elem); UInt nb_total_element = 0; UInt nb_total_node_element = 0; for (UInt t = 0; t < nb_good_types; ++t) { nb_total_element += nb_element[t]; nb_total_node_element += nb_element[t] * nb_nodes_per_element_p1[t]; } dxadj.resize(nb_total_element + 1); /// initialize the dxadj array for (UInt t = 0, linerized_el = 0; t < nb_good_types; ++t) for (UInt el = 0; el < nb_element[t]; ++el, ++linerized_el) dxadj(linerized_el) = nb_nodes_per_element_p1[t]; /// convert the dxadj_val array in a csr one for (UInt i = 1; i < nb_total_element; ++i) dxadj(i) += dxadj(i - 1); for (UInt i = nb_total_element; i > 0; --i) dxadj(i) = dxadj(i - 1); dxadj(0) = 0; dadjncy.resize(2 * dxadj(nb_total_element)); edge_loads.resize(2 * dxadj(nb_total_element)); /// weight map to determine adjacency std::unordered_map<UInt, UInt> weight_map; for (UInt t = 0, linerized_el = 0; t < nb_good_types; ++t) { for (UInt el = 0; el < nb_element[t]; ++el, ++linerized_el) { /// fill the weight map for (UInt n = 0; n < nb_nodes_per_element_p1[t]; ++n) { UInt node = (*conn[t])(el, n); - CSR<UInt>::iterator k; + CSR<Element>::iterator k; for (k = node_to_elem.rbegin(node); k != node_to_elem.rend(node); --k) { - UInt current_el = *k; + Element current_element = *k; + UInt current_el = lin_to_element.find(current_element); + if (current_el <= linerized_el) break; auto it_w = weight_map.find(current_el); if (it_w == weight_map.end()) { weight_map[current_el] = 1; } else { it_w->second++; } } } /// each element with a weight of the size of a facet are adjacent for (auto it_w = weight_map.begin(); it_w != weight_map.end(); ++it_w) { if (it_w->second == magic_number[t]) { UInt adjacent_el = it_w->first; #if defined(AKANTU_COHESIVE_ELEMENT) /// Patch in order to prevent neighboring cohesive elements /// from detecting each other - ElementKind linearized_el_kind = - mesh.linearizedToElement(linerized_el).kind; - ElementKind adjacent_el_kind = - mesh.linearizedToElement(adjacent_el).kind; + ElementKind linearized_el_kind = lin_to_element(linerized_el).kind; + ElementKind adjacent_el_kind = lin_to_element(adjacent_el).kind; if (linearized_el_kind == adjacent_el_kind && linearized_el_kind == _ek_cohesive) continue; #endif UInt index_adj = dxadj(adjacent_el)++; UInt index_lin = dxadj(linerized_el)++; dadjncy(index_lin) = adjacent_el; dadjncy(index_adj) = linerized_el; } } weight_map.clear(); } } Int k_start = 0; for (UInt t = 0, linerized_el = 0, j = 0; t < nb_good_types; ++t) for (UInt el = 0; el < nb_element[t]; ++el, ++linerized_el) { for (Int k = k_start; k < dxadj(linerized_el); ++k, ++j) dadjncy(j) = dadjncy(k); dxadj(linerized_el) = j; k_start += nb_nodes_per_element_p1[t]; } for (UInt i = nb_total_element; i > 0; --i) dxadj(i) = dxadj(i - 1); dxadj(0) = 0; UInt adj = 0; for (UInt i = 0; i < nb_total_element; ++i) { UInt nb_adj = dxadj(i + 1) - dxadj(i); for (UInt j = 0; j < nb_adj; ++j, ++adj) { Int el_adj_id = dadjncy(dxadj(i) + j); Element el = lin_to_element(i); Element el_adj = lin_to_element(el_adj_id); Int load = edge_load_func(el, el_adj); edge_loads(adj) = load; } } - delete [] conn; - AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartition::fillPartitionInformation( const Mesh & mesh, const Int * linearized_partitions) { AKANTU_DEBUG_IN(); - CSR<UInt> node_to_elem; + CSR<Element> node_to_elem; MeshUtils::buildNode2Elements(mesh, node_to_elem); - Mesh::type_iterator it = - mesh.firstType(spatial_dimension, _not_ghost, _ek_not_defined); - Mesh::type_iterator end = - mesh.lastType(spatial_dimension, _not_ghost, _ek_not_defined); - UInt linearized_el = 0; - for (; it != end; ++it) { - ElementType type = *it; - + for (auto & type : mesh.elementTypes(spatial_dimension, _not_ghost, _ek_not_defined)) { UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); partitions.alloc(nb_element, 1, type, _not_ghost); - CSR<UInt> & ghost_part_csr = ghost_partitions_csr(type, _not_ghost); + auto & ghost_part_csr = ghost_partitions_csr(type, _not_ghost); ghost_part_csr.resizeRows(nb_element); ghost_partitions_offset.alloc(nb_element + 1, 1, type, _ghost); ghost_partitions.alloc(0, 1, type, _ghost); const Array<UInt> & connectivity = mesh.getConnectivity(type, _not_ghost); for (UInt el = 0; el < nb_element; ++el, ++linearized_el) { UInt part = linearized_partitions[linearized_el]; partitions(type, _not_ghost)(el) = part; std::list<UInt> list_adj_part; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity.storage()[el * nb_nodes_per_element + n]; - CSR<UInt>::iterator ne; + CSR<Element>::iterator ne; for (ne = node_to_elem.begin(node); ne != node_to_elem.end(node); ++ne) { - UInt adj_el = *ne; + const Element & adj_element = *ne; + UInt adj_el = lin_to_element.find(adj_element); UInt adj_part = linearized_partitions[adj_el]; if (part != adj_part) { list_adj_part.push_back(adj_part); } } } list_adj_part.sort(); list_adj_part.unique(); - for (std::list<UInt>::iterator adj_it = list_adj_part.begin(); - adj_it != list_adj_part.end(); ++adj_it) { - ghost_part_csr.getRows().push_back(*adj_it); + for (auto & adj_part : list_adj_part) { + ghost_part_csr.getRows().push_back(adj_part); ghost_part_csr.rowOffset(el)++; - ghost_partitions(type, _ghost).push_back(*adj_it); + ghost_partitions(type, _ghost).push_back(adj_part); ghost_partitions_offset(type, _ghost)(el)++; } } ghost_part_csr.countToCSR(); /// convert the ghost_partitions_offset array in an offset array Array<UInt> & ghost_partitions_offset_ptr = ghost_partitions_offset(type, _ghost); for (UInt i = 1; i < nb_element; ++i) ghost_partitions_offset_ptr(i) += ghost_partitions_offset_ptr(i - 1); for (UInt i = nb_element; i > 0; --i) ghost_partitions_offset_ptr(i) = ghost_partitions_offset_ptr(i - 1); ghost_partitions_offset_ptr(0) = 0; } // All Facets for (Int sp = spatial_dimension - 1; sp >= 0; --sp) { - Mesh::type_iterator fit = mesh.firstType(sp, _not_ghost, _ek_not_defined); - Mesh::type_iterator fend = mesh.lastType(sp, _not_ghost, _ek_not_defined); - - for (; fit != fend; ++fit) { - ElementType type = *fit; - + for (auto & type : mesh.elementTypes(sp, _not_ghost, _ek_not_defined)) { UInt nb_element = mesh.getNbElement(type); partitions.alloc(nb_element, 1, type, _not_ghost); AKANTU_DEBUG_INFO("Allocating partitions for " << type); - CSR<UInt> & ghost_part_csr = ghost_partitions_csr(type, _not_ghost); + auto & ghost_part_csr = ghost_partitions_csr(type, _not_ghost); ghost_part_csr.resizeRows(nb_element); ghost_partitions_offset.alloc(nb_element + 1, 1, type, _ghost); ghost_partitions.alloc(0, 1, type, _ghost); AKANTU_DEBUG_INFO("Allocating ghost_partitions for " << type); - const Array<std::vector<Element> > & elem_to_subelem = + const Array<std::vector<Element>> & elem_to_subelem = mesh.getElementToSubelement(type, _not_ghost); for (UInt i(0); i < mesh.getNbElement(type, _not_ghost); ++i) { // Facet loop const std::vector<Element> & adjacent_elems = elem_to_subelem(i); if (!adjacent_elems.empty()) { Element min_elem; UInt min_part(std::numeric_limits<UInt>::max()); std::set<UInt> adjacent_parts; for (UInt j(0); j < adjacent_elems.size(); ++j) { UInt adjacent_elem_id = adjacent_elems[j].element; UInt adjacent_elem_part = partitions(adjacent_elems[j].type, adjacent_elems[j].ghost_type)(adjacent_elem_id); if (adjacent_elem_part < min_part) { min_part = adjacent_elem_part; min_elem = adjacent_elems[j]; } adjacent_parts.insert(adjacent_elem_part); } partitions(type, _not_ghost)(i) = min_part; - CSR<UInt>::iterator git = + auto git = ghost_partitions_csr(min_elem.type, _not_ghost) .begin(min_elem.element); - CSR<UInt>::iterator gend = + auto gend = ghost_partitions_csr(min_elem.type, _not_ghost) .end(min_elem.element); for (; git != gend; ++git) { - adjacent_parts.insert(*git); + + adjacent_parts.insert(min_part); } adjacent_parts.erase(min_part); - std::set<UInt>::const_iterator pit = adjacent_parts.begin(); - std::set<UInt>::const_iterator pend = adjacent_parts.end(); - for (; pit != pend; ++pit) { - ghost_part_csr.getRows().push_back(*pit); + for (auto & part : adjacent_parts) { + ghost_part_csr.getRows().push_back(part); ghost_part_csr.rowOffset(i)++; - ghost_partitions(type, _ghost).push_back(*pit); + ghost_partitions(type, _ghost).push_back(part); } ghost_partitions_offset(type, _ghost)(i + 1) = ghost_partitions_offset(type, _ghost)(i + 1) + adjacent_elems.size(); } else { partitions(type, _not_ghost)(i) = 0; } } ghost_part_csr.countToCSR(); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartition::tweakConnectivity(const Array<UInt> & pairs) { AKANTU_DEBUG_IN(); if (pairs.getSize() == 0) return; Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(spatial_dimension, _not_ghost, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; Array<UInt> & conn = const_cast<Array<UInt> &>(mesh.getConnectivity(type, _not_ghost)); UInt nb_nodes_per_element = conn.getNbComponent(); UInt nb_element = conn.getSize(); Array<UInt> & saved_conn = saved_connectivity.alloc( nb_element, nb_nodes_per_element, type, _not_ghost); saved_conn.copy(conn); for (UInt i = 0; i < pairs.getSize(); ++i) { for (UInt el = 0; el < nb_element; ++el) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { if (pairs(i, 1) == conn(el, n)) conn(el, n) = pairs(i, 0); } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartition::restoreConnectivity() { AKANTU_DEBUG_IN(); ElementTypeMapArray<UInt>::type_iterator it = saved_connectivity.firstType( spatial_dimension, _not_ghost, _ek_not_defined); ElementTypeMapArray<UInt>::type_iterator end = saved_connectivity.lastType( spatial_dimension, _not_ghost, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; Array<UInt> & conn = const_cast<Array<UInt> &>(mesh.getConnectivity(type, _not_ghost)); Array<UInt> & saved_conn = saved_connectivity(type, _not_ghost); conn.copy(saved_conn); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -} // akantu +} // namespace akantu diff --git a/src/mesh_utils/mesh_partition.hh b/src/mesh_utils/mesh_partition.hh index 849530369..0d3ad6346 100644 --- a/src/mesh_utils/mesh_partition.hh +++ b/src/mesh_utils/mesh_partition.hh @@ -1,150 +1,152 @@ /** * @file mesh_partition.hh * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Sep 01 2015 * * @brief tools to partitionate a mesh * * @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_MESH_PARTITION_HH__ #define __AKANTU_MESH_PARTITION_HH__ /* -------------------------------------------------------------------------- */ -#include "aka_memory.hh" #include "aka_csr.hh" +#include "aka_memory.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class MeshPartition : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - MeshPartition(const Mesh & mesh, UInt spatial_dimension, const ID & id = "MeshPartitioner", - const MemoryID & memory_id = 0); + const MemoryID & memory_id = 0); virtual ~MeshPartition(); class EdgeLoadFunctor { public: virtual Int operator()(__attribute__((unused)) const Element & el1, - __attribute__((unused)) const Element & el2) const = 0; + __attribute__((unused)) + const Element & el2) const = 0; }; class ConstEdgeLoadFunctor : public EdgeLoadFunctor { public: virtual inline Int operator()(__attribute__((unused)) const Element & el1, - __attribute__((unused)) const Element & el2) const { + __attribute__((unused)) + const Element & el2) const { return 1; } }; - /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// define a partition of the mesh - virtual void partitionate(UInt nb_part, - const EdgeLoadFunctor & edge_load_func = ConstEdgeLoadFunctor(), - const Array<UInt> & pairs = Array<UInt>()) = 0; + virtual void + partitionate(UInt nb_part, + const EdgeLoadFunctor & edge_load_func = ConstEdgeLoadFunctor(), + const Array<UInt> & pairs = Array<UInt>()) = 0; /// reorder the nodes to reduce the filling during the factorization of a /// matrix that has a profil based on the connectivity of the mesh virtual void reorder() = 0; /// fill the partitions array with a given linearized partition information - void fillPartitionInformation(const Mesh & mesh, const Int * linearized_partitions); + void fillPartitionInformation(const Mesh & mesh, + const Int * linearized_partitions); protected: - /// build the dual graph of the mesh, for all element of spatial_dimension void buildDualGraph(Array<Int> & dxadj, Array<Int> & dadjncy, - Array<Int> & edge_loads, - const EdgeLoadFunctor & edge_load_func); + Array<Int> & edge_loads, + const EdgeLoadFunctor & edge_load_func); /// tweak the mesh to handle the PBC pairs void tweakConnectivity(const Array<UInt> & pairs); /// restore the mesh that has been tweaked void restoreConnectivity(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - AKANTU_GET_MACRO(Partitions, partitions, const ElementTypeMapArray<UInt> &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Partition, partitions, UInt); - AKANTU_GET_MACRO(GhostPartitionCSR, ghost_partitions_csr, const ElementTypeMap< CSR<UInt> > &); + AKANTU_GET_MACRO(GhostPartitionCSR, ghost_partitions_csr, + const ElementTypeMap<CSR<UInt>> &); AKANTU_GET_MACRO(NbPartition, nb_partitions, UInt); AKANTU_SET_MACRO(NbPartition, nb_partitions, UInt); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id std::string id; /// the mesh to partition const Mesh & mesh; /// dimension of the elements to consider in the mesh UInt spatial_dimension; /// number of partitions UInt nb_partitions; /// partition numbers ElementTypeMapArray<UInt> partitions; - ElementTypeMap< CSR<UInt> > ghost_partitions_csr; + ElementTypeMap<CSR<UInt>> ghost_partitions_csr; ElementTypeMapArray<UInt> ghost_partitions; ElementTypeMapArray<UInt> ghost_partitions_offset; Array<UInt> * permutation; ElementTypeMapArray<UInt> saved_connectivity; + Array<Element> lin_to_element; }; -} // akantu +} // namespace akantu #ifdef AKANTU_USE_SCOTCH #include "mesh_partition_scotch.hh" #endif #endif /* __AKANTU_MESH_PARTITION_HH__ */ diff --git a/src/mesh_utils/mesh_utils.cc b/src/mesh_utils/mesh_utils.cc index 61ee0a24a..e0e53ad49 100644 --- a/src/mesh_utils/mesh_utils.cc +++ b/src/mesh_utils/mesh_utils.cc @@ -1,2342 +1,2342 @@ /** * @file mesh_utils.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Aug 20 2010 * @date last modification: Fri Jan 22 2016 * * @brief All mesh utils necessary for various tasks * * @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 "mesh_utils.hh" #include "element_synchronizer.hh" #include "fe_engine.hh" #include "mesh_accessor.hh" /* -------------------------------------------------------------------------- */ #include <limits> #include <numeric> #include <queue> #include <set> /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2Elements(const Mesh & mesh, CSR<Element> & node_to_elem, UInt spatial_dimension) { AKANTU_DEBUG_IN(); if (spatial_dimension == _all_dimensions) spatial_dimension = mesh.getSpatialDimension(); /// count number of occurrence of each node UInt nb_nodes = mesh.getNbNodes(); /// array for the node-element list node_to_elem.resizeRows(nb_nodes); node_to_elem.clearRows(); AKANTU_DEBUG_ASSERT( mesh.firstType(spatial_dimension) != mesh.lastType(spatial_dimension), "Some elements must be found in right dimension to compute facets!"); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { Mesh::type_iterator first = mesh.firstType(spatial_dimension, *gt, _ek_not_defined); Mesh::type_iterator last = mesh.lastType(spatial_dimension, *gt, _ek_not_defined); for (; first != last; ++first) { ElementType type = *first; UInt nb_element = mesh.getNbElement(type, *gt); Array<UInt>::const_iterator<Vector<UInt>> conn_it = mesh.getConnectivity(type, *gt).begin( Mesh::getNbNodesPerElement(type)); for (UInt el = 0; el < nb_element; ++el, ++conn_it) for (UInt n = 0; n < conn_it->size(); ++n) ++node_to_elem.rowOffset((*conn_it)(n)); } } node_to_elem.countToCSR(); node_to_elem.resizeCols(); /// rearrange element to get the node-element list Element e; node_to_elem.beginInsertions(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { Mesh::type_iterator first = mesh.firstType(spatial_dimension, *gt, _ek_not_defined); Mesh::type_iterator last = mesh.lastType(spatial_dimension, *gt, _ek_not_defined); e.ghost_type = *gt; for (; first != last; ++first) { ElementType type = *first; e.type = type; e.kind = Mesh::getKind(type); UInt nb_element = mesh.getNbElement(type, *gt); Array<UInt>::const_iterator<Vector<UInt>> conn_it = mesh.getConnectivity(type, *gt).begin( Mesh::getNbNodesPerElement(type)); for (UInt el = 0; el < nb_element; ++el, ++conn_it) { e.element = el; for (UInt n = 0; n < conn_it->size(); ++n) node_to_elem.insertInRow((*conn_it)(n), e); } } } node_to_elem.endInsertions(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * This function should disappear in the future (used in mesh partitioning) */ -void MeshUtils::buildNode2Elements(const Mesh & mesh, CSR<UInt> & node_to_elem, - UInt spatial_dimension) { - AKANTU_DEBUG_IN(); - if (spatial_dimension == _all_dimensions) - spatial_dimension = mesh.getSpatialDimension(); - UInt nb_nodes = mesh.getNbNodes(); - - const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); - Mesh::ConnectivityTypeList::const_iterator it; - - UInt nb_types = type_list.size(); - UInt nb_good_types = 0; - - Vector<UInt> nb_nodes_per_element(nb_types); - UInt ** conn_val = new UInt *[nb_types]; - Vector<UInt> nb_element(nb_types); - - for (it = type_list.begin(); it != type_list.end(); ++it) { - ElementType type = *it; - if (Mesh::getSpatialDimension(type) != spatial_dimension) - continue; - - nb_nodes_per_element[nb_good_types] = Mesh::getNbNodesPerElement(type); - conn_val[nb_good_types] = mesh.getConnectivity(type, _not_ghost).storage(); - nb_element[nb_good_types] = - mesh.getConnectivity(type, _not_ghost).getSize(); - nb_good_types++; - } - - AKANTU_DEBUG_ASSERT( - nb_good_types != 0, - "Some elements must be found in right dimension to compute facets!"); - - /// array for the node-element list - node_to_elem.resizeRows(nb_nodes); - node_to_elem.clearRows(); - - /// count number of occurrence of each node - for (UInt t = 0; t < nb_good_types; ++t) { - for (UInt el = 0; el < nb_element[t]; ++el) { - UInt el_offset = el * nb_nodes_per_element[t]; - for (UInt n = 0; n < nb_nodes_per_element[t]; ++n) { - ++node_to_elem.rowOffset(conn_val[t][el_offset + n]); - } - } - } - - node_to_elem.countToCSR(); - node_to_elem.resizeCols(); - node_to_elem.beginInsertions(); - - /// rearrange element to get the node-element list - for (UInt t = 0, linearized_el = 0; t < nb_good_types; ++t) - for (UInt el = 0; el < nb_element[t]; ++el, ++linearized_el) { - UInt el_offset = el * nb_nodes_per_element[t]; - for (UInt n = 0; n < nb_nodes_per_element[t]; ++n) - node_to_elem.insertInRow(conn_val[t][el_offset + n], linearized_el); - } - - node_to_elem.endInsertions(); - delete[] conn_val; - AKANTU_DEBUG_OUT(); -} +// void MeshUtils::buildNode2Elements(const Mesh & mesh, CSR<UInt> & node_to_elem, +// UInt spatial_dimension) { +// AKANTU_DEBUG_IN(); +// if (spatial_dimension == _all_dimensions) +// spatial_dimension = mesh.getSpatialDimension(); +// UInt nb_nodes = mesh.getNbNodes(); + +// const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); +// Mesh::ConnectivityTypeList::const_iterator it; + +// UInt nb_types = type_list.size(); +// UInt nb_good_types = 0; + +// Vector<UInt> nb_nodes_per_element(nb_types); +// UInt ** conn_val = new UInt *[nb_types]; +// Vector<UInt> nb_element(nb_types); + +// for (it = type_list.begin(); it != type_list.end(); ++it) { +// ElementType type = *it; +// if (Mesh::getSpatialDimension(type) != spatial_dimension) +// continue; + +// nb_nodes_per_element[nb_good_types] = Mesh::getNbNodesPerElement(type); +// conn_val[nb_good_types] = mesh.getConnectivity(type, _not_ghost).storage(); +// nb_element[nb_good_types] = +// mesh.getConnectivity(type, _not_ghost).getSize(); +// nb_good_types++; +// } + +// AKANTU_DEBUG_ASSERT( +// nb_good_types != 0, +// "Some elements must be found in right dimension to compute facets!"); + +// /// array for the node-element list +// node_to_elem.resizeRows(nb_nodes); +// node_to_elem.clearRows(); + +// /// count number of occurrence of each node +// for (UInt t = 0; t < nb_good_types; ++t) { +// for (UInt el = 0; el < nb_element[t]; ++el) { +// UInt el_offset = el * nb_nodes_per_element[t]; +// for (UInt n = 0; n < nb_nodes_per_element[t]; ++n) { +// ++node_to_elem.rowOffset(conn_val[t][el_offset + n]); +// } +// } +// } + +// node_to_elem.countToCSR(); +// node_to_elem.resizeCols(); +// node_to_elem.beginInsertions(); + +// /// rearrange element to get the node-element list +// for (UInt t = 0, linearized_el = 0; t < nb_good_types; ++t) +// for (UInt el = 0; el < nb_element[t]; ++el, ++linearized_el) { +// UInt el_offset = el * nb_nodes_per_element[t]; +// for (UInt n = 0; n < nb_nodes_per_element[t]; ++n) +// node_to_elem.insertInRow(conn_val[t][el_offset + n], linearized_el); +// } + +// node_to_elem.endInsertions(); +// delete[] conn_val; +// AKANTU_DEBUG_OUT(); +// } /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2ElementsElementTypeMap(const Mesh & mesh, CSR<UInt> & node_to_elem, const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_elements = mesh.getConnectivity(type, ghost_type).getSize(); UInt * conn_val = mesh.getConnectivity(type, ghost_type).storage(); /// array for the node-element list node_to_elem.resizeRows(nb_nodes); node_to_elem.clearRows(); /// count number of occurrence of each node for (UInt el = 0; el < nb_elements; ++el) { UInt el_offset = el * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) ++node_to_elem.rowOffset(conn_val[el_offset + n]); } /// convert the occurrence array in a csr one node_to_elem.countToCSR(); node_to_elem.resizeCols(); node_to_elem.beginInsertions(); /// save the element index in the node-element list for (UInt el = 0; el < nb_elements; ++el) { UInt el_offset = el * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { node_to_elem.insertInRow(conn_val[el_offset + n], el); } } node_to_elem.endInsertions(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildFacets(Mesh & mesh) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh.lastType(spatial_dimension - 1, gt_facet); for (; it != end; ++it) { mesh.getConnectivity(*it, *gt).resize(0); // \todo inform the mesh event handler } } buildFacetsDimension(mesh, mesh, true, spatial_dimension); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildAllFacets(const Mesh & mesh, Mesh & mesh_facets, UInt to_dimension) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); buildAllFacets(mesh, mesh_facets, spatial_dimension, to_dimension); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildAllFacets(const Mesh & mesh, Mesh & mesh_facets, UInt from_dimension, UInt to_dimension) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT( mesh_facets.isMeshFacets(), "The mesh_facets should be initialized with initMeshFacets"); const ElementTypeMapArray<UInt> * prank_to_element = nullptr; if (mesh.isDistributed()) { prank_to_element = &(mesh.getElementSynchronizer().getPrankToElement()); } /// generate facets buildFacetsDimension(mesh, mesh_facets, false, from_dimension, prank_to_element); /// copy nodes type MeshAccessor mesh_accessor_facets(mesh_facets); mesh_accessor_facets.getNodesType().copy(mesh.getNodesType()); /// sort facets and generate sub-facets for (UInt i = from_dimension - 1; i > to_dimension; --i) { buildFacetsDimension(mesh_facets, mesh_facets, false, i, prank_to_element); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildFacetsDimension( const Mesh & mesh, Mesh & mesh_facets, bool boundary_only, UInt dimension, const ElementTypeMapArray<UInt> * prank_to_element) { AKANTU_DEBUG_IN(); // save the current parent of mesh_facets and set it temporarly to mesh since // mesh is the one containing the elements for which mesh_facets has the // sub-elements // example: if the function is called with mesh = mesh_facets const Mesh * mesh_facets_parent = nullptr; try { mesh_facets_parent = &mesh_facets.getMeshParent(); } catch (...) { } mesh_facets.defineMeshParent(mesh); MeshAccessor mesh_accessor(mesh_facets); UInt spatial_dimension = mesh.getSpatialDimension(); const Array<Real> & mesh_facets_nodes = mesh_facets.getNodes(); const Array<Real>::const_vector_iterator mesh_facets_nodes_it = mesh_facets_nodes.begin(spatial_dimension); CSR<Element> node_to_elem; buildNode2Elements(mesh, node_to_elem, dimension); Array<UInt> counter; std::vector<Element> connected_elements; // init the SubelementToElement data to improve performance for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator first = mesh.firstType(dimension, ghost_type); Mesh::type_iterator last = mesh.lastType(dimension, ghost_type); for (; first != last; ++first) { ElementType type = *first; mesh_accessor.getSubelementToElement(type, ghost_type); Vector<ElementType> facet_types = mesh.getAllFacetTypes(type); for (UInt ft = 0; ft < facet_types.size(); ++ft) { ElementType facet_type = facet_types(ft); mesh_accessor.getElementToSubelement(facet_type, ghost_type); mesh_accessor.getConnectivity(facet_type, ghost_type); } } } Element current_element; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; GhostType facet_ghost_type = ghost_type; current_element.ghost_type = ghost_type; Mesh::type_iterator first = mesh.firstType(dimension, ghost_type); Mesh::type_iterator last = mesh.lastType(dimension, ghost_type); for (; first != last; ++first) { ElementType type = *first; Vector<ElementType> facet_types = mesh.getAllFacetTypes(type); current_element.type = type; for (UInt ft = 0; ft < facet_types.size(); ++ft) { ElementType facet_type = facet_types(ft); UInt nb_element = mesh.getNbElement(type, ghost_type); Array<std::vector<Element>> * element_to_subelement = &mesh_facets.getElementToSubelement(facet_type, ghost_type); Array<UInt> * connectivity_facets = &mesh_facets.getConnectivity(facet_type, ghost_type); UInt nb_facet_per_element = mesh.getNbFacetsPerElement(type, ft); const Array<UInt> & element_connectivity = mesh.getConnectivity(type, ghost_type); const Matrix<UInt> facet_local_connectivity = mesh.getFacetLocalConnectivity(type, ft); UInt nb_nodes_per_facet = connectivity_facets->getNbComponent(); Vector<UInt> facet(nb_nodes_per_facet); for (UInt el = 0; el < nb_element; ++el) { current_element.element = el; for (UInt f = 0; f < nb_facet_per_element; ++f) { for (UInt n = 0; n < nb_nodes_per_facet; ++n) facet(n) = element_connectivity(el, facet_local_connectivity(f, n)); UInt first_node_nb_elements = node_to_elem.getNbCols(facet(0)); counter.resize(first_node_nb_elements); counter.clear(); // loop over the other nodes to search intersecting elements, // which are the elements that share another node with the // starting element after first_node CSR<Element>::iterator first_node_elements = node_to_elem.begin(facet(0)); CSR<Element>::iterator first_node_elements_end = node_to_elem.end(facet(0)); UInt local_el = 0; for (; first_node_elements != first_node_elements_end; ++first_node_elements, ++local_el) { for (UInt n = 1; n < nb_nodes_per_facet; ++n) { CSR<Element>::iterator node_elements_begin = node_to_elem.begin(facet(n)); CSR<Element>::iterator node_elements_end = node_to_elem.end(facet(n)); counter(local_el) += std::count(node_elements_begin, node_elements_end, *first_node_elements); } } // counting the number of elements connected to the facets and // taking the minimum element number, because the facet should // be inserted just once UInt nb_element_connected_to_facet = 0; Element minimum_el = ElementNull; connected_elements.clear(); for (UInt el_f = 0; el_f < first_node_nb_elements; el_f++) { Element real_el = node_to_elem(facet(0), el_f); if (counter(el_f) == nb_nodes_per_facet - 1) { ++nb_element_connected_to_facet; minimum_el = std::min(minimum_el, real_el); connected_elements.push_back(real_el); } } if (minimum_el == current_element) { bool full_ghost_facet = false; UInt n = 0; while (n < nb_nodes_per_facet && mesh.isPureGhostNode(facet(n))) ++n; if (n == nb_nodes_per_facet) full_ghost_facet = true; if (!full_ghost_facet) { if (!boundary_only || (boundary_only && nb_element_connected_to_facet == 1)) { std::vector<Element> elements; // build elements_on_facets: linearized_el must come first // in order to store the facet in the correct direction // and avoid to invert the sign in the normal computation elements.push_back(current_element); /// boundary facet if (nb_element_connected_to_facet == 1) elements.push_back(ElementNull); /// internal facet else if (nb_element_connected_to_facet == 2) { elements.push_back(connected_elements[1]); /// check if facet is in between ghost and normal /// elements: if it's the case, the facet is either /// ghost or not ghost. The criterion to decide this /// is arbitrary. It was chosen to check the processor /// id (prank) of the two neighboring elements. If /// prank of the ghost element is lower than prank of /// the normal one, the facet is not ghost, otherwise /// it's ghost GhostType gt[2] = {_not_ghost, _not_ghost}; for (UInt el = 0; el < connected_elements.size(); ++el) gt[el] = connected_elements[el].ghost_type; if (gt[0] + gt[1] == 1) { if (prank_to_element) { UInt prank[2]; for (UInt el = 0; el < 2; ++el) { UInt current_el = connected_elements[el].element; ElementType current_type = connected_elements[el].type; GhostType current_gt = connected_elements[el].ghost_type; const Array<UInt> & prank_to_el = (*prank_to_element)(current_type, current_gt); prank[el] = prank_to_el(current_el); } bool ghost_one = (gt[0] != _ghost); if (prank[ghost_one] > prank[!ghost_one]) facet_ghost_type = _not_ghost; else facet_ghost_type = _ghost; connectivity_facets = &mesh_facets.getConnectivity( facet_type, facet_ghost_type); element_to_subelement = &mesh_facets.getElementToSubelement( facet_type, facet_ghost_type); } } } /// facet of facet else { for (UInt i = 1; i < nb_element_connected_to_facet; ++i) { elements.push_back(connected_elements[i]); } } element_to_subelement->push_back(elements); connectivity_facets->push_back(facet); /// current facet index UInt current_facet = connectivity_facets->getSize() - 1; /// loop on every element connected to current facet and /// insert current facet in the first free spot of the /// subelement_to_element vector for (UInt elem = 0; elem < elements.size(); ++elem) { Element loc_el = elements[elem]; if (loc_el.type != _not_defined) { Array<Element> & subelement_to_element = mesh_facets.getSubelementToElement(loc_el.type, loc_el.ghost_type); UInt nb_facet_per_loc_element = subelement_to_element.getNbComponent(); for (UInt f_in = 0; f_in < nb_facet_per_loc_element; ++f_in) { if (subelement_to_element(loc_el.element, f_in).type == _not_defined) { subelement_to_element(loc_el.element, f_in).type = facet_type; subelement_to_element(loc_el.element, f_in).element = current_facet; subelement_to_element(loc_el.element, f_in) .ghost_type = facet_ghost_type; break; } } } } /// reset connectivity in case a facet was found in /// between ghost and normal elements if (facet_ghost_type != ghost_type) { facet_ghost_type = ghost_type; connectivity_facets = &mesh_accessor.getConnectivity( facet_type, facet_ghost_type); element_to_subelement = &mesh_accessor.getElementToSubelement(facet_type, facet_ghost_type); } } } } } } } } } // restore the parent of mesh_facet if (mesh_facets_parent) mesh_facets.defineMeshParent(*mesh_facets_parent); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::renumberMeshNodes(Mesh & mesh, Array<UInt> & local_connectivities, UInt nb_local_element, UInt nb_ghost_element, ElementType type, Array<UInt> & old_nodes_numbers) { AKANTU_DEBUG_IN(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); std::map<UInt, UInt> renumbering_map; for (UInt i = 0; i < old_nodes_numbers.getSize(); ++i) { renumbering_map[old_nodes_numbers(i)] = i; } /// renumber the nodes renumberNodesInConnectivity(local_connectivities, (nb_local_element + nb_ghost_element) * nb_nodes_per_element, renumbering_map); std::map<UInt, UInt>::iterator it = renumbering_map.begin(); std::map<UInt, UInt>::iterator end = renumbering_map.end(); old_nodes_numbers.resize(renumbering_map.size()); for (; it != end; ++it) { old_nodes_numbers(it->second) = it->first; } renumbering_map.clear(); MeshAccessor mesh_accessor(mesh); /// copy the renumbered connectivity to the right place Array<UInt> & local_conn = mesh_accessor.getConnectivity(type); local_conn.resize(nb_local_element); memcpy(local_conn.storage(), local_connectivities.storage(), nb_local_element * nb_nodes_per_element * sizeof(UInt)); Array<UInt> & ghost_conn = mesh_accessor.getConnectivity(type, _ghost); ghost_conn.resize(nb_ghost_element); memcpy(ghost_conn.storage(), local_connectivities.storage() + nb_local_element * nb_nodes_per_element, nb_ghost_element * nb_nodes_per_element * sizeof(UInt)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::renumberNodesInConnectivity( Array<UInt> & list_nodes, UInt nb_nodes, std::map<UInt, UInt> & renumbering_map) { AKANTU_DEBUG_IN(); UInt * connectivity = list_nodes.storage(); UInt new_node_num = renumbering_map.size(); for (UInt n = 0; n < nb_nodes; ++n, ++connectivity) { UInt & node = *connectivity; std::map<UInt, UInt>::iterator it = renumbering_map.find(node); if (it == renumbering_map.end()) { UInt old_node = node; renumbering_map[old_node] = new_node_num; node = new_node_num; ++new_node_num; } else { node = it->second; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::purifyMesh(Mesh & mesh) { AKANTU_DEBUG_IN(); std::map<UInt, UInt> renumbering_map; RemovedNodesEvent remove_nodes(mesh); Array<UInt> & nodes_removed = remove_nodes.getList(); for (UInt gt = _not_ghost; gt <= _ghost; ++gt) { GhostType ghost_type = (GhostType)gt; Mesh::type_iterator it = mesh.firstType(_all_dimensions, ghost_type, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(_all_dimensions, ghost_type, _ek_not_defined); for (; it != end; ++it) { ElementType type(*it); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); Array<UInt> & connectivity = mesh.getConnectivity(type, ghost_type); UInt nb_element(connectivity.getSize()); renumberNodesInConnectivity( connectivity, nb_element * nb_nodes_per_element, renumbering_map); } } Array<UInt> & new_numbering = remove_nodes.getNewNumbering(); std::fill(new_numbering.begin(), new_numbering.end(), UInt(-1)); std::map<UInt, UInt>::iterator it = renumbering_map.begin(); std::map<UInt, UInt>::iterator end = renumbering_map.end(); for (; it != end; ++it) { new_numbering(it->first) = it->second; } for (UInt i = 0; i < new_numbering.getSize(); ++i) { if (new_numbering(i) == UInt(-1)) nodes_removed.push_back(i); } mesh.sendEvent(remove_nodes); AKANTU_DEBUG_OUT(); } #if defined(AKANTU_COHESIVE_ELEMENT) /* -------------------------------------------------------------------------- */ UInt MeshUtils::insertCohesiveElements( Mesh & mesh, Mesh & mesh_facets, const ElementTypeMapArray<bool> & facet_insertion, Array<UInt> & doubled_nodes, Array<Element> & new_elements, bool only_double_facets) { UInt spatial_dimension = mesh.getSpatialDimension(); UInt elements_to_insert = updateFacetToDouble(mesh_facets, facet_insertion); if (elements_to_insert > 0) { if (spatial_dimension == 1) { doublePointFacet(mesh, mesh_facets, doubled_nodes); } else { doubleFacet(mesh, mesh_facets, spatial_dimension - 1, doubled_nodes, true); findSubfacetToDouble<false>(mesh, mesh_facets); if (spatial_dimension == 2) { doubleSubfacet<2>(mesh, mesh_facets, doubled_nodes); } else if (spatial_dimension == 3) { doubleFacet(mesh, mesh_facets, 1, doubled_nodes, false); findSubfacetToDouble<true>(mesh, mesh_facets); doubleSubfacet<3>(mesh, mesh_facets, doubled_nodes); } } if (!only_double_facets) updateCohesiveData(mesh, mesh_facets, new_elements); } return elements_to_insert; } #endif /* -------------------------------------------------------------------------- */ void MeshUtils::doubleNodes(Mesh & mesh, const std::vector<UInt> & old_nodes, Array<UInt> & doubled_nodes) { AKANTU_DEBUG_IN(); Array<Real> & position = mesh.getNodes(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt old_nb_nodes = position.getSize(); UInt new_nb_nodes = old_nb_nodes + old_nodes.size(); UInt old_nb_doubled_nodes = doubled_nodes.getSize(); UInt new_nb_doubled_nodes = old_nb_doubled_nodes + old_nodes.size(); position.resize(new_nb_nodes); doubled_nodes.resize(new_nb_doubled_nodes); Array<Real>::iterator<Vector<Real>> position_begin = position.begin(spatial_dimension); for (UInt n = 0; n < old_nodes.size(); ++n) { UInt new_node = old_nb_nodes + n; /// store doubled nodes doubled_nodes(old_nb_doubled_nodes + n, 0) = old_nodes[n]; doubled_nodes(old_nb_doubled_nodes + n, 1) = new_node; /// update position std::copy(position_begin + old_nodes[n], position_begin + old_nodes[n] + 1, position_begin + new_node); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::doubleFacet(Mesh & mesh, Mesh & mesh_facets, UInt facet_dimension, Array<UInt> & doubled_nodes, bool facet_mode) { AKANTU_DEBUG_IN(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(facet_dimension, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(facet_dimension, gt_facet); for (; it != end; ++it) { ElementType type_facet = *it; Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); if (nb_facet_to_double == 0) continue; ElementType type_subfacet = Mesh::getFacetType(type_facet); const UInt nb_subfacet_per_facet = Mesh::getNbFacetsPerElement(type_facet); GhostType gt_subfacet = _casper; Array<std::vector<Element>> * f_to_subfacet = NULL; Array<Element> & subfacet_to_facet = mesh_facets.getSubelementToElement(type_facet, gt_facet); Array<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); UInt nb_nodes_per_facet = conn_facet.getNbComponent(); UInt old_nb_facet = conn_facet.getSize(); UInt new_nb_facet = old_nb_facet + nb_facet_to_double; conn_facet.resize(new_nb_facet); subfacet_to_facet.resize(new_nb_facet); UInt new_facet = old_nb_facet - 1; Element new_facet_el(type_facet, 0, gt_facet); Array<Element>::iterator<Vector<Element>> subfacet_to_facet_begin = subfacet_to_facet.begin(nb_subfacet_per_facet); Array<UInt>::iterator<Vector<UInt>> conn_facet_begin = conn_facet.begin(nb_nodes_per_facet); for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { UInt old_facet = f_to_double(facet); ++new_facet; /// adding a new facet by copying original one /// copy connectivity in new facet std::copy(conn_facet_begin + old_facet, conn_facet_begin + old_facet + 1, conn_facet_begin + new_facet); /// update subfacet_to_facet std::copy(subfacet_to_facet_begin + old_facet, subfacet_to_facet_begin + old_facet + 1, subfacet_to_facet_begin + new_facet); new_facet_el.element = new_facet; /// loop on every subfacet for (UInt sf = 0; sf < nb_subfacet_per_facet; ++sf) { Element & subfacet = subfacet_to_facet(old_facet, sf); if (subfacet == ElementNull) continue; if (gt_subfacet != subfacet.ghost_type) { gt_subfacet = subfacet.ghost_type; f_to_subfacet = &mesh_facets.getElementToSubelement( type_subfacet, subfacet.ghost_type); } /// update facet_to_subfacet array (*f_to_subfacet)(subfacet.element).push_back(new_facet_el); } } /// update facet_to_subfacet and _segment_3 facets if any if (!facet_mode) { updateSubfacetToFacet(mesh_facets, type_facet, gt_facet, true); updateFacetToSubfacet(mesh_facets, type_facet, gt_facet, true); updateQuadraticSegments<true>(mesh, mesh_facets, type_facet, gt_facet, doubled_nodes); } else updateQuadraticSegments<false>(mesh, mesh_facets, type_facet, gt_facet, doubled_nodes); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ UInt MeshUtils::updateFacetToDouble( Mesh & mesh_facets, const ElementTypeMapArray<bool> & facet_insertion) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh_facets.getSpatialDimension(); UInt nb_facets_to_double = 0.; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); for (; it != end; ++it) { ElementType type_facet = *it; const Array<bool> & f_insertion = facet_insertion(type_facet, gt_facet); Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet); Array<std::vector<Element>> & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); ElementType el_type = _not_defined; GhostType el_gt = _casper; UInt nb_facet_per_element = 0; Element old_facet_el(type_facet, 0, gt_facet); Array<Element> * facet_to_element = NULL; for (UInt f = 0; f < f_insertion.getSize(); ++f) { if (f_insertion(f) == false) continue; ++nb_facets_to_double; if (element_to_facet(f)[1].type == _not_defined #if defined(AKANTU_COHESIVE_ELEMENT) || element_to_facet(f)[1].kind == _ek_cohesive #endif ) { AKANTU_DEBUG_WARNING("attempt to double a facet on the boundary"); continue; } f_to_double.push_back(f); UInt new_facet = mesh_facets.getNbElement(type_facet, gt_facet) + f_to_double.getSize() - 1; old_facet_el.element = f; /// update facet_to_element vector Element & elem_to_update = element_to_facet(f)[1]; UInt el = elem_to_update.element; if (elem_to_update.ghost_type != el_gt || elem_to_update.type != el_type) { el_type = elem_to_update.type; el_gt = elem_to_update.ghost_type; facet_to_element = &mesh_facets.getSubelementToElement(el_type, el_gt); nb_facet_per_element = facet_to_element->getNbComponent(); } Element * f_update = std::find(facet_to_element->storage() + el * nb_facet_per_element, facet_to_element->storage() + el * nb_facet_per_element + nb_facet_per_element, old_facet_el); AKANTU_DEBUG_ASSERT( facet_to_element->storage() + el * nb_facet_per_element != facet_to_element->storage() + el * nb_facet_per_element + nb_facet_per_element, "Facet not found"); f_update->element = new_facet; /// update elements connected to facet std::vector<Element> first_facet_list = element_to_facet(f); element_to_facet.push_back(first_facet_list); /// set new and original facets as boundary facets element_to_facet(new_facet)[0] = element_to_facet(new_facet)[1]; element_to_facet(f)[1] = ElementNull; element_to_facet(new_facet)[1] = ElementNull; } } } AKANTU_DEBUG_OUT(); return nb_facets_to_double; } /* -------------------------------------------------------------------------- */ void MeshUtils::resetFacetToDouble(Mesh & mesh_facets) { AKANTU_DEBUG_IN(); for (UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType)g; Mesh::type_iterator it = mesh_facets.firstType(_all_dimensions, gt); Mesh::type_iterator end = mesh_facets.lastType(_all_dimensions, gt); for (; it != end; ++it) { ElementType type = *it; mesh_facets.getDataPointer<UInt>("facet_to_double", type, gt, 1, false); mesh_facets.getDataPointer<std::vector<Element>>( "facets_to_subfacet_double", type, gt, 1, false); mesh_facets.getDataPointer<std::vector<Element>>( "elements_to_subfacet_double", type, gt, 1, false); mesh_facets.getDataPointer<std::vector<Element>>( "subfacets_to_subsubfacet_double", type, gt, 1, false); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <bool subsubfacet_mode> void MeshUtils::findSubfacetToDouble(Mesh & mesh, Mesh & mesh_facets) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh_facets.getSpatialDimension(); if (spatial_dimension == 1) return; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); for (; it != end; ++it) { ElementType type_facet = *it; Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); if (nb_facet_to_double == 0) continue; ElementType type_subfacet = Mesh::getFacetType(type_facet); GhostType gt_subfacet = _casper; ElementType type_subsubfacet = Mesh::getFacetType(type_subfacet); GhostType gt_subsubfacet = _casper; Array<UInt> * conn_subfacet = NULL; Array<UInt> * sf_to_double = NULL; Array<std::vector<Element>> * sf_to_subfacet_double = NULL; Array<std::vector<Element>> * f_to_subfacet_double = NULL; Array<std::vector<Element>> * el_to_subfacet_double = NULL; UInt nb_subfacet = Mesh::getNbFacetsPerElement(type_facet); UInt nb_subsubfacet; UInt nb_nodes_per_sf_el; if (subsubfacet_mode) { nb_nodes_per_sf_el = Mesh::getNbNodesPerElement(type_subsubfacet); nb_subsubfacet = Mesh::getNbFacetsPerElement(type_subfacet); } else nb_nodes_per_sf_el = Mesh::getNbNodesPerElement(type_subfacet); Array<Element> & subfacet_to_facet = mesh_facets.getSubelementToElement(type_facet, gt_facet); Array<std::vector<Element>> & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); Array<Element> * subsubfacet_to_subfacet = NULL; UInt old_nb_facet = subfacet_to_facet.getSize() - nb_facet_to_double; Element current_facet(type_facet, 0, gt_facet); std::vector<Element> element_list; std::vector<Element> facet_list; std::vector<Element> * subfacet_list; if (subsubfacet_mode) subfacet_list = new std::vector<Element>; /// map to filter subfacets Array<std::vector<Element>> * facet_to_subfacet = NULL; /// this is used to make sure that both new and old facets are /// checked UInt facets[2]; /// loop on every facet for (UInt f_index = 0; f_index < 2; ++f_index) { for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { facets[bool(f_index)] = f_to_double(facet); facets[!bool(f_index)] = old_nb_facet + facet; UInt old_facet = facets[0]; UInt new_facet = facets[1]; Element & starting_element = element_to_facet(new_facet)[0]; current_facet.element = old_facet; /// loop on every subfacet for (UInt sf = 0; sf < nb_subfacet; ++sf) { Element & subfacet = subfacet_to_facet(old_facet, sf); if (subfacet == ElementNull) continue; if (gt_subfacet != subfacet.ghost_type) { gt_subfacet = subfacet.ghost_type; if (subsubfacet_mode) { subsubfacet_to_subfacet = &mesh_facets.getSubelementToElement( type_subfacet, gt_subfacet); } else { conn_subfacet = &mesh_facets.getConnectivity(type_subfacet, gt_subfacet); sf_to_double = &mesh_facets.getData<UInt>( "facet_to_double", type_subfacet, gt_subfacet); f_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "facets_to_subfacet_double", type_subfacet, gt_subfacet); el_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "elements_to_subfacet_double", type_subfacet, gt_subfacet); facet_to_subfacet = &mesh_facets.getElementToSubelement( type_subfacet, gt_subfacet); } } if (subsubfacet_mode) { /// loop on every subsubfacet for (UInt ssf = 0; ssf < nb_subsubfacet; ++ssf) { Element & subsubfacet = (*subsubfacet_to_subfacet)(subfacet.element, ssf); if (subsubfacet == ElementNull) continue; if (gt_subsubfacet != subsubfacet.ghost_type) { gt_subsubfacet = subsubfacet.ghost_type; conn_subfacet = &mesh_facets.getConnectivity(type_subsubfacet, gt_subsubfacet); sf_to_double = &mesh_facets.getData<UInt>( "facet_to_double", type_subsubfacet, gt_subsubfacet); sf_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "subfacets_to_subsubfacet_double", type_subsubfacet, gt_subsubfacet); f_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "facets_to_subfacet_double", type_subsubfacet, gt_subsubfacet); el_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "elements_to_subfacet_double", type_subsubfacet, gt_subsubfacet); facet_to_subfacet = &mesh_facets.getElementToSubelement( type_subsubfacet, gt_subsubfacet); } UInt global_ssf = subsubfacet.element; Vector<UInt> subsubfacet_connectivity( conn_subfacet->storage() + global_ssf * nb_nodes_per_sf_el, nb_nodes_per_sf_el); /// check if subsubfacet is to be doubled if (findElementsAroundSubfacet<true>( mesh, mesh_facets, starting_element, current_facet, subsubfacet_connectivity, element_list, facet_list, subfacet_list) == false && removeElementsInVector(*subfacet_list, (*facet_to_subfacet)(global_ssf)) == false) { sf_to_double->push_back(global_ssf); sf_to_subfacet_double->push_back(*subfacet_list); f_to_subfacet_double->push_back(facet_list); el_to_subfacet_double->push_back(element_list); } } } else { const UInt global_sf = subfacet.element; Vector<UInt> subfacet_connectivity( conn_subfacet->storage() + global_sf * nb_nodes_per_sf_el, nb_nodes_per_sf_el); /// check if subfacet is to be doubled if (findElementsAroundSubfacet<false>( mesh, mesh_facets, starting_element, current_facet, subfacet_connectivity, element_list, facet_list) == false && removeElementsInVector( facet_list, (*facet_to_subfacet)(global_sf)) == false) { sf_to_double->push_back(global_sf); f_to_subfacet_double->push_back(facet_list); el_to_subfacet_double->push_back(element_list); } } } } } if (subsubfacet_mode) delete subfacet_list; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ #if defined(AKANTU_COHESIVE_ELEMENT) void MeshUtils::updateCohesiveData(Mesh & mesh, Mesh & mesh_facets, Array<Element> & new_elements) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); bool third_dimension = spatial_dimension == 3; MeshAccessor mesh_facets_accessor(mesh_facets); for (auto gt_facet : ghost_types) { for (auto type_facet : mesh_facets.elementTypes(spatial_dimension - 1, gt_facet)) { Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); if (nb_facet_to_double == 0) continue; ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet); auto & facet_to_coh_element = mesh_facets_accessor.getSubelementToElement(type_cohesive, gt_facet); auto & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); auto & conn_cohesive = mesh.getConnectivity(type_cohesive, gt_facet); UInt nb_nodes_per_facet = Mesh::getNbNodesPerElement(type_facet); Array<std::vector<Element>> & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); UInt old_nb_cohesive_elements = conn_cohesive.getSize(); UInt new_nb_cohesive_elements = conn_cohesive.getSize() + nb_facet_to_double; UInt old_nb_facet = element_to_facet.getSize() - nb_facet_to_double; facet_to_coh_element.resize(new_nb_cohesive_elements); conn_cohesive.resize(new_nb_cohesive_elements); UInt new_elements_old_size = new_elements.getSize(); new_elements.resize(new_elements_old_size + nb_facet_to_double); Element c_element(type_cohesive, 0, gt_facet, _ek_cohesive); Element f_element(type_facet, 0, gt_facet); UInt facets[2]; for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { /// (in 3D cohesive elements connectivity is inverted) facets[third_dimension] = f_to_double(facet); facets[!third_dimension] = old_nb_facet + facet; UInt cohesive_element = old_nb_cohesive_elements + facet; /// store doubled facets f_element.element = facets[0]; facet_to_coh_element(cohesive_element, 0) = f_element; f_element.element = facets[1]; facet_to_coh_element(cohesive_element, 1) = f_element; /// modify cohesive elements' connectivity for (UInt n = 0; n < nb_nodes_per_facet; ++n) { conn_cohesive(cohesive_element, n) = conn_facet(facets[0], n); conn_cohesive(cohesive_element, n + nb_nodes_per_facet) = conn_facet(facets[1], n); } /// update element_to_facet vectors c_element.element = cohesive_element; element_to_facet(facets[0])[1] = c_element; element_to_facet(facets[1])[1] = c_element; /// add cohesive element to the element event list new_elements(new_elements_old_size + facet) = c_element; } } } AKANTU_DEBUG_OUT(); } #endif /* -------------------------------------------------------------------------- */ void MeshUtils::doublePointFacet(Mesh & mesh, Mesh & mesh_facets, Array<UInt> & doubled_nodes) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); if (spatial_dimension != 1) return; Array<Real> & position = mesh.getNodes(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); for (; it != end; ++it) { ElementType type_facet = *it; Array<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); Array<std::vector<Element>> & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); const Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); UInt old_nb_facet = element_to_facet.getSize() - nb_facet_to_double; UInt new_nb_facet = element_to_facet.getSize(); UInt old_nb_nodes = position.getSize(); UInt new_nb_nodes = old_nb_nodes + nb_facet_to_double; position.resize(new_nb_nodes); conn_facet.resize(new_nb_facet); UInt old_nb_doubled_nodes = doubled_nodes.getSize(); doubled_nodes.resize(old_nb_doubled_nodes + nb_facet_to_double); for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { UInt old_facet = f_to_double(facet); UInt new_facet = old_nb_facet + facet; ElementType type = element_to_facet(new_facet)[0].type; UInt el = element_to_facet(new_facet)[0].element; GhostType gt = element_to_facet(new_facet)[0].ghost_type; UInt old_node = conn_facet(old_facet); UInt new_node = old_nb_nodes + facet; /// update position position(new_node) = position(old_node); conn_facet(new_facet) = new_node; Array<UInt> & conn_segment = mesh.getConnectivity(type, gt); UInt nb_nodes_per_segment = conn_segment.getNbComponent(); /// update facet connectivity UInt i; for (i = 0; conn_segment(el, i) != old_node && i <= nb_nodes_per_segment; ++i) ; conn_segment(el, i) = new_node; doubled_nodes(old_nb_doubled_nodes + facet, 0) = old_node; doubled_nodes(old_nb_doubled_nodes + facet, 1) = new_node; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <bool third_dim_segments> void MeshUtils::updateQuadraticSegments(Mesh & mesh, Mesh & mesh_facets, ElementType type_facet, GhostType gt_facet, Array<UInt> & doubled_nodes) { AKANTU_DEBUG_IN(); if (type_facet != _segment_3) return; Array<UInt> & f_to_double = mesh_facets.getData<UInt>("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); UInt old_nb_facet = mesh_facets.getNbElement(type_facet, gt_facet) - nb_facet_to_double; Array<UInt> & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); Array<std::vector<Element>> & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); /// this ones matter only for segments in 3D Array<std::vector<Element>> * el_to_subfacet_double = NULL; Array<std::vector<Element>> * f_to_subfacet_double = NULL; if (third_dim_segments) { el_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "elements_to_subfacet_double", type_facet, gt_facet); f_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "facets_to_subfacet_double", type_facet, gt_facet); } std::vector<UInt> middle_nodes; for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { UInt old_facet = f_to_double(facet); UInt node = conn_facet(old_facet, 2); if (!mesh.isPureGhostNode(node)) middle_nodes.push_back(node); } UInt n = doubled_nodes.getSize(); doubleNodes(mesh, middle_nodes, doubled_nodes); for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { UInt old_facet = f_to_double(facet); UInt old_node = conn_facet(old_facet, 2); if (mesh.isPureGhostNode(old_node)) continue; UInt new_node = doubled_nodes(n, 1); UInt new_facet = old_nb_facet + facet; conn_facet(new_facet, 2) = new_node; if (third_dim_segments) { updateElementalConnectivity(mesh_facets, old_node, new_node, element_to_facet(new_facet)); updateElementalConnectivity(mesh, old_node, new_node, (*el_to_subfacet_double)(facet), &(*f_to_subfacet_double)(facet)); } else { updateElementalConnectivity(mesh, old_node, new_node, element_to_facet(new_facet)); } ++n; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::updateSubfacetToFacet(Mesh & mesh_facets, ElementType type_subfacet, GhostType gt_subfacet, bool facet_mode) { AKANTU_DEBUG_IN(); Array<UInt> & sf_to_double = mesh_facets.getData<UInt>("facet_to_double", type_subfacet, gt_subfacet); UInt nb_subfacet_to_double = sf_to_double.getSize(); /// update subfacet_to_facet vector ElementType type_facet = _not_defined; GhostType gt_facet = _casper; Array<Element> * subfacet_to_facet = NULL; UInt nb_subfacet_per_facet = 0; UInt old_nb_subfacet = mesh_facets.getNbElement(type_subfacet, gt_subfacet) - nb_subfacet_to_double; Array<std::vector<Element>> * facet_list = NULL; if (facet_mode) facet_list = &mesh_facets.getData<std::vector<Element>>( "facets_to_subfacet_double", type_subfacet, gt_subfacet); else facet_list = &mesh_facets.getData<std::vector<Element>>( "subfacets_to_subsubfacet_double", type_subfacet, gt_subfacet); Element old_subfacet_el(type_subfacet, 0, gt_subfacet); Element new_subfacet_el(type_subfacet, 0, gt_subfacet); for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) { old_subfacet_el.element = sf_to_double(sf); new_subfacet_el.element = old_nb_subfacet + sf; for (UInt f = 0; f < (*facet_list)(sf).size(); ++f) { Element & facet = (*facet_list)(sf)[f]; if (facet.type != type_facet || facet.ghost_type != gt_facet) { type_facet = facet.type; gt_facet = facet.ghost_type; subfacet_to_facet = &mesh_facets.getSubelementToElement(type_facet, gt_facet); nb_subfacet_per_facet = subfacet_to_facet->getNbComponent(); } Element * sf_update = std::find( subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet, subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet + nb_subfacet_per_facet, old_subfacet_el); AKANTU_DEBUG_ASSERT(subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet != subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet + nb_subfacet_per_facet, "Subfacet not found"); *sf_update = new_subfacet_el; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::updateFacetToSubfacet(Mesh & mesh_facets, ElementType type_subfacet, GhostType gt_subfacet, bool facet_mode) { AKANTU_DEBUG_IN(); Array<UInt> & sf_to_double = mesh_facets.getData<UInt>("facet_to_double", type_subfacet, gt_subfacet); UInt nb_subfacet_to_double = sf_to_double.getSize(); Array<std::vector<Element>> & facet_to_subfacet = mesh_facets.getElementToSubelement(type_subfacet, gt_subfacet); Array<std::vector<Element>> * facet_to_subfacet_double = NULL; if (facet_mode) { facet_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "facets_to_subfacet_double", type_subfacet, gt_subfacet); } else { facet_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "subfacets_to_subsubfacet_double", type_subfacet, gt_subfacet); } UInt old_nb_subfacet = facet_to_subfacet.getSize(); facet_to_subfacet.resize(old_nb_subfacet + nb_subfacet_to_double); for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) facet_to_subfacet(old_nb_subfacet + sf) = (*facet_to_subfacet_double)(sf); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MeshUtils::doubleSubfacet(Mesh & mesh, Mesh & mesh_facets, Array<UInt> & doubled_nodes) { AKANTU_DEBUG_IN(); if (spatial_dimension == 1) return; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_subfacet = *gt; Mesh::type_iterator it = mesh_facets.firstType(0, gt_subfacet); Mesh::type_iterator end = mesh_facets.lastType(0, gt_subfacet); for (; it != end; ++it) { ElementType type_subfacet = *it; Array<UInt> & sf_to_double = mesh_facets.getData<UInt>( "facet_to_double", type_subfacet, gt_subfacet); UInt nb_subfacet_to_double = sf_to_double.getSize(); if (nb_subfacet_to_double == 0) continue; AKANTU_DEBUG_ASSERT( type_subfacet == _point_1, "Only _point_1 subfacet doubling is supported at the moment"); Array<UInt> & conn_subfacet = mesh_facets.getConnectivity(type_subfacet, gt_subfacet); UInt old_nb_subfacet = conn_subfacet.getSize(); UInt new_nb_subfacet = old_nb_subfacet + nb_subfacet_to_double; conn_subfacet.resize(new_nb_subfacet); std::vector<UInt> nodes_to_double; UInt old_nb_doubled_nodes = doubled_nodes.getSize(); /// double nodes for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) { UInt old_subfacet = sf_to_double(sf); nodes_to_double.push_back(conn_subfacet(old_subfacet)); } doubleNodes(mesh, nodes_to_double, doubled_nodes); /// add new nodes in connectivity for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) { UInt new_subfacet = old_nb_subfacet + sf; UInt new_node = doubled_nodes(old_nb_doubled_nodes + sf, 1); conn_subfacet(new_subfacet) = new_node; } /// update facet and element connectivity Array<std::vector<Element>> & f_to_subfacet_double = mesh_facets.getData<std::vector<Element>>("facets_to_subfacet_double", type_subfacet, gt_subfacet); Array<std::vector<Element>> & el_to_subfacet_double = mesh_facets.getData<std::vector<Element>>( "elements_to_subfacet_double", type_subfacet, gt_subfacet); Array<std::vector<Element>> * sf_to_subfacet_double = NULL; if (spatial_dimension == 3) sf_to_subfacet_double = &mesh_facets.getData<std::vector<Element>>( "subfacets_to_subsubfacet_double", type_subfacet, gt_subfacet); for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) { UInt old_node = doubled_nodes(old_nb_doubled_nodes + sf, 0); UInt new_node = doubled_nodes(old_nb_doubled_nodes + sf, 1); updateElementalConnectivity(mesh, old_node, new_node, el_to_subfacet_double(sf), &f_to_subfacet_double(sf)); updateElementalConnectivity(mesh_facets, old_node, new_node, f_to_subfacet_double(sf)); if (spatial_dimension == 3) updateElementalConnectivity(mesh_facets, old_node, new_node, (*sf_to_subfacet_double)(sf)); } if (spatial_dimension == 2) { updateSubfacetToFacet(mesh_facets, type_subfacet, gt_subfacet, true); updateFacetToSubfacet(mesh_facets, type_subfacet, gt_subfacet, true); } else if (spatial_dimension == 3) { updateSubfacetToFacet(mesh_facets, type_subfacet, gt_subfacet, false); updateFacetToSubfacet(mesh_facets, type_subfacet, gt_subfacet, false); } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::flipFacets( Mesh & mesh_facets, const ElementTypeMapArray<UInt> & global_connectivity, GhostType gt_facet) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh_facets.getSpatialDimension(); /// get global connectivity for local mesh ElementTypeMapArray<UInt> global_connectivity_tmp("global_connectivity_tmp", mesh_facets.getID(), mesh_facets.getMemoryID()); global_connectivity_tmp.initialize( mesh_facets, _spatial_dimension = spatial_dimension - 1, _with_nb_nodes_per_element = true, _with_nb_element = true); // mesh_facets.initElementTypeMapArray(global_connectivity_tmp, 1, // spatial_dimension - 1, gt_facet, // true, _ek_regular, true); mesh_facets.getGlobalConnectivity(global_connectivity_tmp, spatial_dimension - 1, gt_facet); /// loop on every facet for (auto type_facet : mesh_facets.elementTypes(spatial_dimension - 1, gt_facet)) { auto & connectivity = mesh_facets.getConnectivity(type_facet, gt_facet); const auto & g_connectivity = global_connectivity(type_facet, gt_facet); auto & el_to_f = mesh_facets.getElementToSubelement(type_facet, gt_facet); auto & subfacet_to_facet = mesh_facets.getSubelementToElement(type_facet, gt_facet); UInt nb_subfacet_per_facet = subfacet_to_facet.getNbComponent(); UInt nb_nodes_per_facet = connectivity.getNbComponent(); UInt nb_facet = connectivity.getSize(); UInt nb_nodes_per_P1_facet = Mesh::getNbNodesPerElement(Mesh::getP1ElementType(type_facet)); auto & global_conn_tmp = global_connectivity_tmp(type_facet, gt_facet); auto conn_it = connectivity.begin(nb_nodes_per_facet); auto gconn_tmp_it = global_conn_tmp.begin(nb_nodes_per_facet); auto conn_glob_it = g_connectivity.begin(nb_nodes_per_facet); auto subf_to_f = subfacet_to_facet.begin(nb_subfacet_per_facet); UInt * conn_tmp_pointer = new UInt[nb_nodes_per_facet]; Vector<UInt> conn_tmp(conn_tmp_pointer, nb_nodes_per_facet); Element el_tmp; Element * subf_tmp_pointer = new Element[nb_subfacet_per_facet]; Vector<Element> subf_tmp(subf_tmp_pointer, nb_subfacet_per_facet); for (UInt f = 0; f < nb_facet; ++f, ++conn_it, ++gconn_tmp_it, ++subf_to_f, ++conn_glob_it) { Vector<UInt> & gconn_tmp = *gconn_tmp_it; const Vector<UInt> & conn_glob = *conn_glob_it; Vector<UInt> & conn_local = *conn_it; /// skip facet if connectivities are the same if (gconn_tmp == conn_glob) continue; /// re-arrange connectivity conn_tmp = conn_local; UInt * begin = conn_glob.storage(); UInt * end = conn_glob.storage() + nb_nodes_per_facet; for (UInt n = 0; n < nb_nodes_per_facet; ++n) { UInt * new_node = std::find(begin, end, gconn_tmp(n)); AKANTU_DEBUG_ASSERT(new_node != end, "Node not found"); UInt new_position = new_node - begin; conn_local(new_position) = conn_tmp(n); } /// if 3D, check if facets are just rotated if (spatial_dimension == 3) { /// find first node UInt * new_node = std::find(begin, end, gconn_tmp(0)); AKANTU_DEBUG_ASSERT(new_node != end, "Node not found"); UInt new_position = new_node - begin; UInt n = 1; /// count how many nodes in the received connectivity follow /// the same order of those in the local connectivity for (; n < nb_nodes_per_P1_facet && gconn_tmp(n) == conn_glob((new_position + n) % nb_nodes_per_P1_facet); ++n) ; /// skip the facet inversion if facet is just rotated if (n == nb_nodes_per_P1_facet) continue; } /// update data to invert facet el_tmp = el_to_f(f)[0]; el_to_f(f)[0] = el_to_f(f)[1]; el_to_f(f)[1] = el_tmp; subf_tmp = (*subf_to_f); (*subf_to_f)(0) = subf_tmp(1); (*subf_to_f)(1) = subf_tmp(0); } delete[] subf_tmp_pointer; delete[] conn_tmp_pointer; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::fillElementToSubElementsData(Mesh & mesh) { AKANTU_DEBUG_IN(); if (mesh.getNbElement(mesh.getSpatialDimension() - 1) == 0) { AKANTU_DEBUG_INFO("There are not facets, add them in the mesh file or call " "the buildFacet method."); return; } UInt spatial_dimension = mesh.getSpatialDimension(); ElementTypeMapArray<Real> barycenters("barycenter_tmp", mesh.getID(), mesh.getMemoryID()); barycenters.initialize(mesh, _nb_component = spatial_dimension, _spatial_dimension = _all_dimensions); // mesh.initElementTypeMapArray(barycenters, spatial_dimension, // _all_dimensions); Element element; for (auto ghost_type : ghost_types) { element.ghost_type = ghost_type; for (auto & type : mesh.elementTypes(_all_dimensions, ghost_type)) { element.type = type; UInt nb_element = mesh.getNbElement(type, ghost_type); Array<Real> & barycenters_arr = barycenters(type, ghost_type); barycenters_arr.resize(nb_element); auto bary = barycenters_arr.begin(spatial_dimension); auto bary_end = barycenters_arr.end(spatial_dimension); for (UInt el = 0; bary != bary_end; ++bary, ++el) { element.element = el; mesh.getBarycenter(element, *bary); } } } MeshAccessor mesh_accessor(mesh); for (Int sp(spatial_dimension); sp >= 1; --sp) { if (mesh.getNbElement(sp) == 0) continue; for (auto ghost_type : ghost_types) { for (auto & type : mesh.elementTypes(sp, ghost_type)) { mesh_accessor.getSubelementToElement(type, ghost_type) .resize(mesh.getNbElement(type, ghost_type)); mesh_accessor.getSubelementToElement(type, ghost_type).clear(); } for (auto & type : mesh.elementTypes(sp - 1, ghost_type)) { mesh_accessor.getElementToSubelement(type, ghost_type) .resize(mesh.getNbElement(type, ghost_type)); mesh.getElementToSubelement(type, ghost_type).clear(); } } CSR<Element> nodes_to_elements; buildNode2Elements(mesh, nodes_to_elements, sp); Element facet_element; for (auto ghost_type : ghost_types) { facet_element.ghost_type = ghost_type; for (auto & type : mesh.elementTypes(sp - 1, ghost_type)) { facet_element.type = type; auto & element_to_subelement = mesh.getElementToSubelement(type, ghost_type); const auto & connectivity = mesh.getConnectivity(type, ghost_type); auto fit = connectivity.begin(mesh.getNbNodesPerElement(type)); auto fend = connectivity.end(mesh.getNbNodesPerElement(type)); UInt fid = 0; for (; fit != fend; ++fit, ++fid) { const Vector<UInt> & facet = *fit; facet_element.element = fid; std::map<Element, UInt> element_seen_counter; UInt nb_nodes_per_facet = mesh.getNbNodesPerElement(Mesh::getP1ElementType(type)); for (UInt n(0); n < nb_nodes_per_facet; ++n) { auto eit = nodes_to_elements.begin(facet(n)); auto eend = nodes_to_elements.end(facet(n)); for (; eit != eend; ++eit) { auto & elem = *eit; auto cit = element_seen_counter.find(elem); if (cit != element_seen_counter.end()) { cit->second++; } else { element_seen_counter[elem] = 1; } } } std::vector<Element> connected_elements; auto cit = element_seen_counter.begin(); auto cend = element_seen_counter.end(); for (; cit != cend; ++cit) { if (cit->second == nb_nodes_per_facet) connected_elements.push_back(cit->first); } auto ceit = connected_elements.begin(); auto ceend = connected_elements.end(); for (; ceit != ceend; ++ceit) element_to_subelement(fid).push_back(*ceit); for (UInt ce = 0; ce < connected_elements.size(); ++ce) { Element & elem = connected_elements[ce]; Array<Element> & subelement_to_element = mesh_accessor.getSubelementToElement(elem.type, elem.ghost_type); UInt f(0); for (; f < mesh.getNbFacetsPerElement(elem.type) && subelement_to_element(elem.element, f) != ElementNull; ++f) ; AKANTU_DEBUG_ASSERT( f < mesh.getNbFacetsPerElement(elem.type), "The element " << elem << " seems to have too many facets!! (" << f << " < " << mesh.getNbFacetsPerElement(elem.type) << ")"); subelement_to_element(elem.element, f) = facet_element; } } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <bool third_dim_points> bool MeshUtils::findElementsAroundSubfacet( const Mesh & mesh, const Mesh & mesh_facets, const Element & starting_element, const Element & end_facet, const Vector<UInt> & subfacet_connectivity, std::vector<Element> & elem_list, std::vector<Element> & facet_list, std::vector<Element> * subfacet_list) { AKANTU_DEBUG_IN(); /// preallocated stuff before starting bool facet_matched = false; elem_list.clear(); facet_list.clear(); if (third_dim_points) subfacet_list->clear(); elem_list.push_back(starting_element); const Array<UInt> * facet_connectivity = NULL; const Array<UInt> * sf_connectivity = NULL; const Array<Element> * facet_to_element = NULL; const Array<Element> * subfacet_to_facet = NULL; ElementType current_type = _not_defined; GhostType current_ghost_type = _casper; ElementType current_facet_type = _not_defined; GhostType current_facet_ghost_type = _casper; ElementType current_subfacet_type = _not_defined; GhostType current_subfacet_ghost_type = _casper; const Array<std::vector<Element>> * element_to_facet = NULL; const Element * opposing_el = NULL; std::queue<Element> elements_to_check; elements_to_check.push(starting_element); /// keep going until there are elements to check while (!elements_to_check.empty()) { /// check current element Element & current_el = elements_to_check.front(); if (current_el.type != current_type || current_el.ghost_type != current_ghost_type) { current_type = current_el.type; current_ghost_type = current_el.ghost_type; facet_to_element = &mesh_facets.getSubelementToElement(current_type, current_ghost_type); } /// loop over each facet of the element for (UInt f = 0; f < facet_to_element->getNbComponent(); ++f) { const Element & current_facet = (*facet_to_element)(current_el.element, f); if (current_facet == ElementNull) continue; if (current_facet_type != current_facet.type || current_facet_ghost_type != current_facet.ghost_type) { current_facet_type = current_facet.type; current_facet_ghost_type = current_facet.ghost_type; element_to_facet = &mesh_facets.getElementToSubelement( current_facet_type, current_facet_ghost_type); facet_connectivity = &mesh_facets.getConnectivity( current_facet_type, current_facet_ghost_type); if (third_dim_points) subfacet_to_facet = &mesh_facets.getSubelementToElement( current_facet_type, current_facet_ghost_type); } /// check if end facet is reached if (current_facet == end_facet) facet_matched = true; /// add this facet if not already passed if (std::find(facet_list.begin(), facet_list.end(), current_facet) == facet_list.end() && hasElement(*facet_connectivity, current_facet, subfacet_connectivity)) { facet_list.push_back(current_facet); if (third_dim_points) { /// check subfacets for (UInt sf = 0; sf < subfacet_to_facet->getNbComponent(); ++sf) { const Element & current_subfacet = (*subfacet_to_facet)(current_facet.element, sf); if (current_subfacet == ElementNull) continue; if (current_subfacet_type != current_subfacet.type || current_subfacet_ghost_type != current_subfacet.ghost_type) { current_subfacet_type = current_subfacet.type; current_subfacet_ghost_type = current_subfacet.ghost_type; sf_connectivity = &mesh_facets.getConnectivity( current_subfacet_type, current_subfacet_ghost_type); } if (std::find(subfacet_list->begin(), subfacet_list->end(), current_subfacet) == subfacet_list->end() && hasElement(*sf_connectivity, current_subfacet, subfacet_connectivity)) subfacet_list->push_back(current_subfacet); } } } else continue; /// consider opposing element if ((*element_to_facet)(current_facet.element)[0] == current_el) opposing_el = &(*element_to_facet)(current_facet.element)[1]; else opposing_el = &(*element_to_facet)(current_facet.element)[0]; /// skip null elements since they are on a boundary if (*opposing_el == ElementNull) continue; /// skip this element if already added if (std::find(elem_list.begin(), elem_list.end(), *opposing_el) != elem_list.end()) continue; /// only regular elements have to be checked if (opposing_el->kind == _ek_regular) elements_to_check.push(*opposing_el); elem_list.push_back(*opposing_el); #ifndef AKANTU_NDEBUG const Array<UInt> & conn_elem = mesh.getConnectivity(opposing_el->type, opposing_el->ghost_type); AKANTU_DEBUG_ASSERT( hasElement(conn_elem, *opposing_el, subfacet_connectivity), "Subfacet doesn't belong to this element"); #endif } /// erased checked element from the list elements_to_check.pop(); } AKANTU_DEBUG_OUT(); return facet_matched; } /* -------------------------------------------------------------------------- */ -void MeshUtils::buildSegmentToNodeType(const Mesh & mesh, Mesh & mesh_facets) { - buildAllFacets(mesh, mesh_facets, 1); - - UInt spatial_dimension = mesh.getSpatialDimension(); - - const ElementTypeMapArray<UInt> & element_to_rank = - mesh.getElementSynchronizer().getPrankToElement(); - Int local_rank = StaticCommunicator::getStaticCommunicator().whoAmI(); - - for (ghost_type_t::iterator gt = ghost_type_t::begin(); - gt != ghost_type_t::end(); ++gt) { - GhostType ghost_type = *gt; - Mesh::type_iterator it = mesh_facets.firstType(1, ghost_type); - Mesh::type_iterator end = mesh_facets.lastType(1, ghost_type); - for (; it != end; ++it) { - ElementType type = *it; - UInt nb_segments = mesh_facets.getNbElement(type, ghost_type); - - // allocate the data - Array<Int> & segment_to_nodetype = *(mesh_facets.getDataPointer<Int>( - "segment_to_nodetype", type, ghost_type)); - - std::set<Element> connected_elements; - const Array<std::vector<Element>> & segment_to_2Delement = - mesh_facets.getElementToSubelement(type, ghost_type); - - // loop over segments - for (UInt s = 0; s < nb_segments; ++s) { - - // determine the elements connected to the segment - connected_elements.clear(); - const std::vector<Element> & twoD_elements = segment_to_2Delement(s); - - if (spatial_dimension == 2) { - // if 2D just take the elements connected to the segments - connected_elements.insert(twoD_elements.begin(), twoD_elements.end()); - } else if (spatial_dimension == 3) { - // if 3D a second loop is needed to get to the 3D elements - std::vector<Element>::const_iterator facet = twoD_elements.begin(); - - for (; facet != twoD_elements.end(); ++facet) { - const std::vector<Element> & threeD_elements = - mesh_facets.getElementToSubelement( - facet->type, facet->ghost_type)(facet->element); - connected_elements.insert(threeD_elements.begin(), - threeD_elements.end()); - } - } - - // get the minimum processor rank associated to the connected - // elements and verify if ghost and not ghost elements are - // found - Int minimum_rank = std::numeric_limits<Int>::max(); - - // two booleans saying if not ghost and ghost elements are found in the - // loop - bool ghost_found[2]; - ghost_found[0] = false; - ghost_found[1] = false; - - std::set<Element>::iterator connected_elements_it = - connected_elements.begin(); - - for (; connected_elements_it != connected_elements.end(); - ++connected_elements_it) { - if (*connected_elements_it == ElementNull) - continue; - ghost_found[connected_elements_it->ghost_type] = true; - const Array<UInt> & el_to_rank_array = element_to_rank( - connected_elements_it->type, connected_elements_it->ghost_type); - minimum_rank = - std::min(minimum_rank, - Int(el_to_rank_array(connected_elements_it->element))); - } - - // if no ghost elements are found the segment is local - if (!ghost_found[1]) - segment_to_nodetype(s) = -1; - // if no not ghost elements are found the segment is pure ghost - else if (!ghost_found[0]) - segment_to_nodetype(s) = -3; - // if the minimum rank is equal to the local rank, the segment is master - else if (local_rank == minimum_rank) - segment_to_nodetype(s) = -2; - // if the minimum rank is less than the local rank, the segment is slave - else if (local_rank > minimum_rank) - segment_to_nodetype(s) = minimum_rank; - else - AKANTU_DEBUG_ERROR("The local rank cannot be smaller than the " - "minimum rank if both ghost and not ghost " - "elements are found"); - } - } - } -} +// void MeshUtils::buildSegmentToNodeType(const Mesh & mesh, Mesh & mesh_facets) { +// buildAllFacets(mesh, mesh_facets, 1); + +// UInt spatial_dimension = mesh.getSpatialDimension(); + +// const ElementTypeMapArray<UInt> & element_to_rank = +// mesh.getElementSynchronizer().getPrankToElement(); +// Int local_rank = StaticCommunicator::getStaticCommunicator().whoAmI(); + +// for (ghost_type_t::iterator gt = ghost_type_t::begin(); +// gt != ghost_type_t::end(); ++gt) { +// GhostType ghost_type = *gt; +// Mesh::type_iterator it = mesh_facets.firstType(1, ghost_type); +// Mesh::type_iterator end = mesh_facets.lastType(1, ghost_type); +// for (; it != end; ++it) { +// ElementType type = *it; +// UInt nb_segments = mesh_facets.getNbElement(type, ghost_type); + +// // allocate the data +// Array<Int> & segment_to_nodetype = *(mesh_facets.getDataPointer<Int>( +// "segment_to_nodetype", type, ghost_type)); + +// std::set<Element> connected_elements; +// const Array<std::vector<Element>> & segment_to_2Delement = +// mesh_facets.getElementToSubelement(type, ghost_type); + +// // loop over segments +// for (UInt s = 0; s < nb_segments; ++s) { + +// // determine the elements connected to the segment +// connected_elements.clear(); +// const std::vector<Element> & twoD_elements = segment_to_2Delement(s); + +// if (spatial_dimension == 2) { +// // if 2D just take the elements connected to the segments +// connected_elements.insert(twoD_elements.begin(), twoD_elements.end()); +// } else if (spatial_dimension == 3) { +// // if 3D a second loop is needed to get to the 3D elements +// std::vector<Element>::const_iterator facet = twoD_elements.begin(); + +// for (; facet != twoD_elements.end(); ++facet) { +// const std::vector<Element> & threeD_elements = +// mesh_facets.getElementToSubelement( +// facet->type, facet->ghost_type)(facet->element); +// connected_elements.insert(threeD_elements.begin(), +// threeD_elements.end()); +// } +// } + +// // get the minimum processor rank associated to the connected +// // elements and verify if ghost and not ghost elements are +// // found +// Int minimum_rank = std::numeric_limits<Int>::max(); + +// // two booleans saying if not ghost and ghost elements are found in the +// // loop +// bool ghost_found[2]; +// ghost_found[0] = false; +// ghost_found[1] = false; + +// std::set<Element>::iterator connected_elements_it = +// connected_elements.begin(); + +// for (; connected_elements_it != connected_elements.end(); +// ++connected_elements_it) { +// if (*connected_elements_it == ElementNull) +// continue; +// ghost_found[connected_elements_it->ghost_type] = true; +// const Array<UInt> & el_to_rank_array = element_to_rank( +// connected_elements_it->type, connected_elements_it->ghost_type); +// minimum_rank = +// std::min(minimum_rank, +// Int(el_to_rank_array(connected_elements_it->element))); +// } + +// // if no ghost elements are found the segment is local +// if (!ghost_found[1]) +// segment_to_nodetype(s) = -1; +// // if no not ghost elements are found the segment is pure ghost +// else if (!ghost_found[0]) +// segment_to_nodetype(s) = -3; +// // if the minimum rank is equal to the local rank, the segment is master +// else if (local_rank == minimum_rank) +// segment_to_nodetype(s) = -2; +// // if the minimum rank is less than the local rank, the segment is slave +// else if (local_rank > minimum_rank) +// segment_to_nodetype(s) = minimum_rank; +// else +// AKANTU_DEBUG_ERROR("The local rank cannot be smaller than the " +// "minimum rank if both ghost and not ghost " +// "elements are found"); +// } +// } +// } +// } /* -------------------------------------------------------------------------- */ UInt MeshUtils::updateLocalMasterGlobalConnectivity(Mesh & mesh, UInt local_nb_new_nodes) { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int rank = comm.whoAmI(); Int nb_proc = comm.getNbProc(); if (nb_proc == 1) return local_nb_new_nodes; /// resize global ids array Array<UInt> & nodes_global_ids = mesh.getGlobalNodesIds(); UInt old_nb_nodes = mesh.getNbNodes() - local_nb_new_nodes; nodes_global_ids.resize(mesh.getNbNodes()); /// compute the number of global nodes based on the number of old nodes Vector<UInt> old_local_master_nodes(nb_proc); for (UInt n = 0; n < old_nb_nodes; ++n) if (mesh.isLocalOrMasterNode(n)) ++old_local_master_nodes(rank); comm.allGather(old_local_master_nodes); UInt old_global_nodes = std::accumulate(old_local_master_nodes.storage(), old_local_master_nodes.storage() + nb_proc, 0); /// compute amount of local or master doubled nodes Vector<UInt> local_master_nodes(nb_proc); for (UInt n = old_nb_nodes; n < mesh.getNbNodes(); ++n) if (mesh.isLocalOrMasterNode(n)) ++local_master_nodes(rank); comm.allGather(local_master_nodes); /// update global number of nodes UInt total_nb_new_nodes = std::accumulate( local_master_nodes.storage(), local_master_nodes.storage() + nb_proc, 0); if (total_nb_new_nodes == 0) return 0; /// set global ids of local and master nodes UInt starting_index = std::accumulate(local_master_nodes.storage(), local_master_nodes.storage() + rank, old_global_nodes); for (UInt n = old_nb_nodes; n < mesh.getNbNodes(); ++n) { if (mesh.isLocalOrMasterNode(n)) { nodes_global_ids(n) = starting_index; ++starting_index; } } MeshAccessor mesh_accessor(mesh); mesh_accessor.setNbGlobalNodes(old_global_nodes + total_nb_new_nodes); return total_nb_new_nodes; } /* -------------------------------------------------------------------------- */ // Deactivating -Wunused-parameter #if defined(__INTEL_COMPILER) //#pragma warning ( disable : 383 ) #elif defined(__clang__) // test clang to be sure that when we test for gnu it // is only gnu #elif (defined(__GNUC__) || defined(__GNUG__)) #define GCC_VERSION \ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #if GCC_VERSION > 40600 #pragma GCC diagnostic push #endif #pragma GCC diagnostic ignored "-Wunused-parameter" #endif /* -------------------------------------------------------------------------- */ void MeshUtils::updateElementalConnectivity( Mesh & mesh, UInt old_node, UInt new_node, const std::vector<Element> & element_list, __attribute__((unused)) const std::vector<Element> * facet_list) { AKANTU_DEBUG_IN(); ElementType el_type = _not_defined; GhostType gt_type = _casper; Array<UInt> * conn_elem = NULL; #if defined(AKANTU_COHESIVE_ELEMENT) const Array<Element> * cohesive_facets = NULL; #endif UInt nb_nodes_per_element = 0; UInt * n_update = NULL; for (UInt el = 0; el < element_list.size(); ++el) { const Element & elem = element_list[el]; if (elem.type == _not_defined) continue; if (elem.type != el_type || elem.ghost_type != gt_type) { el_type = elem.type; gt_type = elem.ghost_type; conn_elem = &mesh.getConnectivity(el_type, gt_type); nb_nodes_per_element = conn_elem->getNbComponent(); #if defined(AKANTU_COHESIVE_ELEMENT) if (elem.kind == _ek_cohesive) cohesive_facets = &mesh.getMeshFacets().getSubelementToElement(el_type, gt_type); #endif } #if defined(AKANTU_COHESIVE_ELEMENT) if (elem.kind == _ek_cohesive) { AKANTU_DEBUG_ASSERT( facet_list != NULL, "Provide a facet list in order to update cohesive elements"); /// loop over cohesive element's facets for (UInt f = 0, n = 0; f < 2; ++f, n += nb_nodes_per_element / 2) { const Element & facet = (*cohesive_facets)(elem.element, f); /// skip facets if not present in the list if (std::find(facet_list->begin(), facet_list->end(), facet) == facet_list->end()) continue; n_update = std::find( conn_elem->storage() + elem.element * nb_nodes_per_element + n, conn_elem->storage() + elem.element * nb_nodes_per_element + n + nb_nodes_per_element / 2, old_node); AKANTU_DEBUG_ASSERT(n_update != conn_elem->storage() + elem.element * nb_nodes_per_element + n + nb_nodes_per_element / 2, "Node not found in current element"); /// update connectivity *n_update = new_node; } } else { #endif n_update = std::find(conn_elem->storage() + elem.element * nb_nodes_per_element, conn_elem->storage() + elem.element * nb_nodes_per_element + nb_nodes_per_element, old_node); AKANTU_DEBUG_ASSERT(n_update != conn_elem->storage() + elem.element * nb_nodes_per_element + nb_nodes_per_element, "Node not found in current element"); /// update connectivity *n_update = new_node; #if defined(AKANTU_COHESIVE_ELEMENT) } #endif } AKANTU_DEBUG_OUT(); } // Reactivating -Wunused-parameter #if defined(__INTEL_COMPILER) //#pragma warning ( disable : 383 ) #elif defined(__clang__) // test clang to be sure that when we test for gnu it // is only gnu #elif defined(__GNUG__) #if GCC_VERSION > 40600 #pragma GCC diagnostic pop #else #pragma GCC diagnostic warning "-Wunused-parameter" #endif #endif /* -------------------------------------------------------------------------- */ } // namespace akantu // LocalWords: ElementType diff --git a/src/mesh_utils/mesh_utils.hh b/src/mesh_utils/mesh_utils.hh index 2c79aaa1a..a63d000a4 100644 --- a/src/mesh_utils/mesh_utils.hh +++ b/src/mesh_utils/mesh_utils.hh @@ -1,244 +1,245 @@ /** * @file mesh_utils.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Oct 02 2015 * * @brief All mesh utils necessary for various tasks * * @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_common.hh" #include "mesh.hh" #include "aka_csr.hh" /* -------------------------------------------------------------------------- */ #include <vector> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_UTILS_HH__ #define __AKANTU_MESH_UTILS_HH__ /* -------------------------------------------------------------------------- */ namespace akantu { class MeshUtils { /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// build a CSR<UInt> that contains for each node the linearized number of /// the connected elements of a given spatial dimension - static void buildNode2Elements(const Mesh & mesh, CSR<UInt> & node_to_elem, - UInt spatial_dimension = _all_dimensions); + // static void buildNode2Elements(const Mesh & mesh, CSR<UInt> & node_to_elem, + // UInt spatial_dimension = _all_dimensions); + /// build a CSR<Element> that contains for each node the list of connected /// elements of a given spatial dimension static void buildNode2Elements(const Mesh & mesh, CSR<Element> & node_to_elem, UInt spatial_dimension = _all_dimensions); /// build a CSR<UInt> that contains for each node the number of /// the connected elements of a given ElementType static void buildNode2ElementsElementTypeMap(const Mesh & mesh, CSR<UInt> & node_to_elem, const ElementType & type, const GhostType & ghost_type = _not_ghost); /// build the facets elements on the boundaries of a mesh static void buildFacets(Mesh & mesh); /// build all the facets elements: boundary and internals and store them in /// the mesh_facets for element of dimension from_dimension to to_dimension static void buildAllFacets(const Mesh & mesh, Mesh & mesh_facets, UInt from_dimension, UInt to_dimension); /// build all the facets elements: boundary and internals and store them in /// the mesh_facets static void buildAllFacets(const Mesh & mesh, Mesh & mesh_facets, UInt to_dimension = 0); /// build facets for a given spatial dimension static void buildFacetsDimension( const Mesh & mesh, Mesh & mesh_facets, bool boundary_only, UInt dimension, const ElementTypeMapArray<UInt> * prank_to_element = nullptr); /// take the local_connectivity array as the array of local and ghost /// connectivity, renumber the nodes and set the connectivity of the mesh static void renumberMeshNodes(Mesh & mesh, Array<UInt> & local_connectivities, UInt nb_local_element, UInt nb_ghost_element, ElementType type, Array<UInt> & old_nodes); /// compute pbc pair for a given direction static void computePBCMap(const Mesh & mymesh, const UInt dir, std::map<UInt, UInt> & pbc_pair); /// compute pbc pair for a surface pair static void computePBCMap(const Mesh & mymesh, const std::pair<Surface, Surface> & surface_pair, std::map<UInt, UInt> & pbc_pair); /// remove not connected nodes /!\ this functions renumbers the nodes. static void purifyMesh(Mesh & mesh); #if defined(AKANTU_COHESIVE_ELEMENT) /// function to insert cohesive elements on the selected facets /// @return number of facets that have been doubled static UInt insertCohesiveElements(Mesh & mesh, Mesh & mesh_facets, const ElementTypeMapArray<bool> & facet_insertion, Array<UInt> & doubled_nodes, Array<Element> & new_elements, bool only_double_facets); #endif /// fill the subelement to element and the elements to subelements data static void fillElementToSubElementsData(Mesh & mesh); /// flip facets based on global connectivity static void flipFacets(Mesh & mesh_facets, const ElementTypeMapArray<UInt> & global_connectivity, GhostType gt_facet); /// provide list of elements around a node and check if a given /// facet is reached template <bool third_dim_points> static bool findElementsAroundSubfacet( const Mesh & mesh, const Mesh & mesh_facets, const Element & starting_element, const Element & end_facet, const Vector<UInt> & subfacet_connectivity, std::vector<Element> & elem_list, std::vector<Element> & facet_list, std::vector<Element> * subfacet_list = nullptr); /// function to check if a node belongs to a given element static inline bool hasElement(const Array<UInt> & connectivity, const Element & el, const Vector<UInt> & nodes); /// reset facet_to_double arrays in the Mesh static void resetFacetToDouble(Mesh & mesh_facets); /// associate a node type to each segment in the mesh - static void buildSegmentToNodeType(const Mesh & mesh, Mesh & mesh_facets); + // static void buildSegmentToNodeType(const Mesh & mesh, Mesh & mesh_facets); /// update local and master global connectivity when new nodes are added static UInt updateLocalMasterGlobalConnectivity(Mesh & mesh, UInt old_nb_nodes); private: /// match pairs that are on the associated pbc's static void matchPBCPairs(const Mesh & mymesh, const UInt dir, Array<UInt> & selected_left, Array<UInt> & selected_right, std::map<UInt, UInt> & pbc_pair); /// function used by all the renumbering functions static void renumberNodesInConnectivity(Array<UInt> & list_nodes, UInt nb_nodes, std::map<UInt, UInt> & renumbering_map); /// update facet_to_subfacet static void updateFacetToSubfacet(Mesh & mesh_facets, ElementType type_subfacet, GhostType gt_subfacet, bool facet_mode); /// update subfacet_to_facet static void updateSubfacetToFacet(Mesh & mesh_facets, ElementType type_subfacet, GhostType gt_subfacet, bool facet_mode); /// function to double a given facet and update the list of doubled /// nodes static void doubleFacet(Mesh & mesh, Mesh & mesh_facets, UInt facet_dimension, Array<UInt> & doubled_nodes, bool facet_mode); /// function to double a subfacet given start and end index for /// local facet_to_subfacet vector, and update the list of doubled /// nodes template <UInt spatial_dimension> static void doubleSubfacet(Mesh & mesh, Mesh & mesh_facets, Array<UInt> & doubled_nodes); /// double a node static void doubleNodes(Mesh & mesh, const std::vector<UInt> & old_nodes, Array<UInt> & doubled_nodes); /// fill facet_to_double array in the mesh /// returns the number of facets to be doubled static UInt updateFacetToDouble(Mesh & mesh_facets, const ElementTypeMapArray<bool> & facet_insertion); /// find subfacets to be doubled template <bool subsubfacet_mode> static void findSubfacetToDouble(Mesh & mesh, Mesh & mesh_facets); /// double facets (points) in 1D static void doublePointFacet(Mesh & mesh, Mesh & mesh_facets, Array<UInt> & doubled_nodes); #if defined(AKANTU_COHESIVE_ELEMENT) /// update cohesive element data static void updateCohesiveData(Mesh & mesh, Mesh & mesh_facets, Array<Element> & new_elements); #endif /// update elemental connectivity after doubling a node inline static void updateElementalConnectivity(Mesh & mesh, UInt old_node, UInt new_node, const std::vector<Element> & element_list, const std::vector<Element> * facet_list = NULL); /// double middle nodes if facets are _segment_3 template <bool third_dim_segments> static void updateQuadraticSegments(Mesh & mesh, Mesh & mesh_facets, ElementType type_facet, GhostType gt_facet, Array<UInt> & doubled_nodes); /// remove elements on a vector inline static bool removeElementsInVector(const std::vector<Element> & elem_to_remove, std::vector<Element> & elem_list); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "mesh_utils_inline_impl.cc" } // akantu #endif /* __AKANTU_MESH_UTILS_HH__ */ diff --git a/src/synchronizer/master_element_info_per_processor.cc b/src/synchronizer/master_element_info_per_processor.cc index 44560563c..7699f00d5 100644 --- a/src/synchronizer/master_element_info_per_processor.cc +++ b/src/synchronizer/master_element_info_per_processor.cc @@ -1,490 +1,485 @@ /** * @file master_element_info_per_processor.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Fri Mar 11 14:57:13 2016 * * @brief * * @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 "aka_zip.hh" #include "element_group.hh" #include "element_info_per_processor.hh" #include "element_synchronizer.hh" #include "mesh_utils.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ #include <algorithm> #include <iostream> #include <map> +#include <tuple> /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ MasterElementInfoPerProc::MasterElementInfoPerProc( ElementSynchronizer & synchronizer, UInt message_cnt, UInt root, ElementType type, const MeshPartition & partition) : ElementInfoPerProc(synchronizer, message_cnt, root, type), partition(partition), all_nb_local_element(nb_proc, 0), all_nb_ghost_element(nb_proc, 0), all_nb_element_to_send(nb_proc, 0) { Vector<UInt> size(5); size(0) = (UInt)type; if (type != _not_defined) { nb_nodes_per_element = Mesh::getNbNodesPerElement(type); nb_element = mesh.getNbElement(type); const Array<UInt> & partition_num = this->partition.getPartition(this->type, _not_ghost); const CSR<UInt> & ghost_partition = this->partition.getGhostPartitionCSR()(this->type, _not_ghost); for (UInt el = 0; el < nb_element; ++el) { this->all_nb_local_element[partition_num(el)]++; for (CSR<UInt>::const_iterator part = ghost_partition.begin(el); part != ghost_partition.end(el); ++part) { this->all_nb_ghost_element[*part]++; } this->all_nb_element_to_send[partition_num(el)] += ghost_partition.getNbCols(el) + 1; } /// tag info std::vector<std::string> tag_names; this->getMeshData().getTagNames(tag_names, type); this->nb_tags = tag_names.size(); size(4) = nb_tags; for (UInt p = 0; p < nb_proc; ++p) { if (p != root) { size(1) = this->all_nb_local_element[p]; size(2) = this->all_nb_ghost_element[p]; size(3) = this->all_nb_element_to_send[p]; AKANTU_DEBUG_INFO( "Sending connectivities informations to proc " << p << " TAG(" << Tag::genTag(this->rank, this->message_count, Tag::_SIZES) << ")"); comm.send(size, p, Tag::genTag(this->rank, this->message_count, Tag::_SIZES)); } else { this->nb_local_element = this->all_nb_local_element[p]; this->nb_ghost_element = this->all_nb_ghost_element[p]; } } } else { for (UInt p = 0; p < this->nb_proc; ++p) { if (p != this->root) { AKANTU_DEBUG_INFO( "Sending empty connectivities informations to proc " << p << " TAG(" << Tag::genTag(this->rank, this->message_count, Tag::_SIZES) << ")"); comm.send(size, p, Tag::genTag(this->rank, this->message_count, Tag::_SIZES)); } } } } /* ------------------------------------------------------------------------ */ void MasterElementInfoPerProc::synchronizeConnectivities() { const Array<UInt> & partition_num = this->partition.getPartition(this->type, _not_ghost); const CSR<UInt> & ghost_partition = this->partition.getGhostPartitionCSR()(this->type, _not_ghost); std::vector<Array<UInt>> buffers(this->nb_proc); auto conn_it = this->mesh.getConnectivity(this->type, _not_ghost) .begin(this->nb_nodes_per_element); auto conn_end = this->mesh.getConnectivity(this->type, _not_ghost) .end(this->nb_nodes_per_element); /// copying the local connectivity auto part_it = partition_num.begin(); for (; conn_it != conn_end; ++conn_it, ++part_it) { const auto & conn = *conn_it; for (UInt i = 0; i < conn.size(); ++i) { buffers[*part_it].push_back(conn[i]); } } /// copying the connectivity of ghost element conn_it = this->mesh.getConnectivity(this->type, _not_ghost) .begin(this->nb_nodes_per_element); for (UInt el = 0; conn_it != conn_end; ++el, ++conn_it) { for (auto part = ghost_partition.begin(el); part != ghost_partition.end(el); ++part) { UInt proc = *part; const Vector<UInt> & conn = *conn_it; for (UInt i = 0; i < conn.size(); ++i) { buffers[proc].push_back(conn[i]); } } } #ifndef AKANTU_NDEBUG for (UInt p = 0; p < this->nb_proc; ++p) { UInt size = this->nb_nodes_per_element * (this->all_nb_local_element[p] + this->all_nb_ghost_element[p]); AKANTU_DEBUG_ASSERT( buffers[p].getSize() == size, "The connectivity data packed in the buffer are not correct"); } #endif /// send all connectivity and ghost information to all processors std::vector<CommunicationRequest> requests; for (UInt p = 0; p < this->nb_proc; ++p) { if (p != this->root) { AKANTU_DEBUG_INFO( "Sending connectivities to proc " << p << " TAG(" << Tag::genTag(this->rank, this->message_count, Tag::_CONNECTIVITY) << ")"); requests.push_back(comm.asyncSend( buffers[p], p, Tag::genTag(this->rank, this->message_count, Tag::_CONNECTIVITY))); } } Array<UInt> & old_nodes = this->getNodesGlobalIds(); /// create the renumbered connectivity AKANTU_DEBUG_INFO("Renumbering local connectivities"); MeshUtils::renumberMeshNodes(mesh, buffers[root], all_nb_local_element[root], all_nb_ghost_element[root], type, old_nodes); comm.waitAll(requests); comm.freeCommunicationRequest(requests); } /* ------------------------------------------------------------------------ */ void MasterElementInfoPerProc::synchronizePartitions() { const Array<UInt> & partition_num = this->partition.getPartition(this->type, _not_ghost); const CSR<UInt> & ghost_partition = this->partition.getGhostPartitionCSR()(this->type, _not_ghost); std::vector<Array<UInt>> buffers(this->partition.getNbPartition()); /// splitting the partition information to send them to processors Vector<UInt> count_by_proc(nb_proc, 0); for (UInt el = 0; el < nb_element; ++el) { UInt proc = partition_num(el); buffers[proc].push_back(ghost_partition.getNbCols(el)); UInt i(0); for (CSR<UInt>::const_iterator part = ghost_partition.begin(el); part != ghost_partition.end(el); ++part, ++i) { buffers[proc].push_back(*part); } } for (UInt el = 0; el < nb_element; ++el) { UInt i(0); for (CSR<UInt>::const_iterator part = ghost_partition.begin(el); part != ghost_partition.end(el); ++part, ++i) { buffers[*part].push_back(partition_num(el)); } } #ifndef AKANTU_NDEBUG for (UInt p = 0; p < this->nb_proc; ++p) { AKANTU_DEBUG_ASSERT( buffers[p].getSize() == (this->all_nb_ghost_element[p] + this->all_nb_element_to_send[p]), "Data stored in the buffer are most probably wrong"); } #endif std::vector<CommunicationRequest> requests; /// last data to compute the communication scheme for (UInt p = 0; p < this->nb_proc; ++p) { if (p != this->root) { AKANTU_DEBUG_INFO( "Sending partition informations to proc " << p << " TAG(" << Tag::genTag(this->rank, this->message_count, Tag::_PARTITIONS) << ")"); requests.push_back(comm.asyncSend( buffers[p], p, Tag::genTag(this->rank, this->message_count, Tag::_PARTITIONS))); } } if (Mesh::getSpatialDimension(this->type) == this->mesh.getSpatialDimension()) { AKANTU_DEBUG_INFO("Creating communications scheme"); this->fillCommunicationScheme(buffers[this->rank]); } comm.waitAll(requests); comm.freeCommunicationRequest(requests); } /* -------------------------------------------------------------------------- */ void MasterElementInfoPerProc::synchronizeTags() { AKANTU_DEBUG_IN(); if (this->nb_tags == 0) { AKANTU_DEBUG_OUT(); return; } UInt mesh_data_sizes_buffer_length; MeshData & mesh_data = this->getMeshData(); /// tag info std::vector<std::string> tag_names; mesh_data.getTagNames(tag_names, type); // Make sure the tags are sorted (or at least not in random order), // because they come from a map !! std::sort(tag_names.begin(), tag_names.end()); // Sending information about the tags in mesh_data: name, data type and // number of components of the underlying array associated to the current // type DynamicCommunicationBuffer mesh_data_sizes_buffer; std::vector<std::string>::const_iterator names_it = tag_names.begin(); std::vector<std::string>::const_iterator names_end = tag_names.end(); for (; names_it != names_end; ++names_it) { mesh_data_sizes_buffer << *names_it; mesh_data_sizes_buffer << mesh_data.getTypeCode(*names_it); mesh_data_sizes_buffer << mesh_data.getNbComponent(*names_it, type); } mesh_data_sizes_buffer_length = mesh_data_sizes_buffer.getSize(); AKANTU_DEBUG_INFO( "Broadcasting the size of the information about the mesh data tags: (" << mesh_data_sizes_buffer_length << ")."); comm.broadcast(mesh_data_sizes_buffer_length, root); AKANTU_DEBUG_INFO( "Broadcasting the information about the mesh data tags, addr " << (void *)mesh_data_sizes_buffer.storage()); if (mesh_data_sizes_buffer_length != 0) comm.broadcast(mesh_data_sizes_buffer, root); if (mesh_data_sizes_buffer_length != 0) { // Sending the actual data to each processor DynamicCommunicationBuffer * buffers = new DynamicCommunicationBuffer[nb_proc]; std::vector<std::string>::const_iterator names_it = tag_names.begin(); std::vector<std::string>::const_iterator names_end = tag_names.end(); // Loop over each tag for the current type for (; names_it != names_end; ++names_it) { // Type code of the current tag (i.e. the tag named *names_it) this->fillTagBuffer(buffers, *names_it); } std::vector<CommunicationRequest> requests; for (UInt p = 0; p < nb_proc; ++p) { if (p != root) { AKANTU_DEBUG_INFO("Sending " << buffers[p].getSize() << " bytes of mesh data to proc " << p << " TAG(" << Tag::genTag(this->rank, this->message_count, Tag::_MESH_DATA) << ")"); requests.push_back(comm.asyncSend( buffers[p], p, Tag::genTag(this->rank, this->message_count, Tag::_MESH_DATA))); } } names_it = tag_names.begin(); // Loop over each tag for the current type for (; names_it != names_end; ++names_it) { // Reinitializing the mesh data on the master this->fillMeshData(buffers[root], *names_it, mesh_data.getTypeCode(*names_it), mesh_data.getNbComponent(*names_it, type)); } comm.waitAll(requests); comm.freeCommunicationRequest(requests); requests.clear(); delete[] buffers; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <typename T> void MasterElementInfoPerProc::fillTagBufferTemplated( DynamicCommunicationBuffer * buffers, const std::string & tag_name) { MeshData & mesh_data = this->getMeshData(); const Array<T> & data = mesh_data.getElementalDataArray<T>(tag_name, type); const Array<UInt> & partition_num = this->partition.getPartition(this->type, _not_ghost); const CSR<UInt> & ghost_partition = this->partition.getGhostPartitionCSR()(this->type, _not_ghost); // Not possible to use the iterator because it potentially triggers the // creation of complex // type templates (such as akantu::Vector< std::vector<Element> > which don't // implement the right interface // (e.g. operator<< in that case). // typename Array<T>::template const_iterator< Vector<T> > data_it = // data.begin(data.getNbComponent()); // typename Array<T>::template const_iterator< Vector<T> > data_end = // data.end(data.getNbComponent()); const T * data_it = data.storage(); const T * data_end = data.storage() + data.getSize() * data.getNbComponent(); const UInt * part = partition_num.storage(); /// copying the data, element by element for (; data_it != data_end; ++part) { for (UInt j(0); j < data.getNbComponent(); ++j, ++data_it) { buffers[*part] << *data_it; } } data_it = data.storage(); /// copying the data for the ghost element for (UInt el(0); data_it != data_end; data_it += data.getNbComponent(), ++el) { CSR<UInt>::const_iterator it = ghost_partition.begin(el); CSR<UInt>::const_iterator end = ghost_partition.end(el); for (; it != end; ++it) { UInt proc = *it; for (UInt j(0); j < data.getNbComponent(); ++j) { buffers[proc] << data_it[j]; } } } } /* -------------------------------------------------------------------------- */ void MasterElementInfoPerProc::fillTagBuffer( DynamicCommunicationBuffer * buffers, const std::string & tag_name) { MeshData & mesh_data = this->getMeshData(); #define AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA(r, extra_param, elem) \ case BOOST_PP_TUPLE_ELEM(2, 0, elem): { \ this->fillTagBufferTemplated<BOOST_PP_TUPLE_ELEM(2, 1, elem)>(buffers, \ tag_name); \ break; \ } MeshDataTypeCode data_type_code = mesh_data.getTypeCode(tag_name); switch (data_type_code) { BOOST_PP_SEQ_FOR_EACH(AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA, , AKANTU_MESH_DATA_TYPES) default: AKANTU_DEBUG_ERROR("Could not obtain the type of tag" << tag_name << "!"); break; } #undef AKANTU_DISTRIBUTED_SYNHRONIZER_TAG_DATA } /* -------------------------------------------------------------------------- */ void MasterElementInfoPerProc::synchronizeGroups() { AKANTU_DEBUG_IN(); DynamicCommunicationBuffer * buffers = new DynamicCommunicationBuffer[nb_proc]; - typedef std::vector<std::vector<std::string>> ElementToGroup; + using ElementToGroup = std::vector<std::vector<std::string>>; ElementToGroup element_to_group; element_to_group.resize(nb_element); - GroupManager::const_element_group_iterator egi = mesh.element_group_begin(); - GroupManager::const_element_group_iterator ege = mesh.element_group_end(); + auto egi = mesh.element_group_begin(); + auto ege = mesh.element_group_end(); for (; egi != ege; ++egi) { ElementGroup & eg = *(egi->second); std::string name = egi->first; - ElementGroup::const_element_iterator eit = - eg.element_begin(type, _not_ghost); - ElementGroup::const_element_iterator eend = - eg.element_end(type, _not_ghost); - for (; eit != eend; ++eit) { - element_to_group[*eit].push_back(name); + for (const auto & element : eg.getElements(type, _not_ghost)) { + element_to_group[element].push_back(name); } - eit = eg.element_begin(type, _not_ghost); - if (eit != eend) + auto eit = eg.begin(type, _not_ghost); + if (eit != eg.end(type, _not_ghost)) const_cast<Array<UInt> &>(eg.getElements(type)).empty(); } - const Array<UInt> & partition_num = + const auto & partition_num = this->partition.getPartition(this->type, _not_ghost); - const CSR<UInt> & ghost_partition = + const auto & ghost_partition = this->partition.getGhostPartitionCSR()(this->type, _not_ghost); - /// preparing the buffers - const UInt * part = partition_num.storage(); - /// copying the data, element by element ElementToGroup::const_iterator data_it = element_to_group.begin(); ElementToGroup::const_iterator data_end = element_to_group.end(); - for (; data_it != data_end; ++part, ++data_it) { - buffers[*part] << *data_it; + for (auto pair : zip(partition_num, element_to_group)) { + buffers[std::get<0>(pair)] << std::get<1>(pair); } data_it = element_to_group.begin(); /// copying the data for the ghost element for (UInt el(0); data_it != data_end; ++data_it, ++el) { CSR<UInt>::const_iterator it = ghost_partition.begin(el); CSR<UInt>::const_iterator end = ghost_partition.end(el); for (; it != end; ++it) { UInt proc = *it; buffers[proc] << *data_it; } } std::vector<CommunicationRequest> requests; for (UInt p = 0; p < this->nb_proc; ++p) { if (p == this->rank) continue; AKANTU_DEBUG_INFO("Sending element groups to proc " << p << " TAG(" << Tag::genTag(this->rank, p, Tag::_ELEMENT_GROUP) << ")"); requests.push_back(comm.asyncSend( buffers[p], p, Tag::genTag(this->rank, p, Tag::_ELEMENT_GROUP))); } this->fillElementGroupsFromBuffer(buffers[this->rank]); comm.waitAll(requests); comm.freeCommunicationRequest(requests); requests.clear(); delete[] buffers; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -} // akantu +} // namespace akantu diff --git a/test/test_common/test_grid.cc b/test/test_common/test_grid.cc index 3edc9d699..6dff392f9 100644 --- a/test/test_common/test_grid.cc +++ b/test/test_common/test_grid.cc @@ -1,108 +1,107 @@ /** * @file test_grid.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Jul 15 2010 * @date last modification: Thu Aug 06 2015 * * @brief Test the grid object * * @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 <iostream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_grid_dynamic.hh" #include "mesh.hh" #include "mesh_io.hh" using namespace akantu; int main(int argc, char *argv[]) { const UInt spatial_dimension = 2; akantu::initialize(argc, argv); Mesh circle(spatial_dimension); circle.read("circle.msh"); - circle.computeBoundingBox(); const Vector<Real> & l = circle.getLocalLowerBounds(); const Vector<Real> & u = circle.getLocalUpperBounds(); Real spacing[spatial_dimension] = {0.2, 0.2}; Vector<Real> s(spacing, spatial_dimension); Vector<Real> c = u; c += l; c /= 2.; SpatialGrid<Element> grid(spatial_dimension, s, c); Vector<Real> bary(spatial_dimension); Element el; el.ghost_type = _not_ghost; Mesh::type_iterator it = circle.firstType(spatial_dimension); Mesh::type_iterator last_type = circle.lastType (spatial_dimension); for(; it != last_type; ++it) { UInt nb_element = circle.getNbElement(*it); el.type = *it; for (UInt e = 0; e < nb_element; ++e) { circle.getBarycenter(e, el.type, bary.storage()); el.element = e; grid.insert(el, bary); } } std::cout << grid << std::endl; Mesh mesh(spatial_dimension, "save"); grid.saveAsMesh(mesh); mesh.write("grid.msh"); Vector<Real> pos(spatial_dimension); // const SpatialGrid<Element>::CellID & id = grid.getCellID(pos); // #if !defined AKANTU_NDEBUG // SpatialGrid<Element>::neighbor_cells_iterator nit = grid.beginNeighborCells(id); // SpatialGrid<Element>::neighbor_cells_iterator nend = grid.endNeighborCells(id); // for(;nit != nend; ++nit) { // std::cout << std::endl; // const SpatialGrid<Element>::Cell & cell = grid.getCell(*nit); // SpatialGrid<Element>::Cell::const_iterator cit = cell.begin(); // SpatialGrid<Element>::Cell::position_iterator pit = cell.begin_pos(); // SpatialGrid<Element>::Cell::const_iterator cend = cell.end(); // for (; cit != cend; ++cit, ++pit) { // std::cout << *cit << " " << *pit << std::endl; // } // } // #endif akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fe_engine/test_fe_engine_gauss_integration.cc b/test/test_fe_engine/test_fe_engine_gauss_integration.cc index 225b15096..815cc9ae8 100644 --- a/test/test_fe_engine/test_fe_engine_gauss_integration.cc +++ b/test/test_fe_engine/test_fe_engine_gauss_integration.cc @@ -1,204 +1,203 @@ /** * @file test_fe_engine_precomputation.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Jun 14 2010 * @date last modification: Mon Jul 13 2015 * * @brief test integration on elements, this test consider that mesh is a cube * * @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 "fe_engine.hh" #include "shape_lagrange.hh" #include "integrator_gauss.hh" /* -------------------------------------------------------------------------- */ #include <iostream> /* -------------------------------------------------------------------------- */ using namespace akantu; typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange> FEM; const ElementType type = TYPE; // cst x x^2 x^3 // x^4 x^5 Real alpha[3][6] = {{0.40062394, 0.13703225, 0.51731446, 0.87830084, 0.5410543, 0.71842292}, // x {0.41861835, 0.11080576, 0.49874043, 0.49077504, 0.85073835, 0.66259755}, // y {0.92620845, 0.7503478, 0.62962232, 0.31662719, 0.64069644, 0.30878135}}; // z static Vector<Real> eval_poly(UInt degree, const Vector<Real> & x) { Vector<Real> res(x.size()); for (UInt i = 0; i < degree + 1; ++i) { for (UInt d = 0; d < x.size(); ++d) { res(d) += std::pow(x(d), i) * alpha[d][i]; } } return res; } static Vector<Real> eval_int(UInt degree, const Vector<Real> & a, const Vector<Real> & b) { Vector<Real> res(a.size()); for (UInt i = 0; i < degree + 1; ++i) { for (UInt d = 0; d < a.size(); ++d) { res(d) += (std::pow(b(d), i + 1) - std::pow(a(d), i + 1)) * alpha[d][i] / Real(i + 1); } } if (a.size() == 3) { res(_x) *= std::abs(b(_y) - a(_y)) * std::abs(b(_z) - a(_z)); res(_y) *= std::abs(b(_x) - a(_x)) * std::abs(b(_z) - a(_z)); res(_z) *= std::abs(b(_y) - a(_y)) * std::abs(b(_x) - a(_x)); } else if (a.size() == 2) { res(_x) *= std::abs(b(_y) - a(_y)); res(_y) *= std::abs(b(_x) - a(_x)); } return res; } template <UInt degree> static Vector<Real> integrate_poly(UInt poly_degree, FEM & fem) { Mesh & mesh = fem.getMesh(); UInt dim = mesh.getSpatialDimension(); Matrix<Real> integration_points = fem.getIntegrator().getIntegrationPoints<type, degree>(); // Vector<Real> integration_weights = // fem.getIntegrator().getIntegrationWeights<type, degree>(); // for (UInt i = 0; i < integration_points.cols(); ++i) { // std::cout << "q(" << i << ") = " << Vector<Real>(integration_points(i)) // << " - w(" << i << ") = "<< integration_weights[i] << std::endl; // } UInt nb_integration_points = integration_points.cols(); UInt nb_element = mesh.getNbElement(type); UInt shapes_size = ElementClass<type>::getShapeSize(); Array<Real> shapes(0, shapes_size); fem.getShapeFunctions().computeShapesOnIntegrationPoints<type>( mesh.getNodes(), integration_points, shapes, _not_ghost); UInt vect_size = nb_integration_points * nb_element; Array<Real> integration_points_pos(vect_size, dim); fem.getShapeFunctions().interpolateOnIntegrationPoints<type>( mesh.getNodes(), integration_points_pos, dim, shapes); Array<Real> polynomial(vect_size, dim); Array<Real>::vector_iterator P_it = polynomial.begin(dim); Array<Real>::vector_iterator P_end = polynomial.end(dim); Array<Real>::const_vector_iterator x_it = integration_points_pos.begin(dim); for (; P_it != P_end; ++P_it, ++x_it) { *P_it = eval_poly(poly_degree, *x_it); // std::cout << "Q = " << *x_it << std::endl; // std::cout << "P(Q) = " << *P_it << std::endl; } Vector<Real> res(dim); Array<Real> polynomial_1d(vect_size, 1); for (UInt d = 0; d < dim; ++d) { Array<Real>::const_vector_iterator P_it = polynomial.begin(dim); Array<Real>::const_vector_iterator P_end = polynomial.end(dim); Array<Real>::scalar_iterator P1_it = polynomial_1d.begin(); for (; P_it != P_end; ++P_it, ++P1_it) { *P1_it = (*P_it)(d); // std::cout << "P(Q, d) = " << *P1_it << std::endl; } res(d) = fem.getIntegrator().integrate<type, degree>(polynomial_1d); } return res; } int main(int argc, char * argv[]) { akantu::initialize(argc, argv); const UInt dim = ElementClass<type>::getSpatialDimension(); Mesh mesh(dim); std::stringstream meshfilename; meshfilename << type << ".msh"; mesh.read(meshfilename.str()); FEM fem(mesh, dim, "my_fem"); - mesh.computeBoundingBox(); const Vector<Real> & lower = mesh.getLowerBounds(); const Vector<Real> & upper = mesh.getUpperBounds(); bool ok = true; for (UInt d = 0; d < 6; ++d) { Vector<Real> res(dim); switch (d) { case 0: res = integrate_poly<1>(d, fem); break; case 1: res = integrate_poly<1>(d, fem); break; case 2: res = integrate_poly<2>(d, fem); break; case 3: res = integrate_poly<3>(d, fem); break; case 4: res = integrate_poly<4>(d, fem); break; case 5: res = integrate_poly<5>(d, fem); break; } Vector<Real> exact(dim); exact = eval_int(d, lower, upper); Vector<Real> error(dim); error = exact - res; Real error_n = error.norm<L_inf>(); if (error_n > 5e-14) { std::cout << d << " -> Resultat " << res << " - "; std::cout << "Exact" << exact << " -- "; std::cout << error << " {" << error_n << "}" << std::endl; ok = false; } } finalize(); if (ok) return 0; else return 1; } diff --git a/test/test_fe_engine/test_inverse_map.cc b/test/test_fe_engine/test_inverse_map.cc index 5aef24bce..9ecdcb234 100644 --- a/test/test_fe_engine/test_inverse_map.cc +++ b/test/test_fe_engine/test_inverse_map.cc @@ -1,106 +1,106 @@ /** * @file test_inverse_map.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * * @date creation: Fri Sep 03 2010 * @date last modification: Thu Oct 15 2015 * * @brief test of the fem class * * @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_common.hh" #include "fe_engine.hh" -#include "shape_lagrange.hh" #include "integrator_gauss.hh" +#include "shape_lagrange.hh" /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <iostream> /* -------------------------------------------------------------------------- */ using namespace akantu; -int main(int argc, char *argv[]) { +int main(int argc, char * argv[]) { akantu::initialize(argc, argv); debug::setDebugLevel(dblTest); const ElementType type = TYPE; UInt dim = ElementClass<type>::getSpatialDimension(); Mesh my_mesh(dim); - my_mesh.computeBoundingBox(); const Vector<Real> & lower = my_mesh.getLowerBounds(); const Vector<Real> & upper = my_mesh.getUpperBounds(); - std::stringstream meshfilename; meshfilename << type << ".msh"; + std::stringstream meshfilename; + meshfilename << type << ".msh"; my_mesh.read(meshfilename.str()); UInt nb_elements = my_mesh.getNbElement(type); /// - FEEngineTemplate<IntegratorGauss,ShapeLagrange> *fem = - new FEEngineTemplate<IntegratorGauss,ShapeLagrange>(my_mesh, dim, "my_fem"); + FEEngineTemplate<IntegratorGauss, ShapeLagrange> * fem = + new FEEngineTemplate<IntegratorGauss, ShapeLagrange>(my_mesh, dim, + "my_fem"); fem->initShapeFunctions(); UInt nb_quad_points = fem->getNbIntegrationPoints(type); /// get the quadrature points coordinates - Array<Real> coord_on_quad(nb_quad_points*nb_elements, - my_mesh.getSpatialDimension(), - "coord_on_quad"); - - fem->interpolateOnIntegrationPoints(my_mesh.getNodes(), - coord_on_quad, - my_mesh.getSpatialDimension(), - type); + Array<Real> coord_on_quad(nb_quad_points * nb_elements, + my_mesh.getSpatialDimension(), "coord_on_quad"); + fem->interpolateOnIntegrationPoints(my_mesh.getNodes(), coord_on_quad, + my_mesh.getSpatialDimension(), type); /// loop over the quadrature points - Array<Real>::iterator< Vector<Real> > it = coord_on_quad.begin(dim); + Array<Real>::iterator<Vector<Real>> it = coord_on_quad.begin(dim); Vector<Real> natural_coords(dim); Matrix<Real> quad = GaussIntegrationElement<type>::getQuadraturePoints(); - for(UInt el = 0 ; el < nb_elements ; ++el){ - for(UInt q = 0 ; q < nb_quad_points ; ++q){ + for (UInt el = 0; el < nb_elements; ++el) { + for (UInt q = 0; q < nb_quad_points; ++q) { fem->inverseMap(*it, el, type, natural_coords); for (UInt i = 0; i < dim; ++i) { - __attribute__ ((unused)) const Real eps = 1e-13; - AKANTU_DEBUG_ASSERT(std::abs((natural_coords(i) - quad(i,q))/(upper(i)-lower(i))) < eps, - "real coordinates inversion test failed:" - << natural_coords(i) << " - " << quad(i, q) - << " = " << (natural_coords(i) - quad(i, q))/(upper(i)-lower(i))); + __attribute__((unused)) const Real eps = 1e-13; + AKANTU_DEBUG_ASSERT( + std::abs((natural_coords(i) - quad(i, q)) / (upper(i) - lower(i))) < + eps, + "real coordinates inversion test failed:" + << natural_coords(i) << " - " << quad(i, q) << " = " + << (natural_coords(i) - quad(i, q)) / (upper(i) - lower(i))); } ++it; } } - std::cout << "inverse completed over " << nb_elements << " elements" << std::endl; + std::cout << "inverse completed over " << nb_elements << " elements" + << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/CMakeLists.txt b/test/test_mesh_utils/CMakeLists.txt index 70f83bed2..f96c07092 100644 --- a/test/test_mesh_utils/CMakeLists.txt +++ b/test/test_mesh_utils/CMakeLists.txt @@ -1,50 +1,55 @@ #=============================================================================== # @file CMakeLists.txt # # @author Nicolas Richart <nicolas.richart@epfl.ch> # # @date creation: Fri Oct 22 2010 # @date last modification: Fri Sep 18 2015 # # @brief configuration for MeshUtils tests # # @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 # #=============================================================================== #=============================================================================== # List of tests #=============================================================================== add_akantu_test(test_mesh_io "Test mesh io object") add_akantu_test(test_pbc_tweak "Test pbc facilities") add_akantu_test(test_buildfacets "Tests for the generation of facets") add_akantu_test(test_segment_nodetype "segment_nodetype") register_test(test_purify_mesh SOURCES test_purify_mesh.cc FILES_TO_COPY purify_mesh.msh PACKAGE core ) -add_akantu_test(test_mesh_partitionate "Test mesh partition creation") - +add_mesh(test_mesh_iterators_mesh iterators_mesh.geo 3 1 OUTPUT iterators_mesh.msh) +register_test(test_mesh_iterators + SOURCES test_mesh_iterators.cc + PACKAGE core + DEPENDS test_mesh_iterators_mesh + ) +add_akantu_test(test_mesh_partitionate "Test mesh partition creation") diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_20.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_20.cc index 9f814dc7b..2934e326c 100644 --- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_20.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_20.cc @@ -1,143 +1,143 @@ /** * @file test_buildfacets_hexahedron_20.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue May 08 2012 * @date last modification: Sat Sep 19 2015 * * @brief Test to check the building of the facets. Mesh with hexahedrons * * @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 <iostream> #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 3; const ElementType type = _hexahedron_20; Mesh mesh(spatial_dimension); mesh.read("hexahedron_20.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); // debug::setDebugLevel(dblDump); // std::cout << mesh << std::endl; // std::cout << mesh_facets << std::endl; const ElementType type_facet = mesh.getFacetType(type); const ElementType type_subfacet = mesh.getFacetType(type_facet); const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ const Array< std::vector<Element> > & el_to_subel3 = mesh_facets.getElementToSubelement(type_facet); const Array< std::vector<Element> > & el_to_subel2 = mesh_facets.getElementToSubelement(type_subfacet); const Array< std::vector<Element> > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subsubfacet); std::cout << "ElementToSubelement3" << std::endl; for (UInt i = 0; i < el_to_subel3.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel3(i)[j].type << " " << el_to_subel3(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement2" << std::endl; for (UInt i = 0; i < el_to_subel2.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel2(i).size(); ++j){ std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement1" << std::endl; for (UInt i = 0; i < el_to_subel1.getSize(); ++i) { std::cout << type_subsubfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel1(i).size(); ++j){ std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element << ", "; } std::cout << " " << std::endl; } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array<Element> & subel_to_el3 = mesh_facets.getSubelementToElement(type); const Array<Element> & subel_to_el2 = mesh_facets.getSubelementToElement(type_facet); const Array<Element> & subel_to_el1 = mesh_facets.getSubelementToElement(type_subfacet); std::cout << " " << std::endl; std::cout << "SubelementToElement3" << std::endl; for (UInt i = 0; i < subel_to_el3.getSize(); ++i) { std::cout << type << " " << i << " connected to "; for (UInt j = 0; j < 6; ++j){ std::cout << subel_to_el3(i, j).type << " " << subel_to_el3(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 4; ++j){ std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement1" << std::endl; for (UInt i = 0; i < subel_to_el1.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element << ", "; } std::cout << " " << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_8.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_8.cc index 1ea23ee9c..21f6a9261 100644 --- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_8.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron_8.cc @@ -1,144 +1,144 @@ /** * @file test_buildfacets_hexahedron_8.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue May 08 2012 * @date last modification: Sat Sep 19 2015 * * @brief Test to check the building of the facets. Mesh with hexahedrons * * @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 <iostream> #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 3; const ElementType type = _hexahedron_8; Mesh mesh(spatial_dimension); mesh.read("hexahedron_8.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); // debug::setDebugLevel(dblDump); // std::cout << mesh << std::endl; // std::cout << mesh_facets << std::endl; const ElementType type_facet = mesh.getFacetType(type); const ElementType type_subfacet = mesh.getFacetType(type_facet); const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ const Array< std::vector<Element> > & el_to_subel3 = mesh_facets.getElementToSubelement(type_facet); const Array< std::vector<Element> > & el_to_subel2 = mesh_facets.getElementToSubelement(type_subfacet); const Array< std::vector<Element> > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subsubfacet); std::cout << "ElementToSubelement3" << std::endl; for (UInt i = 0; i < el_to_subel3.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel3(i)[j].type << " " << el_to_subel3(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement2" << std::endl; for (UInt i = 0; i < el_to_subel2.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel2(i).size(); ++j){ std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement1" << std::endl; for (UInt i = 0; i < el_to_subel1.getSize(); ++i) { std::cout << type_subsubfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel1(i).size(); ++j){ std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element << ", "; } std::cout << " " << std::endl; } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array<Element> & subel_to_el3 = mesh_facets.getSubelementToElement(type); const Array<Element> & subel_to_el2 = mesh_facets.getSubelementToElement(type_facet); const Array<Element> & subel_to_el1 = mesh_facets.getSubelementToElement(type_subfacet); std::cout << " " << std::endl; std::cout << "SubelementToElement3" << std::endl; for (UInt i = 0; i < subel_to_el3.getSize(); ++i) { std::cout << type << " " << i << " connected to "; for (UInt j = 0; j < 6; ++j){ std::cout << subel_to_el3(i, j).type << " " << subel_to_el3(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 4; ++j){ std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement1" << std::endl; for (UInt i = 0; i < subel_to_el1.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element << ", "; } std::cout << " " << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_linear.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_linear.cc index 05aa17362..e9d6975a8 100644 --- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_linear.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_linear.cc @@ -1,128 +1,128 @@ /** * @file test_buildfacets_mixed2d_linear.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Fri Sep 18 2015 * @date last modification: Sat Sep 19 2015 * * @brief Test to check the building of the facets. Mesh with quadrangles * and triangles * * @section LICENSE * * Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory * (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <iostream> #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 2; const ElementType type1 = _quadrangle_4; const ElementType type2 = _triangle_3; Mesh mesh(spatial_dimension); mesh.read("mixed2d_linear.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); const ElementType type_facet = mesh.getFacetType(type1); const ElementType type_subfacet = mesh.getFacetType(type_facet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ const Array< std::vector<Element> > & el_to_subel2 = mesh_facets.getElementToSubelement(type_facet); const Array< std::vector<Element> > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subfacet); std::cout << "ElementToSubelement2" << std::endl; for (UInt i = 0; i < el_to_subel2.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement1" << std::endl; for (UInt i = 0; i < el_to_subel1.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel1(i).size(); ++j){ std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element << ", "; } std::cout << " " << std::endl; } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array<Element> & subel_to_el2_1 = mesh_facets.getSubelementToElement(type1); const Array<Element> & subel_to_el2_2 = mesh_facets.getSubelementToElement(type2); const Array<Element> & subel_to_el1 = mesh_facets.getSubelementToElement(type_facet); std::cout << " " << std::endl; std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2_1.getSize(); ++i) { std::cout << type1 << " " << i << " connected to "; for (UInt j = 0; j < 4; ++j){ std::cout << subel_to_el2_1(i, j).type << " " << subel_to_el2_1(i, j).element << ", "; } std::cout << " " << std::endl; } for (UInt i = 0; i < subel_to_el2_2.getSize(); ++i) { std::cout << type2 << " " << i << " connected to "; for (UInt j = 0; j < 3; ++j){ std::cout << subel_to_el2_2(i, j).type << " " << subel_to_el2_2(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement1" << std::endl; for (UInt i = 0; i < subel_to_el1.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element << ", "; } std::cout << " " << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_quadratic.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_quadratic.cc index 96bbd9bda..e13f63e65 100644 --- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_quadratic.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed2d_quadratic.cc @@ -1,128 +1,128 @@ /** * @file test_buildfacets_mixed2d_quadratic.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Fri Sep 18 2015 * @date last modification: Sat Sep 19 2015 * * @brief Test to check the building of the facets. Mesh with quadrangles * and triangles * * @section LICENSE * * Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory * (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <iostream> #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 2; const ElementType type1 = _quadrangle_8; const ElementType type2 = _triangle_6; Mesh mesh(spatial_dimension); mesh.read("mixed2d_quadratic.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); const ElementType type_facet = mesh.getFacetType(type1); const ElementType type_subfacet = mesh.getFacetType(type_facet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ const Array< std::vector<Element> > & el_to_subel2 = mesh_facets.getElementToSubelement(type_facet); const Array< std::vector<Element> > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subfacet); std::cout << "ElementToSubelement2" << std::endl; for (UInt i = 0; i < el_to_subel2.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement1" << std::endl; for (UInt i = 0; i < el_to_subel1.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel1(i).size(); ++j){ std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element << ", "; } std::cout << " " << std::endl; } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array<Element> & subel_to_el2_1 = mesh_facets.getSubelementToElement(type1); const Array<Element> & subel_to_el2_2 = mesh_facets.getSubelementToElement(type2); const Array<Element> & subel_to_el1 = mesh_facets.getSubelementToElement(type_facet); std::cout << " " << std::endl; std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2_1.getSize(); ++i) { std::cout << type1 << " " << i << " connected to "; for (UInt j = 0; j < 4; ++j){ std::cout << subel_to_el2_1(i, j).type << " " << subel_to_el2_1(i, j).element << ", "; } std::cout << " " << std::endl; } for (UInt i = 0; i < subel_to_el2_2.getSize(); ++i) { std::cout << type2 << " " << i << " connected to "; for (UInt j = 0; j < 3; ++j){ std::cout << subel_to_el2_2(i, j).type << " " << subel_to_el2_2(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement1" << std::endl; for (UInt i = 0; i < subel_to_el1.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element << ", "; } std::cout << " " << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_linear.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_linear.cc index 13fd0dd0e..452d24767 100644 --- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_linear.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_linear.cc @@ -1,167 +1,167 @@ /** * @file test_buildfacets_mixed3d_linear.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Tue May 08 2012 * @date last modification: Sat Sep 19 2015 * * @brief Test to check the building of the facets. Mesh with hexahedrons * and pentahedrons * * @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 <iostream> #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 3; const ElementType type1 = _hexahedron_8; const ElementType type2 = _pentahedron_6; Mesh mesh(spatial_dimension); mesh.read("mixed3d_linear.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); const ElementType type_facet1 = mesh.getFacetType(type1); const ElementType type_facet2 = mesh.getFacetType(type2); const ElementType type_subfacet = mesh.getFacetType(type_facet1); const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ const Array< std::vector<Element> > & el_to_subel3_1 = mesh_facets.getElementToSubelement(type_facet1); const Array< std::vector<Element> > & el_to_subel3_2 = mesh_facets.getElementToSubelement(type_facet2); const Array< std::vector<Element> > & el_to_subel2 = mesh_facets.getElementToSubelement(type_subfacet); const Array< std::vector<Element> > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subsubfacet); std::cout << "ElementToSubelement3" << std::endl; for (UInt i = 0; i < el_to_subel3_1.getSize(); ++i) { std::cout << type_facet1 << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel3_1(i)[j].type << " " << el_to_subel3_1(i)[j].element << ", "; } std::cout << " " << std::endl; } for (UInt i = 0; i < el_to_subel3_2.getSize(); ++i) { std::cout << type_facet2 << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel3_2(i)[j].type << " " << el_to_subel3_2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement2" << std::endl; for (UInt i = 0; i < el_to_subel2.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel2(i).size(); ++j){ std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement1" << std::endl; for (UInt i = 0; i < el_to_subel1.getSize(); ++i) { std::cout << type_subsubfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel1(i).size(); ++j){ std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element << ", "; } std::cout << " " << std::endl; } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array<Element> & subel_to_el3_1 = mesh_facets.getSubelementToElement(type1); const Array<Element> & subel_to_el3_2 = mesh_facets.getSubelementToElement(type2); const Array<Element> & subel_to_el2_1 = mesh_facets.getSubelementToElement(type_facet1); const Array<Element> & subel_to_el2_2 = mesh_facets.getSubelementToElement(type_facet2); const Array<Element> & subel_to_el1 = mesh_facets.getSubelementToElement(type_subfacet); std::cout << " " << std::endl; std::cout << "SubelementToElement3" << std::endl; for (UInt i = 0; i < subel_to_el3_1.getSize(); ++i) { std::cout << type1 << " " << i << " connected to "; for (UInt j = 0; j < 6; ++j){ std::cout << subel_to_el3_1(i, j).type << " " << subel_to_el3_1(i, j).element << ", "; } std::cout << " " << std::endl; } for (UInt i = 0; i < subel_to_el3_2.getSize(); ++i) { std::cout << type2 << " " << i << " connected to "; for (UInt j = 0; j < 5; ++j){ std::cout << subel_to_el3_2(i, j).type << " " << subel_to_el3_2(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2_1.getSize(); ++i) { std::cout << type_facet1 << " " << i << " connected to "; for (UInt j = 0; j < 4; ++j){ std::cout << subel_to_el2_1(i, j).type << " " << subel_to_el2_1(i, j).element << ", "; } std::cout << " " << std::endl; } for (UInt i = 0; i < subel_to_el2_2.getSize(); ++i) { std::cout << type_facet2 << " " << i << " connected to "; for (UInt j = 0; j < 3; ++j){ std::cout << subel_to_el2_2(i, j).type << " " << subel_to_el2_2(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement1" << std::endl; for (UInt i = 0; i < subel_to_el1.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element << ", "; } std::cout << " " << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_quadratic.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_quadratic.cc index 4ebdd56d5..ab397a3d0 100644 --- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_quadratic.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_mixed3d_quadratic.cc @@ -1,169 +1,169 @@ /** * @file test_buildfacets_mixed3d_quadratic.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Tue May 08 2012 * @date last modification: Sat Sep 19 2015 * * @brief Test to check the building of the facets. Mesh with hexahedrons * and pentahedrons * * @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 <iostream> #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 3; const ElementType type1 = _hexahedron_20; const ElementType type2 = _pentahedron_15; Mesh mesh(spatial_dimension); mesh.read("mixed3d_quadratic.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); const ElementType type_facet1 = mesh.getFacetType(type1); const ElementType type_facet2 = mesh.getFacetType(type2); const ElementType type_subfacet = mesh.getFacetType(type_facet1); const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ const Array< std::vector<Element> > & el_to_subel3_1 = mesh_facets.getElementToSubelement(type_facet1); const Array< std::vector<Element> > & el_to_subel3_2 = mesh_facets.getElementToSubelement(type_facet2); const Array< std::vector<Element> > & el_to_subel2 = mesh_facets.getElementToSubelement(type_subfacet); const Array< std::vector<Element> > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subsubfacet); std::cout << "ElementToSubelement3" << std::endl; for (UInt i = 0; i < el_to_subel3_1.getSize(); ++i) { std::cout << type_facet1 << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel3_1(i)[j].type << " " << el_to_subel3_1(i)[j].element << ", "; } std::cout << " " << std::endl; } for (UInt i = 0; i < el_to_subel3_2.getSize(); ++i) { std::cout << type_facet2 << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel3_2(i)[j].type << " " << el_to_subel3_2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement2" << std::endl; for (UInt i = 0; i < el_to_subel2.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel2(i).size(); ++j){ std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement1" << std::endl; for (UInt i = 0; i < el_to_subel1.getSize(); ++i) { std::cout << type_subsubfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel1(i).size(); ++j){ std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element << ", "; } std::cout << " " << std::endl; } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array<Element> & subel_to_el3_1 = mesh_facets.getSubelementToElement(type1); const Array<Element> & subel_to_el3_2 = mesh_facets.getSubelementToElement(type2); const Array<Element> & subel_to_el2_1 = mesh_facets.getSubelementToElement(type_facet1); const Array<Element> & subel_to_el2_2 = mesh_facets.getSubelementToElement(type_facet2); const Array<Element> & subel_to_el1 = mesh_facets.getSubelementToElement(type_subfacet); std::cout << " " << std::endl; std::cout << "SubelementToElement3" << std::endl; for (UInt i = 0; i < subel_to_el3_1.getSize(); ++i) { std::cout << type1 << " " << i << " connected to "; for (UInt j = 0; j < 6; ++j){ std::cout << subel_to_el3_1(i, j).type << " " << subel_to_el3_1(i, j).element << ", "; } std::cout << " " << std::endl; } for (UInt i = 0; i < subel_to_el3_2.getSize(); ++i) { std::cout << type2 << " " << i << " connected to "; for (UInt j = 0; j < 5; ++j){ std::cout << subel_to_el3_2(i, j).type << " " << subel_to_el3_2(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2_1.getSize(); ++i) { std::cout << type_facet1 << " " << i << " connected to "; for (UInt j = 0; j < 4; ++j){ std::cout << subel_to_el2_1(i, j).type << " " << subel_to_el2_1(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2_2.getSize(); ++i) { std::cout << type_facet2 << " " << i << " connected to "; for (UInt j = 0; j < 3; ++j){ std::cout << subel_to_el2_2(i, j).type << " " << subel_to_el2_2(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement1" << std::endl; for (UInt i = 0; i < subel_to_el1.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element << ", "; } std::cout << " " << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_15.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_15.cc index 208ed4af1..1b63049d6 100644 --- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_15.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_15.cc @@ -1,148 +1,148 @@ /** * @file test_buildfacets_pentahedron_15.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Tue May 08 2012 * @date last modification: Mon Sep 28 2015 * * @brief Test for cohesive elements * * @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 <iostream> #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 3; const ElementType type = _pentahedron_15; Mesh mesh(spatial_dimension); mesh.read("pentahedron_15.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); Vector<ElementType> types_facet = mesh.getAllFacetTypes(type); const ElementType type_subfacet = mesh.getFacetType(types_facet(0)); const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ for (UInt ft = 0; ft < types_facet.size(); ++ft) { ElementType type_facet = types_facet(ft); Array< std::vector<Element> > & el_to_subel3 = mesh_facets.getElementToSubelement(type_facet); std::cout << "ElementToSubelement3" << std::endl; for (UInt i = 0; i < el_to_subel3.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel3(i)[j].type << " " << el_to_subel3(i)[j].element << ", "; } std::cout << " " << std::endl; } } const Array< std::vector<Element> > & el_to_subel2 = mesh_facets.getElementToSubelement(type_subfacet); const Array< std::vector<Element> > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subsubfacet); std::cout << "ElementToSubelement2" << std::endl; for (UInt i = 0; i < el_to_subel2.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel2(i).size(); ++j){ std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement1" << std::endl; for (UInt i = 0; i < el_to_subel1.getSize(); ++i) { std::cout << type_subsubfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel1(i).size(); ++j){ std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element << ", "; } std::cout << " " << std::endl; } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array<Element> & subel_to_el3 = mesh_facets.getSubelementToElement(type); std::cout << " " << std::endl; std::cout << "SubelementToElement3" << std::endl; for (UInt i = 0; i < subel_to_el3.getSize(); ++i) { std::cout << type << " " << i << " connected to "; for (UInt j = 0; j < subel_to_el3.getNbComponent(); ++j){ std::cout << subel_to_el3(i, j).type << " " << subel_to_el3(i, j).element << ", "; } std::cout << " " << std::endl; } for (UInt ft = 0; ft < types_facet.size(); ++ft) { ElementType type_facet = types_facet(ft); Array<Element> & subel_to_el2 = mesh_facets.getSubelementToElement(type_facet); std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < subel_to_el2.getNbComponent(); ++j){ std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element << ", "; } std::cout << " " << std::endl; } } const Array<Element> & subel_to_el1 = mesh_facets.getSubelementToElement(type_subfacet); std::cout << "SubelementToElement1" << std::endl; for (UInt i = 0; i < subel_to_el1.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < subel_to_el1.getNbComponent(); ++j){ std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element << ", "; } std::cout << " " << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_6.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_6.cc index b11759516..36b8b0033 100644 --- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_6.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_pentahedron_6.cc @@ -1,148 +1,148 @@ /** * @file test_buildfacets_pentahedron_6.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Tue May 08 2012 * @date last modification: Mon Sep 28 2015 * * @brief Test for cohesive elements * * @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 <iostream> #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 3; const ElementType type = _pentahedron_6; Mesh mesh(spatial_dimension); mesh.read("pentahedron_6.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); Vector<ElementType> types_facet = mesh.getAllFacetTypes(type); const ElementType type_subfacet = mesh.getFacetType(types_facet(0)); const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ for (UInt ft = 0; ft < types_facet.size(); ++ft) { ElementType type_facet = types_facet(ft); Array< std::vector<Element> > & el_to_subel3 = mesh_facets.getElementToSubelement(type_facet); std::cout << "ElementToSubelement3" << std::endl; for (UInt i = 0; i < el_to_subel3.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel3(i)[j].type << " " << el_to_subel3(i)[j].element << ", "; } std::cout << " " << std::endl; } } const Array< std::vector<Element> > & el_to_subel2 = mesh_facets.getElementToSubelement(type_subfacet); const Array< std::vector<Element> > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subsubfacet); std::cout << "ElementToSubelement2" << std::endl; for (UInt i = 0; i < el_to_subel2.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel2(i).size(); ++j){ std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement1" << std::endl; for (UInt i = 0; i < el_to_subel1.getSize(); ++i) { std::cout << type_subsubfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel1(i).size(); ++j){ std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element << ", "; } std::cout << " " << std::endl; } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array<Element> & subel_to_el3 = mesh_facets.getSubelementToElement(type); std::cout << " " << std::endl; std::cout << "SubelementToElement3" << std::endl; for (UInt i = 0; i < subel_to_el3.getSize(); ++i) { std::cout << type << " " << i << " connected to "; for (UInt j = 0; j < subel_to_el3.getNbComponent(); ++j){ std::cout << subel_to_el3(i, j).type << " " << subel_to_el3(i, j).element << ", "; } std::cout << " " << std::endl; } for (UInt ft = 0; ft < types_facet.size(); ++ft) { ElementType type_facet = types_facet(ft); Array<Element> & subel_to_el2 = mesh_facets.getSubelementToElement(type_facet); std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < subel_to_el2.getNbComponent(); ++j){ std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element << ", "; } std::cout << " " << std::endl; } } const Array<Element> & subel_to_el1 = mesh_facets.getSubelementToElement(type_subfacet); std::cout << "SubelementToElement1" << std::endl; for (UInt i = 0; i < subel_to_el1.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < subel_to_el1.getNbComponent(); ++j){ std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element << ", "; } std::cout << " " << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_4.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_4.cc index 52d73dd7b..c8c002fe8 100644 --- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_4.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_4.cc @@ -1,116 +1,116 @@ /** * @file test_buildfacets_quadrangle_4.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Fri Sep 18 2015 * @date last modification: Sat Sep 19 2015 * * @brief Test to check the building of the facets. Mesh with quadrangles * * @section LICENSE * * Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory * (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <iostream> #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 2; const ElementType type = _quadrangle_4; Mesh mesh(spatial_dimension); mesh.read("quadrangle_4.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); const ElementType type_facet = mesh.getFacetType(type); const ElementType type_subfacet = mesh.getFacetType(type_facet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ const Array< std::vector<Element> > & el_to_subel2 = mesh_facets.getElementToSubelement(type_facet); const Array< std::vector<Element> > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subfacet); std::cout << "ElementToSubelement2" << std::endl; for (UInt i = 0; i < el_to_subel2.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement1" << std::endl; for (UInt i = 0; i < el_to_subel1.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel1(i).size(); ++j){ std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element << ", "; } std::cout << " " << std::endl; } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array<Element> & subel_to_el2 = mesh_facets.getSubelementToElement(type); const Array<Element> & subel_to_el1 = mesh_facets.getSubelementToElement(type_facet); std::cout << " " << std::endl; std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2.getSize(); ++i) { std::cout << type << " " << i << " connected to "; for (UInt j = 0; j < 4; ++j){ std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement1" << std::endl; for (UInt i = 0; i < subel_to_el1.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element << ", "; } std::cout << " " << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_8.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_8.cc index 0072e9aa5..513ac474d 100644 --- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_8.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_quadrangle_8.cc @@ -1,116 +1,116 @@ /** * @file test_buildfacets_quadrangle_8.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Fri Sep 18 2015 * @date last modification: Sat Sep 19 2015 * * @brief Test to check the building of the facets. Mesh with quadrangles * * @section LICENSE * * Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory * (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <iostream> #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 2; const ElementType type = _quadrangle_8; Mesh mesh(spatial_dimension); mesh.read("quadrangle_8.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); const ElementType type_facet = mesh.getFacetType(type); const ElementType type_subfacet = mesh.getFacetType(type_facet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ const Array< std::vector<Element> > & el_to_subel2 = mesh_facets.getElementToSubelement(type_facet); const Array< std::vector<Element> > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subfacet); std::cout << "ElementToSubelement2" << std::endl; for (UInt i = 0; i < el_to_subel2.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement1" << std::endl; for (UInt i = 0; i < el_to_subel1.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel1(i).size(); ++j){ std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element << ", "; } std::cout << " " << std::endl; } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array<Element> & subel_to_el2 = mesh_facets.getSubelementToElement(type); const Array<Element> & subel_to_el1 = mesh_facets.getSubelementToElement(type_facet); std::cout << " " << std::endl; std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2.getSize(); ++i) { std::cout << type << " " << i << " connected to "; for (UInt j = 0; j < 4; ++j){ std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement1" << std::endl; for (UInt i = 0; i < subel_to_el1.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element << ", "; } std::cout << " " << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_tetrahedron_10.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_tetrahedron_10.cc index 70495db8b..8b9767f68 100644 --- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_tetrahedron_10.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_tetrahedron_10.cc @@ -1,143 +1,143 @@ /** * @file test_buildfacets_tetrahedron_10.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue May 08 2012 * @date last modification: Sat Sep 19 2015 * * @brief Test for cohesive elements * * @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 <iostream> #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 3; const ElementType type = _tetrahedron_10; Mesh mesh(spatial_dimension); mesh.read("tetrahedron_10.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); // debug::setDebugLevel(dblDump); // std::cout << mesh << std::endl; // std::cout << mesh_facets << std::endl; const ElementType type_facet = mesh.getFacetType(type); const ElementType type_subfacet = mesh.getFacetType(type_facet); const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ const Array< std::vector<Element> > & el_to_subel3 = mesh_facets.getElementToSubelement(type_facet); const Array< std::vector<Element> > & el_to_subel2 = mesh_facets.getElementToSubelement(type_subfacet); const Array< std::vector<Element> > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subsubfacet); std::cout << "ElementToSubelement3" << std::endl; for (UInt i = 0; i < el_to_subel3.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel3(i)[j].type << " " << el_to_subel3(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement2" << std::endl; for (UInt i = 0; i < el_to_subel2.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel2(i).size(); ++j){ std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement1" << std::endl; for (UInt i = 0; i < el_to_subel1.getSize(); ++i) { std::cout << type_subsubfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel1(i).size(); ++j){ std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element << ", "; } std::cout << " " << std::endl; } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array<Element> & subel_to_el3 = mesh_facets.getSubelementToElement(type); const Array<Element> & subel_to_el2 = mesh_facets.getSubelementToElement(type_facet); const Array<Element> & subel_to_el1 = mesh_facets.getSubelementToElement(type_subfacet); std::cout << " " << std::endl; std::cout << "SubelementToElement3" << std::endl; for (UInt i = 0; i < subel_to_el3.getSize(); ++i) { std::cout << type << " " << i << " connected to "; for (UInt j = 0; j < 4; ++j){ std::cout << subel_to_el3(i, j).type << " " << subel_to_el3(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 3; ++j){ std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement1" << std::endl; for (UInt i = 0; i < subel_to_el1.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element << ", "; } std::cout << " " << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_3.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_3.cc index 383648403..604241e37 100644 --- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_3.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_3.cc @@ -1,116 +1,116 @@ /** * @file test_buildfacets_triangle_3.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Fri Sep 18 2015 * @date last modification: Sat Sep 19 2015 * * @brief Test to check the building of the facets. Mesh with triangles * * @section LICENSE * * Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory * (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <iostream> #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 2; const ElementType type = _triangle_3; Mesh mesh(spatial_dimension); mesh.read("triangle_3.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); const ElementType type_facet = mesh.getFacetType(type); const ElementType type_subfacet = mesh.getFacetType(type_facet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ const Array< std::vector<Element> > & el_to_subel2 = mesh_facets.getElementToSubelement(type_facet); const Array< std::vector<Element> > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subfacet); std::cout << "ElementToSubelement2" << std::endl; for (UInt i = 0; i < el_to_subel2.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement1" << std::endl; for (UInt i = 0; i < el_to_subel1.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel1(i).size(); ++j){ std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element << ", "; } std::cout << " " << std::endl; } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array<Element> & subel_to_el2 = mesh_facets.getSubelementToElement(type); const Array<Element> & subel_to_el1 = mesh_facets.getSubelementToElement(type_facet); std::cout << " " << std::endl; std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2.getSize(); ++i) { std::cout << type << " " << i << " connected to "; for (UInt j = 0; j < 3; ++j){ std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement1" << std::endl; for (UInt i = 0; i < subel_to_el1.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element << ", "; } std::cout << " " << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_6.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_6.cc index 5e0a5f12d..b28d0c719 100644 --- a/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_6.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_triangle_6.cc @@ -1,116 +1,116 @@ /** * @file test_buildfacets_triangle_6.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Fri Sep 18 2015 * @date last modification: Sat Sep 19 2015 * * @brief Test to check the building of the facets. Mesh with triangles * * @section LICENSE * * Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory * (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <iostream> #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 2; const ElementType type = _triangle_6; Mesh mesh(spatial_dimension); mesh.read("triangle_6.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); const ElementType type_facet = mesh.getFacetType(type); const ElementType type_subfacet = mesh.getFacetType(type_facet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ const Array< std::vector<Element> > & el_to_subel2 = mesh_facets.getElementToSubelement(type_facet); const Array< std::vector<Element> > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subfacet); std::cout << "ElementToSubelement2" << std::endl; for (UInt i = 0; i < el_to_subel2.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << el_to_subel2(i)[j].type << " " << el_to_subel2(i)[j].element << ", "; } std::cout << " " << std::endl; } std::cout << "ElementToSubelement1" << std::endl; for (UInt i = 0; i < el_to_subel1.getSize(); ++i) { std::cout << type_subfacet << " " << i << " connected to "; for (UInt j = 0; j < el_to_subel1(i).size(); ++j){ std::cout << el_to_subel1(i)[j].type << " " << el_to_subel1(i)[j].element << ", "; } std::cout << " " << std::endl; } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array<Element> & subel_to_el2 = mesh_facets.getSubelementToElement(type); const Array<Element> & subel_to_el1 = mesh_facets.getSubelementToElement(type_facet); std::cout << " " << std::endl; std::cout << "SubelementToElement2" << std::endl; for (UInt i = 0; i < subel_to_el2.getSize(); ++i) { std::cout << type << " " << i << " connected to "; for (UInt j = 0; j < 3; ++j){ std::cout << subel_to_el2(i, j).type << " " << subel_to_el2(i, j).element << ", "; } std::cout << " " << std::endl; } std::cout << "SubelementToElement1" << std::endl; for (UInt i = 0; i < subel_to_el1.getSize(); ++i) { std::cout << type_facet << " " << i << " connected to "; for (UInt j = 0; j < 2; ++j){ std::cout << subel_to_el1(i, j).type << " " << subel_to_el1(i, j).element << ", "; } std::cout << " " << std::endl; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/test_segment_nodetype/CMakeLists.txt b/test/test_mesh_utils/test_segment_nodetype/CMakeLists.txt index aea1a0789..01a5ad4b6 100644 --- a/test/test_mesh_utils/test_segment_nodetype/CMakeLists.txt +++ b/test/test_mesh_utils/test_segment_nodetype/CMakeLists.txt @@ -1,34 +1,34 @@ #=============================================================================== # @file CMakeLists.txt # # @author Marco Vocialta <marco.vocialta@epfl.ch> # # @date creation: Fri Sep 18 2015 # # @brief CMakeLists for segment nodetype tests # # @section LICENSE # # Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory # (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see <http://www.gnu.org/licenses/>. # #=============================================================================== -register_test(test_segment_nodetype - SOURCES test_segment_nodetype.cc - FILES_TO_COPY mesh.msh - PACKAGE parallel - ) +# register_test(test_segment_nodetype +# SOURCES test_segment_nodetype.cc +# FILES_TO_COPY mesh.msh +# PACKAGE parallel +# ) diff --git a/test/test_mesh_utils/test_segment_nodetype/test_segment_nodetype.cc b/test/test_mesh_utils/test_segment_nodetype/test_segment_nodetype.cc index 07cff2289..a3d7bb111 100644 --- a/test/test_mesh_utils/test_segment_nodetype/test_segment_nodetype.cc +++ b/test/test_mesh_utils/test_segment_nodetype/test_segment_nodetype.cc @@ -1,97 +1,97 @@ /** * @file test_segment_nodetype.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Sep 18 2015 * * @brief Test to verify that the node type is correctly associated to * the segments in parallel * * @section LICENSE * * Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory * (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "element_synchronizer.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { initialize(argc, argv); UInt spatial_dimension = 3; Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); // partition the mesh if (prank == 0) { mesh.read("mesh.msh"); } mesh.distribute(); // compute the node types for each segment - Mesh mesh_facets(mesh.initMeshFacets()); + Mesh & mesh_facets = mesh.initMeshFacets(); MeshUtils::buildSegmentToNodeType(mesh, mesh_facets); // verify that the number of segments per node type makes sense std::map<Int, UInt> nb_facets_per_nodetype; UInt nb_segments = 0; for (auto ghost_type : ghost_types) { const Array<Int> & segment_to_nodetype = mesh_facets.getData<Int>("segment_to_nodetype", _segment_2, ghost_type); // count the number of segments per node type for (auto & stn : segment_to_nodetype) { if (nb_facets_per_nodetype.find(stn) == nb_facets_per_nodetype.end()) nb_facets_per_nodetype[stn] = 1; else ++nb_facets_per_nodetype[stn]; } nb_segments += segment_to_nodetype.getSize(); } // checking the solution if (nb_segments != 24) AKANTU_DEBUG_ERROR("The number of segments is wrong"); if (prank == 0) { if (nb_facets_per_nodetype[-1] != 3 || nb_facets_per_nodetype[-2] != 9 || nb_facets_per_nodetype[-3] != 12) AKANTU_DEBUG_ERROR( "The segments of processor 0 have the wrong node type"); if (nb_facets_per_nodetype.size() > 3) AKANTU_DEBUG_ERROR("Processor 0 cannot have any slave segment"); } if (prank == psize - 1 && nb_facets_per_nodetype.find(-2) != nb_facets_per_nodetype.end()) AKANTU_DEBUG_ERROR("The last processor must not have any master facets"); finalize(); return 0; } diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit.cc b/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit.cc index 1e199d191..8641b1041 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit.cc +++ b/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit.cc @@ -1,313 +1,312 @@ /** * @file patch_test_explicit.cc * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Cyprien Wolff <cyprien.wolff@epfl.ch> * * @date creation: Sat Apr 16 2011 * @date last modification: Thu Oct 15 2015 * * @brief patch test for elastic material in solid mechanics model * * @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 "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ using namespace akantu; Real alpha[3][4] = {{0.01, 0.02, 0.03, 0.04}, {0.05, 0.06, 0.07, 0.08}, {0.09, 0.10, 0.11, 0.12}}; /* -------------------------------------------------------------------------- */ template <ElementType type, bool plane_strain> static Matrix<Real> prescribed_strain() { UInt spatial_dimension = ElementClass<type>::getSpatialDimension(); Matrix<Real> strain(spatial_dimension, spatial_dimension); for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < spatial_dimension; ++j) { strain(i, j) = alpha[i][j + 1]; } } return strain; } template <ElementType type, bool is_plane_strain> static Matrix<Real> prescribed_stress() { UInt spatial_dimension = ElementClass<type>::getSpatialDimension(); Matrix<Real> stress(spatial_dimension, spatial_dimension); // plane strain in 2d Matrix<Real> strain(spatial_dimension, spatial_dimension); Matrix<Real> pstrain; pstrain = prescribed_strain<type, is_plane_strain>(); Real nu = 0.3; Real E = 2.1e11; Real trace = 0; /// symetric part of the strain tensor for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) strain(i, j) = 0.5 * (pstrain(i, j) + pstrain(j, i)); for (UInt i = 0; i < spatial_dimension; ++i) trace += strain(i, i); if (spatial_dimension == 1) { stress(0, 0) = E * strain(0, 0); } else { if (is_plane_strain) { Real Ep = E / (1 + nu); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) { stress(i, j) = Ep * strain(i, j); if (i == j) stress(i, j) += Ep * (nu / (1 - 2 * nu)) * trace; } } else { Real Ep = E / (1 + nu); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) { stress(i, j) = Ep * strain(i, j); if (i == j) stress(i, j) += (nu * E) / (1 - (nu * nu)) * trace; } } } return stress; } /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { std::string input_file; if (PLANE_STRAIN) input_file = "material_check_stress_plane_strain.dat"; else input_file = "material_check_stress_plane_stress.dat"; initialize(input_file, argc, argv); debug::setDebugLevel(dblWarning); UInt dim = ElementClass<TYPE>::getSpatialDimension(); const ElementType element_type = TYPE; UInt damping_steps = 600000; UInt damping_interval = 50; Real damping_ratio = 0.99; UInt additional_steps = 20000; UInt max_steps = damping_steps + additional_steps; /// load mesh Mesh my_mesh(dim); std::stringstream filename; filename << TYPE << ".msh"; my_mesh.read(filename.str()); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initFull(); std::cout << my_model.getMaterial(0) << std::endl; Real time_step = my_model.getStableTimeStep() / 100.; my_model.setTimeStep(time_step); my_model.assembleMassLumped(); std::cout << "The number of time steps is: " << max_steps << " (" << time_step << "s)" << std::endl; // boundary conditions const Array<Real> & coordinates = my_mesh.getNodes(); Array<Real> & displacement = my_model.getDisplacement(); Array<bool> & boundary = my_model.getBlockedDOFs(); MeshUtils::buildFacets(my_mesh); my_mesh.createBoundaryGroupFromGeometry(); // Loop over (Sub)Boundar(ies) to block the nodes for (GroupManager::const_element_group_iterator it( my_mesh.element_group_begin()); it != my_mesh.element_group_end(); ++it) - for (ElementGroup::const_node_iterator nodes_it(it->second->node_begin()); - nodes_it != it->second->node_end(); ++nodes_it) + for (const auto & node : it->second->getNodeGroup()) for (UInt i = 0; i < dim; ++i) - boundary(*nodes_it, i) = true; + boundary(node, i) = true; // set the position of all nodes to the static solution for (UInt n = 0; n < nb_nodes; ++n) { for (UInt i = 0; i < dim; ++i) { displacement(n, i) = alpha[i][0]; for (UInt j = 0; j < dim; ++j) { displacement(n, i) += alpha[i][j + 1] * coordinates(n, j); } } } Array<Real> & velocity = my_model.getVelocity(); std::ofstream energy; std::stringstream energy_filename; energy_filename << "energy_" << TYPE << ".csv"; energy.open(energy_filename.str().c_str()); energy << "id,time,ekin" << std::endl; Real ekin_mean = 0.; //#define DEBUG_TEST #ifdef DEBUG_TEST my_model.solveStep(); my_model.addDumpField("strain"); my_model.addDumpField("stress"); my_model.addDumpField("external_force"); my_model.addDumpField("internal_force"); my_model.addDumpField("velocity"); my_model.addDumpField("acceleration"); my_model.addDumpField("displacement"); my_model.dump(); #endif /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ UInt s; for (s = 1; s <= max_steps; ++s) { if (s % 10000 == 0) std::cout << "passing step " << s << "/" << max_steps << " (" << s * time_step << "s)" << std::endl; // damp velocity in order to find equilibrium if ((s < damping_steps) && (s % damping_interval == 0)) { velocity *= damping_ratio; } if (s % 1000 == 0) { ekin_mean = ekin_mean / 1000.; std::cout << "Ekin mean = " << ekin_mean << std::endl; if (ekin_mean < 1e-10) break; ekin_mean = 0.; } my_model.solveStep(); akantu::Real ekin = my_model.getEnergy("kinetic"); ekin_mean += ekin; if (s % 1000 == 0) energy << s << "," << s * time_step << "," << ekin << std::endl; } energy.close(); UInt nb_quadrature_points = my_model.getFEEngine().getNbIntegrationPoints(TYPE); Array<Real> & stress_vect = const_cast<Array<Real> &>( my_model.getMaterial(0).getStress(element_type)); Array<Real> & strain_vect = const_cast<Array<Real> &>(my_model.getMaterial(0).getGradU(element_type)); Array<Real>::matrix_iterator stress_it = stress_vect.begin(dim, dim); Array<Real>::matrix_iterator strain_it = strain_vect.begin(dim, dim); Matrix<Real> presc_stress; presc_stress = prescribed_stress<TYPE, PLANE_STRAIN>(); Matrix<Real> presc_strain; presc_strain = prescribed_strain<TYPE, PLANE_STRAIN>(); UInt nb_element = my_mesh.getNbElement(TYPE); Real strain_tolerance = 1e-13; Real stress_tolerance = 1e-13; for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quadrature_points; ++q) { Matrix<Real> & stress = *stress_it; Matrix<Real> & strain = *strain_it; Matrix<Real> diff(dim, dim); diff = strain; diff -= presc_strain; Real strain_error = diff.norm<L_inf>() / strain.norm<L_inf>(); if (strain_error > strain_tolerance) { std::cerr << "strain error: " << strain_error << " > " << strain_tolerance << std::endl; std::cerr << "strain: " << strain << std::endl << "prescribed strain: " << presc_strain << std::endl; return EXIT_FAILURE; } else { std::cerr << "strain error: " << strain_error << " < " << strain_tolerance << std::endl; } diff = stress; diff -= presc_stress; Real stress_error = diff.norm<L_inf>() / stress.norm<L_inf>(); if (stress_error > stress_tolerance) { std::cerr << "stress error: " << stress_error << " > " << stress_tolerance << std::endl; std::cerr << "stress: " << stress << std::endl << "prescribed stress: " << presc_stress << std::endl; return EXIT_FAILURE; } else { std::cerr << "stress error: " << stress_error << " < " << stress_tolerance << std::endl; } ++stress_it; ++strain_it; } } for (UInt n = 0; n < nb_nodes; ++n) { for (UInt i = 0; i < dim; ++i) { Real disp = alpha[i][0]; for (UInt j = 0; j < dim; ++j) { disp += alpha[i][j + 1] * coordinates(n, j); } if (!(std::abs(displacement(n, i) - disp) < 1e-7)) { std::cerr << "displacement(" << n << ", " << i << ")=" << displacement(n, i) << " should be equal to " << disp << "(" << displacement(n, i) - disp << ")" << std::endl; return EXIT_FAILURE; } } } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit_anisotropic.cc b/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit_anisotropic.cc index fde87d4e0..e3d06c526 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit_anisotropic.cc +++ b/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit_anisotropic.cc @@ -1,314 +1,312 @@ /** * @file patch_test_explicit_anisotropic.cc * * @author Till Junge <till.junge@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Cyprien Wolff <cyprien.wolff@epfl.ch> * * @date creation: Sat Apr 16 2011 * @date last modification: Thu Oct 15 2015 * * @brief patch test for elastic material in solid mechanics model * * @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 "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ using namespace akantu; Real alpha[3][4] = {{0.01, 0.02, 0.03, 0.04}, {0.05, 0.06, 0.07, 0.08}, {0.09, 0.10, 0.11, 0.12}}; // Stiffness tensor, rotated by hand Real C[3][3][3][3] = { {{{112.93753505, 1.85842452538e-10, -4.47654358027e-10}, {1.85847317471e-10, 54.2334345331, -3.69840984824}, {-4.4764768395e-10, -3.69840984824, 56.848605217}}, {{1.85847781609e-10, 25.429294233, -3.69840984816}, {25.429294233, 3.31613847493e-10, -8.38797920011e-11}, {-3.69840984816, -8.38804581349e-11, -1.97875715813e-10}}, {{-4.47654358027e-10, -3.69840984816, 28.044464917}, {-3.69840984816, 2.09374961813e-10, 9.4857455224e-12}, {28.044464917, 9.48308098714e-12, -2.1367885239e-10}}}, {{{1.85847781609e-10, 25.429294233, -3.69840984816}, {25.429294233, 3.31613847493e-10, -8.38793479119e-11}, {-3.69840984816, -8.38795699565e-11, -1.97876381947e-10}}, {{54.2334345331, 3.31617400207e-10, 2.09372075233e-10}, {3.3161562385e-10, 115.552705733, -3.15093728886e-10}, {2.09372075233e-10, -3.15090176173e-10, 54.2334345333}}, {{-3.69840984824, -8.38795699565e-11, 9.48219280872e-12}, {-8.38795699565e-11, -3.1509195253e-10, 25.4292942335}, {9.48441325477e-12, 25.4292942335, 3.69840984851}}}, {{{-4.47653469848e-10, -3.69840984816, 28.044464917}, {-3.69840984816, 2.09374073634e-10, 9.48752187924e-12}, {28.044464917, 9.48552347779e-12, -2.1367885239e-10}}, {{-3.69840984824, -8.3884899027e-11, 9.48219280872e-12}, {-8.3884899027e-11, -3.150972816e-10, 25.4292942335}, {9.48041645188e-12, 25.4292942335, 3.69840984851}}, {{56.848605217, -1.97875493768e-10, -2.13681516925e-10}, {-1.97877270125e-10, 54.2334345333, 3.69840984851}, {-2.13683293282e-10, 3.69840984851, 112.93753505}}}}; /* -------------------------------------------------------------------------- */ template <ElementType type> static Matrix<Real> prescribed_grad_u() { UInt spatial_dimension = ElementClass<type>::getSpatialDimension(); Matrix<Real> grad_u(spatial_dimension, spatial_dimension); for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < spatial_dimension; ++j) { grad_u(i, j) = alpha[i][j + 1]; } } return grad_u; } template <ElementType type> static Matrix<Real> prescribed_stress() { UInt spatial_dimension = ElementClass<type>::getSpatialDimension(); Matrix<Real> stress(spatial_dimension, spatial_dimension); // plane strain in 2d Matrix<Real> strain(spatial_dimension, spatial_dimension); Matrix<Real> pstrain; pstrain = prescribed_grad_u<type>(); Real trace = 0; /// symetric part of the strain tensor for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) strain(i, j) = 0.5 * (pstrain(i, j) + pstrain(j, i)); for (UInt i = 0; i < spatial_dimension; ++i) trace += strain(i, i); for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < spatial_dimension; ++j) { stress(i, j) = 0; for (UInt k = 0; k < spatial_dimension; ++k) { for (UInt l = 0; l < spatial_dimension; ++l) { stress(i, j) += C[i][j][k][l] * strain(k, l); } } } } return stress; } #define TYPE _tetrahedron_4 /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize("material_anisotropic.dat", argc, argv); UInt dim = ElementClass<TYPE>::getSpatialDimension(); const ElementType element_type = TYPE; UInt damping_steps = 600000; UInt damping_interval = 50; Real damping_ratio = 0.99; UInt additional_steps = 20000; UInt max_steps = damping_steps + additional_steps; /// load mesh Mesh my_mesh(dim); std::stringstream filename; filename << TYPE << ".msh"; my_mesh.read(filename.str()); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel model(my_mesh); /// model initialization model.initFull(); std::cout << model.getMaterial(0) << std::endl; Real time_step = model.getStableTimeStep() / 5.; model.setTimeStep(time_step); std::cout << "The number of time steps is: " << max_steps << " (" << time_step << "s)" << std::endl; // boundary conditions const Array<Real> & coordinates = my_mesh.getNodes(); Array<Real> & displacement = model.getDisplacement(); Array<bool> & boundary = model.getBlockedDOFs(); MeshUtils::buildFacets(my_mesh); my_mesh.createBoundaryGroupFromGeometry(); // Loop over (Sub)Boundar(ies) // Loop over (Sub)Boundar(ies) for (GroupManager::const_element_group_iterator it( my_mesh.element_group_begin()); it != my_mesh.element_group_end(); ++it) { - for (ElementGroup::const_node_iterator nodes_it(it->second->node_begin()); - nodes_it != it->second->node_end(); ++nodes_it) { - UInt n(*nodes_it); - std::cout << "Node " << *nodes_it << std::endl; + for (const auto & n : it->second->getNodeGroup()) { + std::cout << "Node " << n << std::endl; for (UInt i = 0; i < dim; ++i) { displacement(n, i) = alpha[i][0]; for (UInt j = 0; j < dim; ++j) { displacement(n, i) += alpha[i][j + 1] * coordinates(n, j); } boundary(n, i) = true; } } } // Actually, loop over all nodes, since I wanna test a static solution for (UInt n = 0; n < nb_nodes; ++n) { for (UInt i = 0; i < dim; ++i) { displacement(n, i) = alpha[i][0]; for (UInt j = 0; j < dim; ++j) { displacement(n, i) += alpha[i][j + 1] * coordinates(n, j); } } } Array<Real> & velocity = model.getVelocity(); std::ofstream energy; std::stringstream energy_filename; energy_filename << "energy_" << TYPE << ".csv"; energy.open(energy_filename.str().c_str()); energy << "id,time,ekin" << std::endl; Real ekin_mean = 0.; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ UInt s; for (s = 1; s <= max_steps; ++s) { if (s % 10000 == 0) std::cout << "passing step " << s << "/" << max_steps << " (" << s * time_step << "s)" << std::endl; // damp velocity in order to find equilibrium if ((s < damping_steps) && (s % damping_interval == 0)) { velocity *= damping_ratio; } if (s % 1000 == 0) { ekin_mean = ekin_mean / 1000.; std::cout << "Ekin mean = " << ekin_mean << std::endl; if (ekin_mean < 1e-10) break; ekin_mean = 0.; } model.solveStep(); Real ekin = model.getEnergy("kinetic"); ekin_mean += ekin; if (s % 1000 == 0) energy << s << "," << s * time_step << "," << ekin << std::endl; } energy.close(); UInt nb_quadrature_points = model.getFEEngine().getNbIntegrationPoints(TYPE); Array<Real> & stress_vect = const_cast<Array<Real> &>(model.getMaterial(0).getStress(element_type)); Array<Real> & gradu_vect = const_cast<Array<Real> &>(model.getMaterial(0).getGradU(element_type)); Array<Real>::iterator<Matrix<Real>> stress_it = stress_vect.begin(dim, dim); Array<Real>::iterator<Matrix<Real>> gradu_it = gradu_vect.begin(dim, dim); Matrix<Real> presc_stress; presc_stress = prescribed_stress<TYPE>(); Matrix<Real> presc_gradu; presc_gradu = prescribed_grad_u<TYPE>(); UInt nb_element = my_mesh.getNbElement(TYPE); Real gradu_tolerance = 1e-9; Real stress_tolerance = 1e-2; if (s > max_steps) { stress_tolerance = 1e-4; gradu_tolerance = 1e-7; } for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quadrature_points; ++q) { Matrix<Real> & stress = *stress_it; Matrix<Real> & gradu = *gradu_it; for (UInt i = 0; i < dim; ++i) { for (UInt j = 0; j < dim; ++j) { if (!(std::abs(gradu(i, j) - presc_gradu(i, j)) < gradu_tolerance)) { std::cerr << "gradu[" << i << "," << j << "] = " << gradu(i, j) << " but should be = " << presc_gradu(i, j) << " (-" << std::abs(gradu(i, j) - presc_gradu(i, j)) << ") [el : " << el << " - q : " << q << "]" << std::endl; std::cerr << gradu << presc_gradu << std::endl; return EXIT_FAILURE; } if (!(std::abs(stress(i, j) - presc_stress(i, j)) < stress_tolerance)) { std::cerr << "stress[" << i << "," << j << "] = " << stress(i, j) << " but should be = " << presc_stress(i, j) << " (-" << std::abs(stress(i, j) - presc_stress(i, j)) << ") [el : " << el << " - q : " << q << "]" << std::endl; std::cerr << stress << presc_stress << std::endl; return EXIT_FAILURE; } } } ++stress_it; ++gradu_it; } } for (UInt n = 0; n < nb_nodes; ++n) { for (UInt i = 0; i < dim; ++i) { Real disp = alpha[i][0]; for (UInt j = 0; j < dim; ++j) { disp += alpha[i][j + 1] * coordinates(n, j); } if (!(std::abs(displacement(n, i) - disp) < 1e-7)) { std::cerr << "displacement(" << n << ", " << i << ")=" << displacement(n, i) << " should be equal to " << disp << "(" << displacement(n, i) - disp << ")" << std::endl; return EXIT_FAILURE; } } } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/implicit/patch_test_implicit.cc b/test/test_model/test_solid_mechanics_model/patch_tests/implicit/patch_test_implicit.cc index 173cf03b1..499f183db 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/implicit/patch_test_implicit.cc +++ b/test/test_model/test_solid_mechanics_model/patch_tests/implicit/patch_test_implicit.cc @@ -1,249 +1,247 @@ /** * @file patch_test_implicit.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sat Apr 16 2011 * @date last modification: Thu Oct 15 2015 * * @brief patch test for elastic material in solid mechanics model * * @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 "non_linear_solver.hh" #include "solid_mechanics_model.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; Real alpha[3][4] = {{0.01, 0.02, 0.03, 0.04}, {0.05, 0.06, 0.07, 0.08}, {0.09, 0.10, 0.11, 0.12}}; /* -------------------------------------------------------------------------- */ template <ElementType type, bool is_plane_strain> static Matrix<Real> prescribed_strain() { UInt spatial_dimension = ElementClass<type>::getSpatialDimension(); Matrix<Real> strain(spatial_dimension, spatial_dimension); for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < spatial_dimension; ++j) { strain(i, j) = alpha[i][j + 1]; } } return strain; } template <ElementType type, bool is_plane_strain> static Matrix<Real> prescribed_stress() { UInt spatial_dimension = ElementClass<type>::getSpatialDimension(); Matrix<Real> stress(spatial_dimension, spatial_dimension); // plane strain in 2d Matrix<Real> strain(spatial_dimension, spatial_dimension); Matrix<Real> pstrain; pstrain = prescribed_strain<type, is_plane_strain>(); Real nu = 0.3; Real E = 2.1e11; Real trace = 0; /// symetric part of the strain tensor for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) strain(i, j) = 0.5 * (pstrain(i, j) + pstrain(j, i)); for (UInt i = 0; i < spatial_dimension; ++i) trace += strain(i, i); Real lambda = nu * E / ((1 + nu) * (1 - 2 * nu)); Real mu = E / (2 * (1 + nu)); if (!is_plane_strain) { std::cout << "toto" << std::endl; lambda = nu * E / (1 - nu * nu); } if (spatial_dimension == 1) { stress(0, 0) = E * strain(0, 0); } else { for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) { stress(i, j) = (i == j) * lambda * trace + 2 * mu * strain(i, j); } } return stress; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { std::string input_file; if (PLANE_STRAIN) input_file = "material_check_stress_plane_strain.dat"; else input_file = "material_check_stress_plane_stress.dat"; initialize(input_file, argc, argv); UInt dim = ElementClass<TYPE>::getSpatialDimension(); const ElementType element_type = TYPE; /// load mesh Mesh mesh(dim); std::stringstream filename; filename << TYPE << ".msh"; mesh.read(filename.str()); UInt nb_nodes = mesh.getNbNodes(); /// declaration of model SolidMechanicsModel model(mesh); /// model initialization model.initFull(_analysis_method = _static); const Array<Real> & coordinates = mesh.getNodes(); Array<Real> & displacement = model.getDisplacement(); Array<bool> & boundary = model.getBlockedDOFs(); MeshUtils::buildFacets(mesh); mesh.createBoundaryGroupFromGeometry(); // Loop over (Sub)Boundar(ies) for (GroupManager::const_element_group_iterator it( mesh.element_group_begin()); it != mesh.element_group_end(); ++it) { - for (ElementGroup::const_node_iterator nodes_it(it->second->node_begin()); - nodes_it != it->second->node_end(); ++nodes_it) { - UInt n(*nodes_it); - std::cout << "Node " << *nodes_it << std::endl; + for (const auto & n : it->second->getNodeGroup()) { + std::cout << "Node " << n << std::endl; for (UInt i = 0; i < dim; ++i) { displacement(n, i) = alpha[i][0]; for (UInt j = 0; j < dim; ++j) { displacement(n, i) += alpha[i][j + 1] * coordinates(n, j); } boundary(n, i) = true; } } } /* ------------------------------------------------------------------------ */ /* Static solve */ /* ------------------------------------------------------------------------ */ auto & solver = model.getNonLinearSolver(); solver.set("max_iterations", 2); solver.set("threshold", 2e-4); solver.set("convergence_type", _scc_residual); model.solveStep(); model.getDOFManager().getMatrix("K").saveMatrix("clown_matrix.mtx"); /* ------------------------------------------------------------------------ */ /* Checks */ /* ------------------------------------------------------------------------ */ UInt nb_quadrature_points = model.getFEEngine().getNbIntegrationPoints(element_type); Array<Real> & stress_vect = const_cast<Array<Real> &>(model.getMaterial(0).getStress(element_type)); Array<Real> & strain_vect = const_cast<Array<Real> &>(model.getMaterial(0).getGradU(element_type)); Array<Real>::matrix_iterator stress_it = stress_vect.begin(dim, dim); Array<Real>::matrix_iterator strain_it = strain_vect.begin(dim, dim); Matrix<Real> presc_stress; presc_stress = prescribed_stress<TYPE, PLANE_STRAIN>(); Matrix<Real> presc_strain; presc_strain = prescribed_strain<TYPE, PLANE_STRAIN>(); UInt nb_element = mesh.getNbElement(TYPE); Real strain_tolerance = 1e-13; Real stress_tolerance = 1e-13; for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quadrature_points; ++q) { Matrix<Real> & stress = *stress_it; Matrix<Real> & strain = *strain_it; Matrix<Real> diff(dim, dim); diff = strain; diff -= presc_strain; Real strain_error = diff.norm<L_inf>() / strain.norm<L_inf>(); if (strain_error > strain_tolerance) { std::cerr << "strain error: " << strain_error << " > " << strain_tolerance << std::endl; std::cerr << "strain: " << strain << std::endl << "prescribed strain: " << presc_strain << std::endl; return EXIT_FAILURE; } else { std::cerr << "strain error: " << strain_error << " < " << strain_tolerance << std::endl; } diff = stress; diff -= presc_stress; Real stress_error = diff.norm<L_inf>() / stress.norm<L_inf>(); if (stress_error > stress_tolerance) { std::cerr << "stress error: " << stress_error << " > " << stress_tolerance << std::endl; std::cerr << "stress: " << stress << std::endl << "prescribed stress: " << presc_stress << std::endl; return EXIT_FAILURE; } else { std::cerr << "stress error: " << stress_error << " < " << stress_tolerance << std::endl; } ++stress_it; ++strain_it; } } for (UInt n = 0; n < nb_nodes; ++n) { for (UInt i = 0; i < dim; ++i) { Real disp = alpha[i][0]; for (UInt j = 0; j < dim; ++j) { disp += alpha[i][j + 1] * coordinates(n, j); } if (!(std::abs(displacement(n, i) - disp) < 2e-15)) { std::cerr << "displacement(" << n << ", " << i << ")=" << displacement(n, i) << " should be equal to " << disp << std::endl; return EXIT_FAILURE; } } } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_1d_element/test_cohesive_1d_element.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_1d_element/test_cohesive_1d_element.cc index 345c7de54..f8755cf90 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_1d_element/test_cohesive_1d_element.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_1d_element/test_cohesive_1d_element.cc @@ -1,122 +1,121 @@ /** * @file test_cohesive_1d_element.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Jun 14 2013 * @date last modification: Sun Oct 19 2014 * * @brief Test for 1D cohesive elements * * @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 "solid_mechanics_model_cohesive.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); const UInt max_steps = 2000; const Real strain_rate = 4; UInt spatial_dimension = 1; Mesh mesh(spatial_dimension, "mesh"); mesh.read("bar.msh"); SolidMechanicsModelCohesive model(mesh); model.initFull( SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); Real time_step = model.getStableTimeStep() * 0.01; model.setTimeStep(time_step); std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); - mesh.computeBoundingBox(); Real posx_max = mesh.getUpperBounds()(0); Real posx_min = mesh.getLowerBounds()(0); /// initial conditions Array<Real> & velocity = model.getVelocity(); const Array<Real> & position = mesh.getNodes(); UInt nb_nodes = mesh.getNbNodes(); for (UInt n = 0; n < nb_nodes; ++n) velocity(n) = strain_rate * (position(n) - (posx_max + posx_min) / 2.); /// boundary conditions Array<bool> & boundary = model.getBlockedDOFs(); Array<Real> & displacement = model.getDisplacement(); Real disp_increment = strain_rate * (posx_max - posx_min) / 2. * time_step; for (UInt node = 0; node < mesh.getNbNodes(); ++node) { if (Math::are_float_equal(position(node), posx_min)) { // left side boundary(node) = true; } if (Math::are_float_equal(position(node), posx_max)) { // right side boundary(node) = true; } } model.synchronizeBoundaries(); model.assembleInternalForces(); for (UInt s = 1; s <= max_steps; ++s) { model.checkCohesiveStress(); model.solveStep(); UInt nb_cohesive_elements = mesh.getNbElement(_cohesive_1d_2); if (s % 10 == 0) { std::cout << "passing step " << s << "/" << max_steps << ", number of cohesive elemets:" << nb_cohesive_elements << std::endl; } /// update external work and boundary conditions for (UInt n = 0; n < mesh.getNbNodes(); ++n) { if (Math::are_float_equal(position(n), posx_min)) // left side displacement(n) -= disp_increment; if (Math::are_float_equal(position(n), posx_max)) // right side displacement(n) += disp_increment; } } Real Ed = model.getEnergy("dissipated"); Real Edt = 100 * 3; std::cout << Ed << std::endl; if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; finalize(); return EXIT_FAILURE; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_interpolate_stress.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_interpolate_stress.cc index 9fab6b8ca..952d1bb85 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_interpolate_stress.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_interpolate_stress.cc @@ -1,181 +1,181 @@ /** * @file test_interpolate_stress.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Thu Jun 07 2012 * @date last modification: Thu Oct 15 2015 * * @brief Test for the stress interpolation function * * @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 <fstream> #include <iostream> #include <limits> /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; Real function(Real x, Real y, Real z) { return 100. + 2. * x + 3. * y + 4 * z; } int main(int argc, char * argv[]) { initialize("../material.dat", argc, argv); debug::setDebugLevel(dblWarning); const UInt spatial_dimension = 3; const ElementType type = _tetrahedron_10; Mesh mesh(spatial_dimension); mesh.read("interpolation.msh"); const ElementType type_facet = mesh.getFacetType(type); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); + Mesh & mesh_facets = mesh.initMeshFacets("mesh_facets"); MeshUtils::buildAllFacets(mesh, mesh_facets); SolidMechanicsModel model(mesh); /// model initialization model.initFull(); Array<Real> & position = mesh.getNodes(); UInt nb_facet = mesh_facets.getNbElement(type_facet); UInt nb_element = mesh.getNbElement(type); /// compute quadrature points positions on facets typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange> MyFEEngineType; model.registerFEEngineObject<MyFEEngineType>("FacetsFEEngine", mesh_facets, spatial_dimension - 1); model.getFEEngine("FacetsFEEngine").initShapeFunctions(); UInt nb_quad_per_facet = model.getFEEngine("FacetsFEEngine").getNbIntegrationPoints(type_facet); UInt nb_tot_quad = nb_quad_per_facet * nb_facet; Array<Real> quad_facets(nb_tot_quad, spatial_dimension); model.getFEEngine("FacetsFEEngine") .interpolateOnIntegrationPoints(position, quad_facets, spatial_dimension, type_facet); Array<Element> & facet_to_element = mesh_facets.getSubelementToElement(type); UInt nb_facet_per_elem = facet_to_element.getNbComponent(); ElementTypeMapArray<Real> element_quad_facet; element_quad_facet.alloc(nb_element * nb_facet_per_elem * nb_quad_per_facet, spatial_dimension, type); ElementTypeMapArray<Real> interpolated_stress("interpolated_stress", ""); interpolated_stress.initialize( mesh, _nb_component = spatial_dimension * spatial_dimension, _spatial_dimension = spatial_dimension); Array<Real> & interp_stress = interpolated_stress(type); interp_stress.resize(nb_element * nb_facet_per_elem * nb_quad_per_facet); Array<Real> & el_q_facet = element_quad_facet(type); for (UInt el = 0; el < nb_element; ++el) { for (UInt f = 0; f < nb_facet_per_elem; ++f) { UInt global_facet = facet_to_element(el, f).element; for (UInt q = 0; q < nb_quad_per_facet; ++q) { for (UInt s = 0; s < spatial_dimension; ++s) { el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, s) = quad_facets(global_facet * nb_quad_per_facet + q, s); } } } } /// compute quadrature points position of the elements UInt nb_quad_per_element = model.getFEEngine().getNbIntegrationPoints(type); UInt nb_tot_quad_el = nb_quad_per_element * nb_element; Array<Real> quad_elements(nb_tot_quad_el, spatial_dimension); model.getFEEngine().interpolateOnIntegrationPoints(position, quad_elements, spatial_dimension, type); /// assign some values to stresses Array<Real> & stress = const_cast<Array<Real> &>(model.getMaterial(0).getStress(type)); for (UInt q = 0; q < nb_tot_quad_el; ++q) { for (UInt s = 0; s < spatial_dimension * spatial_dimension; ++s) { stress(q, s) = s * function(quad_elements(q, 0), quad_elements(q, 1), quad_elements(q, 2)); } } /// interpolate stresses on facets' quadrature points model.getMaterial(0).initElementalFieldInterpolation(element_quad_facet); model.getMaterial(0).interpolateStress(interpolated_stress); Real tolerance = 1.e-10; /// check results for (UInt el = 0; el < nb_element; ++el) { for (UInt f = 0; f < nb_facet_per_elem; ++f) { for (UInt q = 0; q < nb_quad_per_facet; ++q) { for (UInt s = 0; s < spatial_dimension * spatial_dimension; ++s) { Real x = el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, 0); Real y = el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, 1); Real z = el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, 2); Real theoretical = s * function(x, y, z); Real numerical = interp_stress(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, s); if (std::abs(theoretical - numerical) > tolerance) { std::cout << "Theoretical and numerical values aren't coincident!" << std::endl; return EXIT_FAILURE; } } } } } std::cout << "OK: Stress interpolation test passed." << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc index 325e3881e..9eeeaa40c 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_thermal.cc @@ -1,101 +1,100 @@ /** * @file test_material_thermal.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Wed Aug 04 2010 * @date last modification: Sun Oct 19 2014 * * @brief test of the class akantu::MaterialThermal * * @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 <iostream> /* -------------------------------------------------------------------------- */ #include "non_linear_solver.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { debug::setDebugLevel(dblWarning); initialize("material_thermal.dat", argc, argv); Math::setTolerance(1.e-13); Mesh mesh(2); mesh.read("square.msh"); SolidMechanicsModel model(mesh); model.initFull(_analysis_method = _static); - mesh.computeBoundingBox(); const Vector<Real> & min = mesh.getLowerBounds(); const Vector<Real> & max = mesh.getUpperBounds(); Array<Real> & pos = mesh.getNodes(); Array<bool> & boundary = model.getBlockedDOFs(); Array<Real> & disp = model.getDisplacement(); for (UInt i = 0; i < mesh.getNbNodes(); ++i) { if (Math::are_float_equal(pos(i, 0), min(0))) { boundary(i, 0) = true; } if (Math::are_float_equal(pos(i, 1), min(1))) { boundary(i, 1) = true; } } model.setBaseName("test_material_thermal"); model.addDumpField("displacement"); model.addDumpField("strain"); model.addDumpField("stress"); model.addDumpField("delta_T"); auto & solver = model.getNonLinearSolver("static"); solver.set("max_iterations", 2); solver.set("threshold", 1e-10); model.solveStep(); for (UInt i = 0; i < mesh.getNbNodes(); ++i) { if (Math::are_float_equal(pos(i, 0), max(0)) && Math::are_float_equal(pos(i, 1), max(1))) { if (!Math::are_float_equal(disp(i, 0), 1.0) || !Math::are_float_equal(disp(i, 1), 1.0)) { AKANTU_DEBUG_ERROR("Test not passed"); return EXIT_FAILURE; } } } model.dump(); finalize(); std::cout << "Test passed" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_multi_material_elastic.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_multi_material_elastic.cc index a354718ad..b087bfb75 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_multi_material_elastic.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_multi_material_elastic.cc @@ -1,92 +1,92 @@ #include <solid_mechanics_model.hh> #include "non_linear_solver.hh" using namespace akantu; int main(int argc, char *argv[]) { initialize("test_multi_material_elastic.dat", argc, argv); UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); mesh.read("test_multi_material_elastic.msh"); - mesh.createGroupsFromMeshData<std::string>("physical_names"); SolidMechanicsModel model(mesh); MeshDataMaterialSelector<std::string> mat_sel("physical_names", model); model.setMaterialSelector(mat_sel); model.initFull(_analysis_method = _static); model.applyBC(BC::Dirichlet::FlagOnly(_y), "ground"); model.applyBC(BC::Dirichlet::FlagOnly(_x), "corner"); Vector<Real> trac(spatial_dimension, 0.); trac(_y) = 1.; model.applyBC(BC::Neumann::FromTraction(trac), "air"); - model.addDumpField("force"); - model.addDumpField("residual"); + model.addDumpField("external_force"); + model.addDumpField("internal_force"); model.addDumpField("blocked_dofs"); model.addDumpField("displacement"); model.addDumpField("stress"); model.addDumpField("grad_u"); //model.dump(); auto & solver = model.getNonLinearSolver("static"); solver.set("max_iterations", 1); solver.set("threshold", 1e-8); solver.set("convergence_type", _scc_residual); + model.solveStep(); //model.dump(); std::map<std::string, Matrix<Real>> ref_strain; ref_strain["strong"] = Matrix<Real>(spatial_dimension, spatial_dimension, 0.); ref_strain["strong"](_y, _y) = .5; ref_strain["weak"] = Matrix<Real>(spatial_dimension, spatial_dimension, 0.); ref_strain["weak"](_y, _y) = 1; Matrix<Real> ref_stress(spatial_dimension, spatial_dimension, 0.); ref_stress(_y, _y) = 1.; std::vector<std::string> mats = {"strong", "weak"}; typedef Array<Real>::const_matrix_iterator mat_it; auto check = [](mat_it it, mat_it end, const Matrix<Real> & ref) -> bool { for(;it != end; ++it) { Real dist = (*it - ref).norm<L_2>(); //std::cout << *it << " " << dist << " " << (dist < 1e-10 ? "OK" : "Not OK") << std::endl; if (dist > 1e-10) return false; } return true; }; auto tit = mesh.firstType(spatial_dimension); auto tend = mesh.lastType(spatial_dimension); for (; tit != tend; ++tit) { auto & type = *tit; for(auto mat_id : mats) { auto & stress = model.getMaterial(mat_id).getStress(type); auto & grad_u = model.getMaterial(mat_id).getGradU(type); auto sit = stress.begin(spatial_dimension, spatial_dimension); auto send = stress.end(spatial_dimension, spatial_dimension); auto git = grad_u.begin(spatial_dimension, spatial_dimension); auto gend = grad_u.end(spatial_dimension, spatial_dimension); if(!check(sit, send, ref_stress)) AKANTU_DEBUG_ERROR("The stresses are not correct"); if(!check(git, gend, ref_strain[mat_id])) AKANTU_DEBUG_ERROR("The grad_u are not correct"); } } finalize(); return 0; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_eigenstrain.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_eigenstrain.cc index 5b363ef62..2b1fafe0d 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_eigenstrain.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_eigenstrain.cc @@ -1,203 +1,201 @@ /** * @file test_solid_mechanics_model_material_eigenstrain.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sat Apr 16 2011 * @date last modification: Wed Aug 12 2015 * * @brief test the internal field prestrain * * @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 "solid_mechanics_model.hh" #include "non_linear_solver.hh" using namespace akantu; Real alpha [3][4] = { { 0.01, 0.02, 0.03, 0.04 }, { 0.05, 0.06, 0.07, 0.08 }, { 0.09, 0.10, 0.11, 0.12 } }; /* -------------------------------------------------------------------------- */ template<ElementType type> static Matrix<Real> prescribed_strain() { UInt spatial_dimension = ElementClass<type>::getSpatialDimension(); Matrix<Real> strain(spatial_dimension, spatial_dimension); for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < spatial_dimension; ++j) { strain(i, j) = alpha[i][j + 1]; } } return strain; } template<ElementType type> static Matrix<Real> prescribed_stress(Matrix<Real> prescribed_eigengradu) { UInt spatial_dimension = ElementClass<type>::getSpatialDimension(); Matrix<Real> stress(spatial_dimension, spatial_dimension); //plane strain in 2d Matrix<Real> strain(spatial_dimension, spatial_dimension); Matrix<Real> pstrain; pstrain = prescribed_strain<type>(); Real nu = 0.3; Real E = 2.1e11; Real trace = 0; /// symetric part of the strain tensor for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) strain(i,j) = 0.5 * (pstrain(i, j) + pstrain(j, i)); // elastic strain is equal to elastic strain minus the eigenstrain strain -= prescribed_eigengradu; for (UInt i = 0; i < spatial_dimension; ++i) trace += strain(i,i); Real lambda = nu * E / ((1 + nu) * (1 - 2*nu)); Real mu = E / (2 * (1 + nu)); if(spatial_dimension == 1) { stress(0, 0) = E * strain(0, 0); } else { for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) { stress(i, j) = (i == j)*lambda*trace + 2*mu*strain(i, j); } } return stress; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { initialize("material_elastic_plane_strain.dat", argc, argv); UInt dim = 3; const ElementType element_type = _tetrahedron_4; Matrix<Real> prescribed_eigengradu(dim, dim); prescribed_eigengradu.set(0.1); /// load mesh Mesh mesh(dim); mesh.read("cube_3d_tet_4.msh"); /// declaration of model SolidMechanicsModel model(mesh); /// model initialization model.initFull(_analysis_method = _static); //model.getNewSolver("static", _tsst_static, _nls_newton_raphson_modified); auto & solver = model.getNonLinearSolver("static"); solver.set("threshold", 2e-4); solver.set("max_iterations", 2); solver.set("convergence_type", _scc_residual); const Array<Real> & coordinates = mesh.getNodes(); Array<Real> & displacement = model.getDisplacement(); Array<bool> & boundary = model.getBlockedDOFs(); MeshUtils::buildFacets(mesh); mesh.createBoundaryGroupFromGeometry(); // Loop over (Sub)Boundar(ies) for(GroupManager::const_element_group_iterator it(mesh.element_group_begin()); it != mesh.element_group_end(); ++it) { - for(ElementGroup::const_node_iterator nodes_it(it->second->node_begin()); - nodes_it!= it->second->node_end(); ++nodes_it) { - UInt n(*nodes_it); - std::cout << "Node " << *nodes_it << std::endl; + for(const auto & n : it->second->getNodeGroup()) { + std::cout << "Node " << n << std::endl; for (UInt i = 0; i < dim; ++i) { displacement(n, i) = alpha[i][0]; for (UInt j = 0; j < dim; ++j) { displacement(n, i) += alpha[i][j + 1] * coordinates(n, j); } boundary(n, i) = true; } } } /* ------------------------------------------------------------------------ */ /* Apply eigenstrain in each element */ /* ------------------------------------------------------------------------ */ Array<Real> & eigengradu_vect = model.getMaterial(0).getInternal<Real>("eigen_grad_u")(element_type); auto eigengradu_it = eigengradu_vect.begin(dim, dim); auto eigengradu_end = eigengradu_vect.end(dim, dim); for (; eigengradu_it != eigengradu_end; ++eigengradu_it) { *eigengradu_it = prescribed_eigengradu; } /* ------------------------------------------------------------------------ */ /* Static solve */ /* ------------------------------------------------------------------------ */ model.solveStep(); std::cout << "Converged in " << Int(solver.get("nb_iterations")) << " (" << Real(solver.get("error")) << ")" << std::endl; /* ------------------------------------------------------------------------ */ /* Checks */ /* ------------------------------------------------------------------------ */ const Array<Real> & stress_vect = model.getMaterial(0).getStress(element_type); auto stress_it = stress_vect.begin(dim, dim); auto stress_end = stress_vect.end(dim, dim); Matrix<Real> presc_stress; presc_stress = prescribed_stress<element_type>(prescribed_eigengradu); Real stress_tolerance = 1e-13; for (; stress_it != stress_end; ++stress_it) { const auto & stress = *stress_it; Matrix<Real> diff(dim, dim); diff = stress; diff -= presc_stress; Real stress_error = diff.norm<L_inf>() / stress.norm<L_inf>(); if(stress_error > stress_tolerance) { std::cerr << "stress error: " << stress_error << " > " << stress_tolerance << std::endl; std::cerr << "stress: " << stress << std::endl << "prescribed stress: " << presc_stress << std::endl; return EXIT_FAILURE; } // else { // std::cerr << "stress error: " << stress_error // << " < " << stress_tolerance << std::endl; // } } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_synchronizer/test_data_distribution.cc b/test/test_synchronizer/test_data_distribution.cc index d3c8db9c9..2efd1498e 100644 --- a/test/test_synchronizer/test_data_distribution.cc +++ b/test/test_synchronizer/test_data_distribution.cc @@ -1,197 +1,197 @@ /** * @file test_data_distribution.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Sep 05 2014 * @date last modification: Sun Oct 19 2014 * * @brief Test the mesh distribution on creation of a distributed synchonizer * * @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 "element_group.hh" #include "element_synchronizer.hh" #include "mesh_partition_mesh_data.hh" #include "aka_random_generator.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { initialize(argc, argv); const UInt spatial_dimension = 3; Mesh mesh_group_after(spatial_dimension, "after"); Mesh mesh_group_before(spatial_dimension, "before"); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); if (prank == 0) { mesh_group_before.read("data_split.msh"); mesh_group_after.read("data_split.msh"); mesh_group_before.registerData<UInt>("global_id"); mesh_group_after.registerData<UInt>("global_id"); for (Mesh::type_iterator tit = mesh_group_after.firstType(_all_dimensions); tit != mesh_group_after.lastType(_all_dimensions); ++tit) { Array<UInt> & gidb = - *(mesh_group_before.getDataPointer<UInt>("global_id", *tit)); + mesh_group_before.getDataPointer<UInt>("global_id", *tit); Array<UInt> & gida = - *(mesh_group_after.getDataPointer<UInt>("global_id", *tit)); + mesh_group_after.getDataPointer<UInt>("global_id", *tit); Array<UInt>::scalar_iterator ait = gida.begin(); Array<UInt>::scalar_iterator bit = gidb.begin(); Array<UInt>::scalar_iterator end = gida.end(); for (UInt i = 0; ait != end; ++ait, ++i, ++bit) { *bit = i; *ait = i; } } } RandomGenerator<UInt>::seed(1); mesh_group_before.distribute(); RandomGenerator<UInt>::seed(1); mesh_group_after.distribute(); if (prank == 0) std::cout << mesh_group_after; GroupManager::element_group_iterator grp_ait = mesh_group_after.element_group_begin(); GroupManager::element_group_iterator grp_end = mesh_group_after.element_group_end(); for (; grp_ait != grp_end; ++grp_ait) { std::string grp = grp_ait->first; const ElementGroup & bgrp = mesh_group_before.getElementGroup(grp); const ElementGroup & agrp = *grp_ait->second; for (ghost_type_t::iterator git = ghost_type_t::begin(); git != ghost_type_t::end(); ++git) { GhostType ghost_type = *git; for (Mesh::type_iterator tit = bgrp.firstType(_all_dimensions, ghost_type); tit != bgrp.lastType(_all_dimensions, ghost_type); ++tit) { - Array<UInt> & gidb = *(mesh_group_before.getDataPointer<UInt>( - "global_id", *tit, ghost_type)); - Array<UInt> & gida = *(mesh_group_after.getDataPointer<UInt>( - "global_id", *tit, ghost_type)); + Array<UInt> & gidb = mesh_group_before.getDataPointer<UInt>( + "global_id", *tit, ghost_type); + Array<UInt> & gida = mesh_group_after.getDataPointer<UInt>( + "global_id", *tit, ghost_type); Array<UInt> bgelem(bgrp.getElements(*tit, ghost_type)); Array<UInt> agelem(agrp.getElements(*tit, ghost_type)); Array<UInt>::scalar_iterator ait = agelem.begin(); Array<UInt>::scalar_iterator bit = bgelem.begin(); Array<UInt>::scalar_iterator end = agelem.end(); for (; ait != end; ++ait, ++bit) { *bit = gidb(*bit); *ait = gida(*ait); } std::sort(bgelem.begin(), bgelem.end()); std::sort(agelem.begin(), agelem.end()); if (!std::equal(bgelem.begin(), bgelem.end(), agelem.begin())) { std::cerr << "The filters array for the group " << grp << " and for the element type " << *tit << ", " << ghost_type << " do not match" << std::endl; debug::setDebugLevel(dblTest); std::cerr << bgelem << std::endl; std::cerr << agelem << std::endl; debug::debugger.exit(EXIT_FAILURE); } } } } GroupManager::node_group_iterator ngrp_ait = mesh_group_after.node_group_begin(); GroupManager::node_group_iterator ngrp_end = mesh_group_after.node_group_end(); for (; ngrp_ait != ngrp_end; ++ngrp_ait) { std::string grp = ngrp_ait->first; const NodeGroup & bgrp = mesh_group_before.getNodeGroup(grp); const NodeGroup & agrp = *ngrp_ait->second; const Array<UInt> & gidb = mesh_group_before.getGlobalNodesIds(); const Array<UInt> & gida = mesh_group_after.getGlobalNodesIds(); Array<UInt> bgnode(0, 1); Array<UInt> agnode(0, 1); Array<UInt>::const_scalar_iterator ait = agrp.begin(); Array<UInt>::const_scalar_iterator bit = bgrp.begin(); Array<UInt>::const_scalar_iterator end = agrp.end(); for (; ait != end; ++ait, ++bit) { if (psize > 1) { if (mesh_group_before.isLocalOrMasterNode(*bit)) bgnode.push_back(gidb(*bit)); if (mesh_group_after.isLocalOrMasterNode(*ait)) agnode.push_back(gida(*ait)); } } std::sort(bgnode.begin(), bgnode.end()); std::sort(agnode.begin(), agnode.end()); if (!std::equal(bgnode.begin(), bgnode.end(), agnode.begin())) { std::cerr << "The filters array for the group " << grp << " do not match" << std::endl; debug::setDebugLevel(dblTest); std::cerr << bgnode << std::endl; std::cerr << agnode << std::endl; debug::debugger.exit(EXIT_FAILURE); } } mesh_group_after.getElementGroup("inside").setBaseName("after_inside"); mesh_group_after.getElementGroup("inside").dump(); mesh_group_after.getElementGroup("outside").setBaseName("after_outside"); mesh_group_after.getElementGroup("outside").dump(); mesh_group_after.getElementGroup("volume").setBaseName("after_volume"); mesh_group_after.getElementGroup("volume").dump(); mesh_group_before.getElementGroup("inside").setBaseName("before_inside"); mesh_group_before.getElementGroup("inside").dump(); mesh_group_before.getElementGroup("outside").setBaseName("before_outside"); mesh_group_before.getElementGroup("outside").dump(); mesh_group_before.getElementGroup("volume").setBaseName("before_volume"); mesh_group_before.getElementGroup("volume").dump(); finalize(); return EXIT_SUCCESS; }