diff --git a/packages/core.cmake b/packages/core.cmake index 23dd56108..0608787ec 100644 --- a/packages/core.cmake +++ b/packages/core.cmake @@ -1,581 +1,583 @@ #=============================================================================== # @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 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_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/packages/damage_non_local.cmake b/packages/damage_non_local.cmake index c3b2335f2..c3bb6f74a 100644 --- a/packages/damage_non_local.cmake +++ b/packages/damage_non_local.cmake @@ -1,68 +1,68 @@ #=============================================================================== # @file damage_non_local.cmake # # @author Nicolas Richart <nicolas.richart@epfl.ch> # # @date creation: Fri Jun 15 2012 # @date last modification: Mon Jan 18 2016 # # @brief package description for non-local materials # # @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(damage_non_local DESCRIPTION "Package for Non-local damage constitutives laws Akantu" DEPENDS lapack) package_declare_sources(damage_non_local model/solid_mechanics/materials/material_damage/material_damage_non_local.hh + model/solid_mechanics/materials/material_damage/material_marigo_non_local.cc model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh - model/solid_mechanics/materials/material_damage/material_marigo_non_local_inline_impl.cc model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc model/solid_mechanics/materials/material_damage/material_mazars_non_local.hh model/solid_mechanics/materials/weight_functions/base_weight_function.hh model/solid_mechanics/materials/weight_functions/base_weight_function_inline_impl.cc model/solid_mechanics/materials/weight_functions/damaged_weight_function.hh model/solid_mechanics/materials/weight_functions/damaged_weight_function_inline_impl.cc model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function.hh model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.cc model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh model/solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function_inline_impl.cc model/solid_mechanics/materials/weight_functions/stress_based_weight_function.hh model/solid_mechanics/materials/weight_functions/stress_based_weight_function.cc model/solid_mechanics/materials/weight_functions/stress_based_weight_function_inline_impl.cc ) package_declare_material_infos(damage_non_local LIST AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST INCLUDE material_non_local_includes.hh ) package_declare_documentation_files(damage_non_local manual-constitutive-laws-non_local.tex manual-appendix-materials-non-local.tex) package_declare_documentation(damage_non_local "This package activates the non local damage feature of AKANTU" "") diff --git a/src/common/aka_common.cc b/src/common/aka_common.cc index dd5955a94..0fd4b6d31 100644 --- a/src/common/aka_common.cc +++ b/src/common/aka_common.cc @@ -1,155 +1,152 @@ /** * @file aka_common.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Jun 14 2010 * @date last modification: Tue Jan 19 2016 * * @brief Initialization of global variables * * @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_static_memory.hh" #include "static_communicator.hh" #include "aka_random_generator.hh" #include "parser.hh" #include "cppargparse.hh" #include "communication_tag.hh" /* -------------------------------------------------------------------------- */ #include <ctime> /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ void initialize(int & argc, char **& argv) { AKANTU_DEBUG_IN(); initialize("", argc, argv); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void initialize(const std::string & input_file, int & argc, char **& argv) { AKANTU_DEBUG_IN(); StaticMemory::getStaticMemory(); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(argc, argv); Tag::setMaxTag(comm.getMaxTag()); debug::debugger.setParallelContext(comm.whoAmI(), comm.getNbProc()); debug::initSignalHandler(); debug::setDebugLevel(dblError); static_argparser.setParallelContext(comm.whoAmI(), comm.getNbProc()); static_argparser.setExternalExitFunction(debug::exit); static_argparser.addArgument("--aka_input_file", "Akantu's input file", 1, cppargparse::_string, std::string()); static_argparser.addArgument( "--aka_debug_level", std::string("Akantu's overall debug level") + std::string(" (0: error, 1: exceptions, 4: warnings, 5: info, ..., " "100: dump") + std::string(" more info on levels can be foind in aka_error.hh)"), 1, cppargparse::_integer, int(dblWarning)); static_argparser.addArgument( "--aka_print_backtrace", "Should Akantu print a backtrace in case of error", 0, cppargparse::_boolean, false, true); static_argparser.parse(argc, argv, cppargparse::_remove_parsed); std::string infile = static_argparser["aka_input_file"]; if (infile == "") infile = input_file; debug::debugger.printBacktrace(static_argparser["aka_print_backtrace"]); if ("" != infile) { readInputFile(infile); } long int seed; try { seed = static_parser.getParameter("seed", _ppsc_current_scope); } catch (debug::Exception &) { seed = time(NULL); } seed *= (comm.whoAmI() + 1); -#if not defined(_WIN32) - Rand48Generator<Real>::seed(seed); -#endif - RandGenerator<Real>::seed(seed); + RandomGenerator<UInt>::seed(seed); int dbl_level = static_argparser["aka_debug_level"]; debug::setDebugLevel(DebugLevel(dbl_level)); AKANTU_DEBUG_INFO("Random seed set to " << seed); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void finalize() { AKANTU_DEBUG_IN(); if (StaticCommunicator::isInstantiated()) { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); delete &comm; } if (StaticMemory::isInstantiated()) { delete &(StaticMemory::getStaticMemory()); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void readInputFile(const std::string & input_file) { static_parser.parse(input_file); } /* -------------------------------------------------------------------------- */ cppargparse::ArgumentParser & getStaticArgumentParser() { return static_argparser; } /* -------------------------------------------------------------------------- */ Parser & getStaticParser() { return static_parser; } /* -------------------------------------------------------------------------- */ const ParserSection & getUserParser() { return *(static_parser.getSubSections(_st_user).first); } } // akantu diff --git a/src/common/aka_extern.cc b/src/common/aka_extern.cc index 4c5b7d03e..27d30649a 100644 --- a/src/common/aka_extern.cc +++ b/src/common/aka_extern.cc @@ -1,137 +1,128 @@ /** * @file aka_extern.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Jun 14 2010 * @date last modification: Thu Nov 19 2015 * * @brief initialisation of all global variables * to insure the order of creation * * @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_common.hh" #include "aka_math.hh" #include "aka_named_argument.hh" #include "aka_random_generator.hh" #include "communication_tag.hh" #include "cppargparse.hh" #include "parser.hh" #include "solid_mechanics_model.hh" #if defined(AKANTU_COHESIVE_ELEMENT) #include "solid_mechanics_model_cohesive.hh" #endif /* -------------------------------------------------------------------------- */ #include <iostream> #include <limits> /* -------------------------------------------------------------------------- */ #if defined(AKANTU_DEBUG_TOOLS) #include "aka_debug_tools.hh" #endif namespace akantu { -/** \todo write function to get this - * values from the environment or a config file - */ - /* -------------------------------------------------------------------------- */ /* error.hpp variables */ /* -------------------------------------------------------------------------- */ namespace debug { + /** \todo write function to get this + * values from the environment or a config file + */ /// standard output for debug messages std::ostream * _akantu_debug_cout = &std::cerr; /// standard output for normal messages std::ostream & _akantu_cout = std::cout; /// parallel context used in debug messages std::string _parallel_context = ""; Debugger debugger; #if defined(AKANTU_DEBUG_TOOLS) DebugElementManager element_manager; #endif } // namespace debug /* -------------------------------------------------------------------------- */ /// list of ghost iterable types ghost_type_t ghost_types(_casper); /* -------------------------------------------------------------------------- */ use_named_args_t use_named_args; CREATE_NAMED_ARGUMENT(all_ghost_types); CREATE_NAMED_ARGUMENT(default_value); CREATE_NAMED_ARGUMENT(element_kind); CREATE_NAMED_ARGUMENT(ghost_type); CREATE_NAMED_ARGUMENT(nb_component); CREATE_NAMED_ARGUMENT(spatial_dimension); CREATE_NAMED_ARGUMENT(with_nb_element); CREATE_NAMED_ARGUMENT(with_nb_nodes_per_element); CREATE_NAMED_ARGUMENT(analysis_method); CREATE_NAMED_ARGUMENT(no_init_materials); #if defined(AKANTU_COHESIVE_ELEMENT) CREATE_NAMED_ARGUMENT(is_extrinsic); #endif /* -------------------------------------------------------------------------- */ /// Paser for commandline arguments ::cppargparse::ArgumentParser static_argparser; /// Parser containing the information parsed by the input file given to initFull Parser static_parser; bool Parser::permissive_parser = false; /* -------------------------------------------------------------------------- */ Real Math::tolerance = std::numeric_limits<Real>::epsilon(); /* -------------------------------------------------------------------------- */ const UInt _all_dimensions = UInt(-1); /* -------------------------------------------------------------------------- */ const Array<UInt> empty_filter(0, 1, "empty_filter"); /* -------------------------------------------------------------------------- */ -template <> long int RandGenerator<Real>::_seed = 0; -template <> -long int RandGenerator<bool>::_seed = - 0; // useless just defined due to a template instantiation -template <> long int RandGenerator<UInt>::_seed = 0; -template <> long int RandGenerator<Int>::_seed = 0; -#if not defined(_WIN32) -template <> long int Rand48Generator<Real>::_seed = 0; -#endif - +template <> long int RandomGenerator<UInt>::_seed = 5489u; +template <> std::default_random_engine RandomGenerator<UInt>::generator(5489u); /* -------------------------------------------------------------------------- */ int Tag::max_tag = 0; /* -------------------------------------------------------------------------- */ } // namespace akantu diff --git a/src/common/aka_factory.hh b/src/common/aka_factory.hh new file mode 100644 index 000000000..958ed5285 --- /dev/null +++ b/src/common/aka_factory.hh @@ -0,0 +1,78 @@ +/** + * @file aka_factory.hh + * + * @author Nicolas Richart + * + * @date creation Thu Jul 06 2017 + * + * @brief This is a generic factory + * + * @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_common.hh" +/* -------------------------------------------------------------------------- */ +#include <map> +#include <memory> +#include <functional> +#include <string> +/* -------------------------------------------------------------------------- */ + +#ifndef __AKANTU_AKA_FACTORY_HH__ +#define __AKANTU_AKA_FACTORY_HH__ + +namespace akantu { + +template <class Base, class... Args> class Factory { + using allocator_t = std::function<std::unique_ptr<Base>(Args...)>; +private: + Factory() = default; +public: + Factory(const Factory &) = delete; + Factory & operator=(const Factory &) = delete; + + static Factory & getInstance() { + static Factory instance; + return instance; + } + /* ------------------------------------------------------------------------ */ + bool registerAllocator(ID id, const allocator_t & allocator) { + if (allocators.find(id) != allocators.end()) + AKANTU_EXCEPTION("The id " << id << " is already registered in the " + << debug::demangle(typeid(Base).name()) << " factory"); + allocators[id] = allocator; + return true; + } + + std::unique_ptr<Base> allocate(ID id, Args... args) { + if (allocators.find(id) == allocators.end()) + AKANTU_EXCEPTION("The id " << id << " is not registered in the " + << debug::demangle(typeid(Base).name()) + << " factory."); + return std::forward<std::unique_ptr<Base>>(allocators[id](args...)); + } + +private: + std::map<std::string, allocator_t> allocators; +}; + +} // namespace akantu + +#endif /* __AKANTU_AKA_FACTORY_HH__ */ diff --git a/src/common/aka_named_argument.hh b/src/common/aka_named_argument.hh index 1b5ecc1bf..af0c7d742 100644 --- a/src/common/aka_named_argument.hh +++ b/src/common/aka_named_argument.hh @@ -1,158 +1,158 @@ /** * @file aka_named_argument.hh * * @author Marco Arena * * @date creation Fri Jun 16 2017 * * @brief A Documented file. * * @section LICENSE * * Public Domain ? https://gist.github.com/ilpropheta/7576dce4c3249df89f85 * */ /* -------------------------------------------------------------------------- */ #include <tuple> #include <type_traits> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_NAMED_ARGUMENT_HH__ #define __AKANTU_AKA_NAMED_ARGUMENT_HH__ namespace akantu { struct use_named_args_t {}; extern use_named_args_t use_named_args; namespace named_argument { /* -- Pack utils (proxy version) -------------------------------------------- */ /// Proxy containing [tag, value] template <typename tag, typename type> struct param_t { using _tag = tag; using _type = type; template <typename T> explicit param_t(T && value) : _value(std::forward<T>(value)) {} type _value; }; /* * Tagged proxy that allows syntax _name = value * operator=(T&&) returns a param_t instance **/ template <typename tag> struct param_proxy { using _tag = tag; template <typename T> decltype(auto) operator=(T && value) { return param_t<tag, decltype(value)>{std::forward<T>(value)}; } }; /* Same as type_at but it's supposed to be used by passing a pack of param_t (_tag is looked for instead of a plain type). This and type_at should be refactored. */ template <typename T, typename head, typename... tail> struct type_at_p { enum { _tmp = (std::is_same<T, typename std::decay<head>::type::_tag>::value) ? 0 : type_at_p<T, tail...>::_pos }; enum { _pos = _tmp == -1 ? -1 : 1 + _tmp }; }; template <typename T, typename head> struct type_at_p<T, head> { enum { _pos = (std::is_same<T, typename std::decay<head>::type::_tag>::value ? 1 : -1) }; }; template <typename T, typename head, typename... tail> struct type_at { enum { _tmp = type_at_p<T, head, tail...>::_pos }; enum { _pos = _tmp == 1 ? 0 : (_tmp == -1 ? -1 : _tmp - 1) }; }; /* Same as get_at but it's supposed to be used by passing a pack of param_t (_type is retrieved instead) This and get_at should be refactored. */ template <int pos, int curr> struct get_at { static_assert(pos >= 0, "Required parameter"); template <typename head, typename... tail> static decltype(auto) get(head &&, tail &&... t) { return get_at<pos, curr + 1>::get(std::forward<tail>(t)...); } }; template <int pos> struct get_at<pos, pos> { static_assert(pos >= 0, "Required parameter"); template <typename head, typename... tail> static decltype(auto) get(head && h, tail &&...) { - return std::forward<typename head::_type>(h._value); + return std::forward<decltype(h._value)>(h._value); } }; // Optional version template <int pos, int curr> struct get_optional { template <typename T, typename... pack> static decltype(auto) get(T &&, pack &&... _pack) { return get_at<pos, curr>::get(std::forward<pack>(_pack)...); } }; template <int curr> struct get_optional<-1, curr> { template <typename T, typename... pack> static decltype(auto) get(T && _default, pack &&...) { return std::forward<T>(_default); } }; } // namespace named_argument // CONVENIENCE MACROS FOR CLASS DESIGNERS ========== #define TAG_OF_ARGUMENT(_name) p_##_name #define TAG_OF_ARGUMENT_WNS(_name) named_argument::TAG_OF_ARGUMENT(_name) #define REQUIRED_NAMED_ARG(_name) \ named_argument::get_at< \ named_argument::type_at<TAG_OF_ARGUMENT_WNS(_name), pack...>::_pos, \ 0>::get(std::forward<pack>(_pack)...) #define OPTIONAL_NAMED_ARG(_name, _defaultVal) \ named_argument::get_optional< \ named_argument::type_at<TAG_OF_ARGUMENT_WNS(_name), pack...>::_pos, \ 0>::get(_defaultVal, std::forward<pack>(_pack)...) #define DECLARE_NAMED_ARGUMENT(name) \ namespace named_argument { \ struct TAG_OF_ARGUMENT(name) {}; \ } \ extern named_argument::param_proxy<TAG_OF_ARGUMENT_WNS(name)> _##name #define CREATE_NAMED_ARGUMENT(name) \ named_argument::param_proxy<TAG_OF_ARGUMENT_WNS(name)> _##name DECLARE_NAMED_ARGUMENT(all_ghost_types); DECLARE_NAMED_ARGUMENT(default_value); DECLARE_NAMED_ARGUMENT(element_kind); DECLARE_NAMED_ARGUMENT(ghost_type); DECLARE_NAMED_ARGUMENT(nb_component); DECLARE_NAMED_ARGUMENT(with_nb_element); DECLARE_NAMED_ARGUMENT(with_nb_nodes_per_element); DECLARE_NAMED_ARGUMENT(spatial_dimension); DECLARE_NAMED_ARGUMENT(analysis_method); DECLARE_NAMED_ARGUMENT(no_init_materials); #if defined(AKANTU_COHESIVE_ELEMENT) DECLARE_NAMED_ARGUMENT(is_extrinsic); #endif } // namespace akantu #endif /* __AKANTU_AKA_NAMED_ARGUMENT_HH__ */ diff --git a/src/fe_engine/fe_engine_template_tmpl.hh b/src/fe_engine/fe_engine_template_tmpl.hh index 15f8a9fe3..c6f135b15 100644 --- a/src/fe_engine/fe_engine_template_tmpl.hh +++ b/src/fe_engine/fe_engine_template_tmpl.hh @@ -1,1674 +1,1673 @@ /** * @file fe_engine_template_tmpl.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue Feb 15 2011 * @date last modification: Thu Nov 19 2015 * * @brief Template implementation of FEEngineTemplate * * @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 "dof_manager.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::FEEngineTemplate( Mesh & mesh, UInt spatial_dimension, ID id, MemoryID memory_id) : FEEngine(mesh, spatial_dimension, id, memory_id), integrator(mesh, id, memory_id), shape_functions(mesh, id, memory_id) {} /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::~FEEngineTemplate() {} /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct GradientOnIntegrationPointsHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) Mesh & mesh, __attribute__((unused)) const Array<Real> & u, __attribute__((unused)) Array<Real> & nablauq, __attribute__((unused)) const UInt nb_degree_of_freedom, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type, __attribute__((unused)) const Array<UInt> & filter_elements) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define COMPUTE_GRADIENT(type) \ if (element_dimension == ElementClass<type>::getSpatialDimension()) \ shape_functions.template gradientOnIntegrationPoints<type>( \ u, nablauq, nb_degree_of_freedom, ghost_type, filter_elements); #define AKANTU_SPECIALIZE_GRADIENT_ON_INTEGRATION_POINTS_HELPER(kind) \ template <> struct GradientOnIntegrationPointsHelper<kind> { \ template <class S> \ static void call(const S & shape_functions, Mesh & mesh, \ const Array<Real> & u, Array<Real> & nablauq, \ const UInt nb_degree_of_freedom, \ const ElementType & type, const GhostType & ghost_type, \ const Array<UInt> & filter_elements) { \ UInt element_dimension = mesh.getSpatialDimension(type); \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_GRADIENT, kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST( AKANTU_SPECIALIZE_GRADIENT_ON_INTEGRATION_POINTS_HELPER, AKANTU_FE_ENGINE_LIST_GRADIENT_ON_INTEGRATION_POINTS) #undef AKANTU_SPECIALIZE_GRADIENT_ON_INTEGRATION_POINTS_HELPER #undef COMPUTE_GRADIENT template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: gradientOnIntegrationPoints(const Array<Real> & u, Array<Real> & nablauq, const UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); UInt nb_element = mesh.getNbElement(type, ghost_type); if (filter_elements != empty_filter) nb_element = filter_elements.getSize(); UInt nb_points = shape_functions.getIntegrationPoints(type, ghost_type).cols(); #ifndef AKANTU_NDEBUG UInt element_dimension = mesh.getSpatialDimension(type); AKANTU_DEBUG_ASSERT(u.getSize() == mesh.getNbNodes(), "The vector u(" << u.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(u.getNbComponent() == nb_degree_of_freedom, "The vector u(" << u.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT( nablauq.getNbComponent() == nb_degree_of_freedom * element_dimension, "The vector nablauq(" << nablauq.getID() << ") has not the good number of component."); // AKANTU_DEBUG_ASSERT(nablauq.getSize() == nb_element * nb_points, // "The vector nablauq(" << nablauq.getID() // << ") has not the good size."); #endif nablauq.resize(nb_element * nb_points); GradientOnIntegrationPointsHelper<kind>::call( shape_functions, mesh, u, nablauq, nb_degree_of_freedom, type, ghost_type, filter_elements); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::initShapeFunctions( const GhostType & ghost_type) { initShapeFunctions(mesh.getNodes(), ghost_type); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::initShapeFunctions( const Array<Real> & nodes, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Mesh::type_iterator it = mesh.firstType(element_dimension, ghost_type, kind); Mesh::type_iterator end = mesh.lastType(element_dimension, ghost_type, kind); for (; it != end; ++it) { ElementType type = *it; integrator.initIntegrator(nodes, type, ghost_type); const Matrix<Real> & control_points = getIntegrationPoints(type, ghost_type); shape_functions.initShapeFunctions(nodes, control_points, type, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct IntegrateHelper {}; #define INTEGRATE(type) \ integrator.template integrate<type>(f, intf, nb_degree_of_freedom, \ ghost_type, filter_elements); #define AKANTU_SPECIALIZE_INTEGRATE_HELPER(kind) \ template <> struct IntegrateHelper<kind> { \ template <class I> \ static void call(const I & integrator, const Array<Real> & f, \ Array<Real> & intf, UInt nb_degree_of_freedom, \ const ElementType & type, const GhostType & ghost_type, \ const Array<UInt> & filter_elements) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind); \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_HELPER) #undef AKANTU_SPECIALIZE_INTEGRATE_HELPER #undef INTEGRATE template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::integrate( const Array<Real> & f, Array<Real> & intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { UInt nb_element = mesh.getNbElement(type, ghost_type); if (filter_elements != empty_filter) nb_element = filter_elements.getSize(); #ifndef AKANTU_NDEBUG UInt nb_quadrature_points = getNbIntegrationPoints(type); AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points, "The vector f(" << f.getID() << " size " << f.getSize() << ") has not the good size (" << nb_element << ")."); AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom, "The vector f(" << f.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degree_of_freedom, "The vector intf(" << intf.getID() << ") has not the good number of component."); #endif intf.resize(nb_element); IntegrateHelper<kind>::call(integrator, f, intf, nb_degree_of_freedom, type, ghost_type, filter_elements); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct IntegrateScalarHelper {}; #define INTEGRATE(type) \ integral = \ integrator.template integrate<type>(f, ghost_type, filter_elements); #define AKANTU_SPECIALIZE_INTEGRATE_SCALAR_HELPER(kind) \ template <> struct IntegrateScalarHelper<kind> { \ template <class I> \ static Real call(const I & integrator, const Array<Real> & f, \ const ElementType & type, const GhostType & ghost_type, \ const Array<UInt> & filter_elements) { \ Real integral = 0.; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind); \ return integral; \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_SCALAR_HELPER) #undef AKANTU_SPECIALIZE_INTEGRATE_SCALAR_HELPER #undef INTEGRATE template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> Real FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::integrate( const Array<Real> & f, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); #ifndef AKANTU_NDEBUG // std::stringstream sstr; sstr << ghost_type; // AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(), // "The vector " << nablauq.getID() << " is not taged " << // ghost_type); UInt nb_element = mesh.getNbElement(type, ghost_type); if (filter_elements != empty_filter) nb_element = filter_elements.getSize(); UInt nb_quadrature_points = getNbIntegrationPoints(type, ghost_type); AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points, "The vector f(" << f.getID() << ") has not the good size. (" << f.getSize() << "!=" << nb_quadrature_points * nb_element << ")"); AKANTU_DEBUG_ASSERT(f.getNbComponent() == 1, "The vector f(" << f.getID() << ") has not the good number of component."); #endif Real integral = IntegrateScalarHelper<kind>::call( integrator, f, type, ghost_type, filter_elements); AKANTU_DEBUG_OUT(); return integral; } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct IntegrateScalarOnOneElementHelper {}; #define INTEGRATE(type) \ res = integrator.template integrate<type>(f, index, ghost_type); #define AKANTU_SPECIALIZE_INTEGRATE_SCALAR_ON_ONE_ELEMENT_HELPER(kind) \ template <> struct IntegrateScalarOnOneElementHelper<kind> { \ template <class I> \ static Real call(const I & integrator, const Vector<Real> & f, \ const ElementType & type, UInt index, \ const GhostType & ghost_type) { \ Real res = 0.; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind); \ return res; \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_SCALAR_ON_ONE_ELEMENT_HELPER) #undef AKANTU_SPECIALIZE_INTEGRATE_SCALAR_ON_ONE_ELEMENT_HELPER #undef INTEGRATE template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> Real FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::integrate( const Vector<Real> & f, const ElementType & type, UInt index, const GhostType & ghost_type) const { Real res = IntegrateScalarOnOneElementHelper<kind>::call(integrator, f, type, index, ghost_type); return res; } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct IntegrateOnIntegrationPointsHelper {}; #define INTEGRATE(type) \ integrator.template integrateOnIntegrationPoints<type>( \ f, intf, nb_degree_of_freedom, ghost_type, filter_elements); #define AKANTU_SPECIALIZE_INTEGRATE_ON_INTEGRATION_POINTS_HELPER(kind) \ template <> struct IntegrateOnIntegrationPointsHelper<kind> { \ template <class I> \ static void call(const I & integrator, const Array<Real> & f, \ Array<Real> & intf, UInt nb_degree_of_freedom, \ const ElementType & type, const GhostType & ghost_type, \ const Array<UInt> & filter_elements) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTEGRATE, kind); \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_INTEGRATE_ON_INTEGRATION_POINTS_HELPER) #undef AKANTU_SPECIALIZE_INTEGRATE_ON_INTEGRATION_POINTS_HELPER #undef INTEGRATE template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: integrateOnIntegrationPoints(const Array<Real> & f, Array<Real> & intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { UInt nb_element = mesh.getNbElement(type, ghost_type); if (filter_elements != empty_filter) nb_element = filter_elements.getSize(); UInt nb_quadrature_points = getNbIntegrationPoints(type); #ifndef AKANTU_NDEBUG // std::stringstream sstr; sstr << ghost_type; // AKANTU_DEBUG_ASSERT(sstr.str() == nablauq.getTag(), // "The vector " << nablauq.getID() << " is not taged " << // ghost_type); AKANTU_DEBUG_ASSERT(f.getSize() == nb_element * nb_quadrature_points, "The vector f(" << f.getID() << " size " << f.getSize() << ") has not the good size (" << nb_element << ")."); AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom, "The vector f(" << f.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degree_of_freedom, "The vector intf(" << intf.getID() << ") has not the good number of component."); #endif intf.resize(nb_element * nb_quadrature_points); IntegrateOnIntegrationPointsHelper<kind>::call(integrator, f, intf, nb_degree_of_freedom, type, ghost_type, filter_elements); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct InterpolateOnIntegrationPointsHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) const Array<Real> & u, __attribute__((unused)) Array<Real> & uq, __attribute__((unused)) const UInt nb_degree_of_freedom, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type, __attribute__((unused)) const Array<UInt> & filter_elements) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define INTERPOLATE(type) \ shape_functions.template interpolateOnIntegrationPoints<type>( \ u, uq, nb_degree_of_freedom, ghost_type, filter_elements); #define AKANTU_SPECIALIZE_INTERPOLATE_ON_INTEGRATION_POINTS_HELPER(kind) \ template <> struct InterpolateOnIntegrationPointsHelper<kind> { \ template <class S> \ static void call(const S & shape_functions, const Array<Real> & u, \ Array<Real> & uq, const UInt nb_degree_of_freedom, \ const ElementType & type, const GhostType & ghost_type, \ const Array<UInt> & filter_elements) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTERPOLATE, kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST( AKANTU_SPECIALIZE_INTERPOLATE_ON_INTEGRATION_POINTS_HELPER, AKANTU_FE_ENGINE_LIST_INTERPOLATE_ON_INTEGRATION_POINTS) #undef AKANTU_SPECIALIZE_INTERPOLATE_ON_INTEGRATION_POINTS_HELPER #undef INTERPOLATE template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: interpolateOnIntegrationPoints(const Array<Real> & u, Array<Real> & uq, const UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { AKANTU_DEBUG_IN(); UInt nb_points = shape_functions.getIntegrationPoints(type, ghost_type).cols(); UInt nb_element = mesh.getNbElement(type, ghost_type); if (filter_elements != empty_filter) nb_element = filter_elements.getSize(); #ifndef AKANTU_NDEBUG AKANTU_DEBUG_ASSERT(u.getSize() == mesh.getNbNodes(), "The vector u(" << u.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(u.getNbComponent() == nb_degree_of_freedom, "The vector u(" << u.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(uq.getNbComponent() == nb_degree_of_freedom, "The vector uq(" << uq.getID() << ") has not the good number of component."); #endif uq.resize(nb_element * nb_points); InterpolateOnIntegrationPointsHelper<kind>::call(shape_functions, u, uq, nb_degree_of_freedom, type, ghost_type, filter_elements); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: interpolateOnIntegrationPoints( const Array<Real> & u, ElementTypeMapArray<Real> & uq, const ElementTypeMapArray<UInt> * filter_elements) const { AKANTU_DEBUG_IN(); const Array<UInt> * filter = NULL; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; ElementTypeMapArray<Real>::type_iterator it = uq.firstType(_all_dimensions, ghost_type, kind); ElementTypeMapArray<Real>::type_iterator last = uq.lastType(_all_dimensions, ghost_type, kind); for (; it != last; ++it) { ElementType type = *it; UInt nb_quad_per_element = getNbIntegrationPoints(type, ghost_type); UInt nb_element = 0; if (filter_elements) { filter = &((*filter_elements)(type, ghost_type)); nb_element = filter->getSize(); } else { filter = &empty_filter; nb_element = mesh.getNbElement(type, ghost_type); } UInt nb_tot_quad = nb_quad_per_element * nb_element; Array<Real> & quad = uq(type, ghost_type); quad.resize(nb_tot_quad); interpolateOnIntegrationPoints(u, quad, quad.getNbComponent(), type, ghost_type, *filter); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: computeIntegrationPointsCoordinates( ElementTypeMapArray<Real> & quadrature_points_coordinates, const ElementTypeMapArray<UInt> * filter_elements) const { const Array<Real> & nodes_coordinates = mesh.getNodes(); interpolateOnIntegrationPoints( nodes_coordinates, quadrature_points_coordinates, filter_elements); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: computeIntegrationPointsCoordinates( Array<Real> & quadrature_points_coordinates, const ElementType & type, const GhostType & ghost_type, const Array<UInt> & filter_elements) const { const Array<Real> & nodes_coordinates = mesh.getNodes(); UInt spatial_dimension = mesh.getSpatialDimension(); interpolateOnIntegrationPoints( nodes_coordinates, quadrature_points_coordinates, spatial_dimension, type, ghost_type, filter_elements); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: initElementalFieldInterpolationFromIntegrationPoints( const ElementTypeMapArray<Real> & interpolation_points_coordinates, ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices, const ElementTypeMapArray<UInt> * element_filter) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = this->mesh.getSpatialDimension(); ElementTypeMapArray<Real> quadrature_points_coordinates( "quadrature_points_coordinates_for_interpolation", getID(), getMemoryID()); quadrature_points_coordinates.initialize( - *this, _nb_component = spatial_dimension, - _spatial_dimension = spatial_dimension); + *this, _nb_component = spatial_dimension); computeIntegrationPointsCoordinates(quadrature_points_coordinates, element_filter); shape_functions.initElementalFieldInterpolationFromIntegrationPoints( interpolation_points_coordinates, interpolation_points_coordinates_matrices, quad_points_coordinates_inv_matrices, quadrature_points_coordinates, element_filter); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: interpolateElementalFieldFromIntegrationPoints( const ElementTypeMapArray<Real> & field, const ElementTypeMapArray<Real> & interpolation_points_coordinates, ElementTypeMapArray<Real> & result, const GhostType ghost_type, const ElementTypeMapArray<UInt> * element_filter) const { ElementTypeMapArray<Real> interpolation_points_coordinates_matrices( "interpolation_points_coordinates_matrices", id, memory_id); ElementTypeMapArray<Real> quad_points_coordinates_inv_matrices( "quad_points_coordinates_inv_matrices", id, memory_id); initElementalFieldInterpolationFromIntegrationPoints( interpolation_points_coordinates, interpolation_points_coordinates_matrices, quad_points_coordinates_inv_matrices, element_filter); interpolateElementalFieldFromIntegrationPoints( field, interpolation_points_coordinates_matrices, quad_points_coordinates_inv_matrices, result, ghost_type, element_filter); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: interpolateElementalFieldFromIntegrationPoints( const ElementTypeMapArray<Real> & field, const ElementTypeMapArray<Real> & interpolation_points_coordinates_matrices, const ElementTypeMapArray<Real> & quad_points_coordinates_inv_matrices, ElementTypeMapArray<Real> & result, const GhostType ghost_type, const ElementTypeMapArray<UInt> * element_filter) const { shape_functions.interpolateElementalFieldFromIntegrationPoints( field, interpolation_points_coordinates_matrices, quad_points_coordinates_inv_matrices, result, ghost_type, element_filter); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct InterpolateHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) const Vector<Real> & real_coords, __attribute__((unused)) UInt elem, __attribute__((unused)) const Matrix<Real> & nodal_values, __attribute__((unused)) Vector<Real> & interpolated, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define INTERPOLATE(type) \ shape_functions.template interpolate<type>( \ real_coords, element, nodal_values, interpolated, ghost_type); #define AKANTU_SPECIALIZE_INTERPOLATE_HELPER(kind) \ template <> struct InterpolateHelper<kind> { \ template <class S> \ static void call(const S & shape_functions, \ const Vector<Real> & real_coords, UInt element, \ const Matrix<Real> & nodal_values, \ Vector<Real> & interpolated, const ElementType & type, \ const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INTERPOLATE, kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_INTERPOLATE_HELPER, AKANTU_FE_ENGINE_LIST_INTERPOLATE) #undef AKANTU_SPECIALIZE_INTERPOLATE_HELPER #undef INTERPOLATE template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::interpolate( const Vector<Real> & real_coords, const Matrix<Real> & nodal_values, Vector<Real> & interpolated, const Element & element) const { AKANTU_DEBUG_IN(); InterpolateHelper<kind>::call(shape_functions, real_coords, element.element, nodal_values, interpolated, element.type, element.ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: computeNormalsOnIntegrationPoints(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); computeNormalsOnIntegrationPoints(mesh.getNodes(), ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: computeNormalsOnIntegrationPoints(const Array<Real> & field, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); // Real * coord = mesh.getNodes().storage(); UInt spatial_dimension = mesh.getSpatialDimension(); // allocate the normal arrays Mesh::type_iterator it = mesh.firstType(element_dimension, ghost_type, kind); Mesh::type_iterator end = mesh.lastType(element_dimension, ghost_type, kind); for (; it != end; ++it) { ElementType type = *it; UInt size = mesh.getNbElement(type, ghost_type); if (normals_on_integration_points.exists(type, ghost_type)) { normals_on_integration_points(type, ghost_type).resize(size); } else { normals_on_integration_points.alloc(size, spatial_dimension, type, ghost_type); } } // loop over the type to build the normals it = mesh.firstType(element_dimension, ghost_type, kind); for (; it != end; ++it) { Array<Real> & normals_on_quad = normals_on_integration_points(*it, ghost_type); computeNormalsOnIntegrationPoints(field, normals_on_quad, *it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct ComputeNormalsOnIntegrationPoints { template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind k, class IOF> static void call(__attribute__((unused)) const FEEngineTemplate<I, S, k, IOF> & fem, __attribute__((unused)) const Array<Real> & field, __attribute__((unused)) Array<Real> & normal, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define COMPUTE_NORMALS_ON_INTEGRATION_POINTS(type) \ fem.template computeNormalsOnIntegrationPoints<type>(field, normal, \ ghost_type); #define AKANTU_SPECIALIZE_COMPUTE_NORMALS_ON_INTEGRATION_POINTS(kind) \ template <> struct ComputeNormalsOnIntegrationPoints<kind> { \ template <template <ElementKind, class> class I, \ template <ElementKind> class S, ElementKind k, class IOF> \ static void call(const FEEngineTemplate<I, S, k, IOF> & fem, \ const Array<Real> & field, Array<Real> & normal, \ const ElementType & type, const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_NORMALS_ON_INTEGRATION_POINTS, \ kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST( AKANTU_SPECIALIZE_COMPUTE_NORMALS_ON_INTEGRATION_POINTS, AKANTU_FE_ENGINE_LIST_COMPUTE_NORMALS_ON_INTEGRATION_POINTS) #undef AKANTU_SPECIALIZE_COMPUTE_NORMALS_ON_INTEGRATION_POINTS #undef COMPUTE_NORMALS_ON_INTEGRATION_POINTS template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: computeNormalsOnIntegrationPoints(const Array<Real> & field, Array<Real> & normal, const ElementType & type, const GhostType & ghost_type) const { ComputeNormalsOnIntegrationPoints<kind>::call(*this, field, normal, type, ghost_type); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: computeNormalsOnIntegrationPoints(const Array<Real> & field, Array<Real> & normal, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_points = getNbIntegrationPoints(type, ghost_type); UInt nb_element = mesh.getConnectivity(type, ghost_type).getSize(); normal.resize(nb_element * nb_points); Array<Real>::matrix_iterator normals_on_quad = normal.begin_reinterpret(spatial_dimension, nb_points, nb_element); Array<Real> f_el(0, spatial_dimension * nb_nodes_per_element); FEEngine::extractNodalToElementField(mesh, field, f_el, type, ghost_type); const Matrix<Real> & quads = integrator.template getIntegrationPoints<type>(ghost_type); Array<Real>::matrix_iterator f_it = f_el.begin(spatial_dimension, nb_nodes_per_element); for (UInt elem = 0; elem < nb_element; ++elem) { ElementClass<type>::computeNormalsOnNaturalCoordinates(quads, *f_it, *normals_on_quad); ++normals_on_quad; ++f_it; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Matrix lumping functions */ /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct AssembleLumpedTemplateHelper {}; #define ASSEMBLE_LUMPED(type) \ fem.template assembleLumpedTemplate<type>(field_1, lumped, dof_id, \ dof_manager, ghost_type) #define AKANTU_SPECIALIZE_ASSEMBLE_HELPER(kind) \ template <> struct AssembleLumpedTemplateHelper<kind> { \ template <template <ElementKind, class> class I, \ template <ElementKind> class S, ElementKind k, class IOF> \ static void call(const FEEngineTemplate<I, S, k, IOF> & fem, \ const Array<Real> & field_1, const ID & lumped, \ const ID & dof_id, DOFManager & dof_manager, \ ElementType type, const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(ASSEMBLE_LUMPED, kind); \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_ASSEMBLE_HELPER) #undef AKANTU_SPECIALIZE_ASSEMBLE_HELPER #undef ASSEMBLE_LUMPED /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IOF> void FEEngineTemplate<I, S, kind, IOF>::assembleFieldLumped( const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, ElementType type, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); AssembleLumpedTemplateHelper<kind>::call(*this, field, lumped, dof_id, dof_manager, type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct AssembleFieldMatrixHelper {}; #define ASSEMBLE_MATRIX(type) \ fem.template assembleFieldMatrix<Functor, type>( \ field_funct, matrix_id, dof_id, dof_manager, ghost_type) #define AKANTU_SPECIALIZE_ASSEMBLE_FIELD_MATRIX_HELPER(kind) \ template <> struct AssembleFieldMatrixHelper<kind> { \ template <template <ElementKind, class> class I, \ template <ElementKind> class S, ElementKind k, class IOF, \ class Functor> \ static void call(const FEEngineTemplate<I, S, k, IOF> & fem, \ Functor field_funct, const ID & matrix_id, \ const ID & dof_id, DOFManager & dof_manager, \ ElementType type, const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(ASSEMBLE_MATRIX, kind); \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_ASSEMBLE_FIELD_MATRIX_HELPER) #undef AKANTU_SPECIALIZE_ASSEMBLE_FIELD_MATRIX_HELPER #undef ASSEMBLE_MATRIX template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IOF> template <class Functor> void FEEngineTemplate<I, S, kind, IOF>::assembleFieldMatrix( Functor field_funct, const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager, ElementType type, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); AssembleFieldMatrixHelper<kind>::template call( *this, field_funct, matrix_id, dof_id, dof_manager, type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: assembleLumpedTemplate(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); this->template assembleLumpedRowSum<type>(field, lumped, dof_id, dof_manager, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j dV = * \int \rho \varphi_i dV @f$ */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: assembleLumpedRowSum(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt shapes_size = ElementClass<type>::getShapeSize(); UInt nb_degree_of_freedom = field.getNbComponent(); Array<Real> * field_times_shapes = new Array<Real>(0, shapes_size * nb_degree_of_freedom); shape_functions.template fieldTimesShapes<type>(field, *field_times_shapes, ghost_type); UInt nb_element = mesh.getNbElement(type, ghost_type); Array<Real> * int_field_times_shapes = new Array<Real>( nb_element, shapes_size * nb_degree_of_freedom, "inte_rho_x_shapes"); integrator.template integrate<type>( *field_times_shapes, *int_field_times_shapes, nb_degree_of_freedom * shapes_size, ghost_type, empty_filter); delete field_times_shapes; dof_manager.assembleElementalArrayToLumpedMatrix( dof_id, *int_field_times_shapes, lumped, type, ghost_type); delete int_field_times_shapes; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * @f$ \tilde{M}_{i} = c * M_{ii} = \int_{V_e} \rho dV @f$ */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> template <ElementType type> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>:: assembleLumpedDiagonalScaling(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); const ElementType & type_p1 = ElementClass<type>::getP1ElementType(); UInt nb_nodes_per_element_p1 = Mesh::getNbNodesPerElement(type_p1); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = integrator.template getIntegrationPoints<type>(ghost_type).cols(); UInt nb_degree_of_freedom = field.getNbComponent(); UInt nb_element = field.getSize() / nb_quadrature_points; Vector<Real> nodal_factor(nb_nodes_per_element); #define ASSIGN_WEIGHT_TO_NODES(corner, mid) \ { \ for (UInt n = 0; n < nb_nodes_per_element_p1; n++) \ nodal_factor(n) = corner; \ for (UInt n = nb_nodes_per_element_p1; n < nb_nodes_per_element; n++) \ nodal_factor(n) = mid; \ } if (type == _triangle_6) ASSIGN_WEIGHT_TO_NODES(1. / 12., 1. / 4.); if (type == _tetrahedron_10) ASSIGN_WEIGHT_TO_NODES(1. / 32., 7. / 48.); if (type == _quadrangle_8) ASSIGN_WEIGHT_TO_NODES( 3. / 76., 16. / 76.); /** coeff. derived by scaling * the diagonal terms of the corresponding * consistent mass computed with 3x3 gauss points; * coeff. are (1./36., 8./36.) for 2x2 gauss points */ if (type == _hexahedron_20) ASSIGN_WEIGHT_TO_NODES( 7. / 248., 16. / 248.); /** coeff. derived by scaling * the diagonal terms of the corresponding * consistent mass computed with 3x3x3 gauss points; * coeff. are (1./40., * 1./15.) for 2x2x2 gauss points */ if (type == _pentahedron_15) { // coefficients derived by scaling the diagonal terms of the corresponding // consistent mass computed with 8 gauss points; for (UInt n = 0; n < nb_nodes_per_element_p1; n++) nodal_factor(n) = 51. / 2358.; Real mid_triangle = 192. / 2358.; Real mid_quadrangle = 300. / 2358.; nodal_factor(6) = mid_triangle; nodal_factor(7) = mid_triangle; nodal_factor(8) = mid_triangle; nodal_factor(9) = mid_quadrangle; nodal_factor(10) = mid_quadrangle; nodal_factor(11) = mid_quadrangle; nodal_factor(12) = mid_triangle; nodal_factor(13) = mid_triangle; nodal_factor(14) = mid_triangle; } if (nb_element == 0) { AKANTU_DEBUG_OUT(); return; } #undef ASSIGN_WEIGHT_TO_NODES /// compute @f$ \int \rho dV = \rho V @f$ for each element Array<Real> * int_field = new Array<Real>(field.getSize(), nb_degree_of_freedom, "inte_rho_x"); integrator.template integrate<type>(field, *int_field, nb_degree_of_freedom, ghost_type, empty_filter); /// distribute the mass of the element to the nodes Array<Real> * lumped_per_node = new Array<Real>( nb_element, nb_degree_of_freedom * nb_nodes_per_element, "mass_per_node"); Array<Real>::const_vector_iterator int_field_it = int_field->begin(nb_degree_of_freedom); Array<Real>::matrix_iterator lumped_per_node_it = lumped_per_node->begin(nb_degree_of_freedom, nb_nodes_per_element); for (UInt e = 0; e < nb_element; ++e) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { Vector<Real> l = (*lumped_per_node_it)(n); l = *int_field_it; l *= nodal_factor(n); } ++int_field_it; ++lumped_per_node_it; } delete int_field; dof_manager.assembleElementalArrayToLumpedMatrix(dof_id, *lumped_per_node, lumped, type, ghost_type); delete lumped_per_node; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j dV = * \int \rho \varphi_i dV @f$ */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> template <class Functor, ElementType type> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::assembleFieldMatrix( Functor field_funct, const ID & matrix_id, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt shapes_size = ElementClass<type>::getShapeSize(); UInt nb_degree_of_freedom = dof_manager.getDOFs(dof_id).getNbComponent(); UInt lmat_size = nb_degree_of_freedom * shapes_size; UInt nb_element = mesh.getNbElement(type, ghost_type); // \int N * N so degree 2 * degree of N const UInt polynomial_degree = 2 * ElementClassProperty<type>::polynomial_degree; Matrix<Real> integration_points = integrator.template getIntegrationPoints<type, polynomial_degree>(); UInt nb_integration_points = integration_points.cols(); UInt vect_size = nb_integration_points * nb_element; Array<Real> shapes(0, shapes_size); shape_functions.template computeShapesOnIntegrationPoints<type>( mesh.getNodes(), integration_points, shapes, ghost_type); Array<Real> integration_points_pos(vect_size, mesh.getSpatialDimension()); shape_functions.template interpolateOnIntegrationPoints<type>( mesh.getNodes(), integration_points_pos, mesh.getSpatialDimension(), shapes, ghost_type, empty_filter); Array<Real> * modified_shapes = new Array<Real>(vect_size, lmat_size * nb_degree_of_freedom); modified_shapes->clear(); Array<Real> * local_mat = new Array<Real>(vect_size, lmat_size * lmat_size); Array<Real>::matrix_iterator mshapes_it = modified_shapes->begin(nb_degree_of_freedom, lmat_size); Array<Real>::const_vector_iterator shapes_it = shapes.begin(shapes_size); for (UInt q = 0; q < vect_size; ++q, ++mshapes_it, ++shapes_it) { for (UInt d = 0; d < nb_degree_of_freedom; ++d) { for (UInt s = 0; s < shapes_size; ++s) { (*mshapes_it)(d, s * nb_degree_of_freedom + d) = (*shapes_it)(s); } } } Array<Real> field(vect_size, nb_degree_of_freedom); Array<Real>::matrix_iterator field_c_it = field.begin_reinterpret( nb_degree_of_freedom, nb_integration_points, nb_element); Array<Real>::const_matrix_iterator pos_it = integration_points_pos.begin_reinterpret( mesh.getSpatialDimension(), nb_integration_points, nb_element); Element el; el.type = type, el.ghost_type = ghost_type; for (el.element = 0; el.element < nb_element; ++el.element, ++field_c_it, ++pos_it) { field_funct(*field_c_it, el, *pos_it); } mshapes_it = modified_shapes->begin(nb_degree_of_freedom, lmat_size); Array<Real>::matrix_iterator lmat = local_mat->begin(lmat_size, lmat_size); Array<Real>::const_vector_iterator field_it = field.begin_reinterpret(nb_degree_of_freedom, field.getSize()); for (UInt q = 0; q < vect_size; ++q, ++lmat, ++mshapes_it, ++field_it) { const Vector<Real> & rho = *field_it; const Matrix<Real> & N = *mshapes_it; Matrix<Real> & mat = *lmat; Matrix<Real> Nt = N.transpose(); for (UInt d = 0; d < Nt.cols(); ++d) { Nt(d) *= rho(d); } mat.mul<false, false>(Nt, N); } delete modified_shapes; Array<Real> * int_field_times_shapes = new Array<Real>(nb_element, lmat_size * lmat_size, "inte_rho_x_shapes"); this->integrator.template integrate<type, polynomial_degree>( *local_mat, *int_field_times_shapes, lmat_size * lmat_size, ghost_type); delete local_mat; dof_manager.assembleElementalMatricesToMatrix( matrix_id, dof_id, *int_field_times_shapes, type, ghost_type); delete int_field_times_shapes; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct InverseMapHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) const Vector<Real> & real_coords, __attribute__((unused)) UInt element, __attribute__((unused)) const ElementType & type, __attribute__((unused)) Vector<Real> & natural_coords, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define INVERSE_MAP(type) \ shape_functions.template inverseMap<type>(real_coords, element, \ natural_coords, ghost_type); #define AKANTU_SPECIALIZE_INVERSE_MAP_HELPER(kind) \ template <> struct InverseMapHelper<kind> { \ template <class S> \ static void call(const S & shape_functions, \ const Vector<Real> & real_coords, UInt element, \ const ElementType & type, Vector<Real> & natural_coords, \ const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(INVERSE_MAP, kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_INVERSE_MAP_HELPER, AKANTU_FE_ENGINE_LIST_INVERSE_MAP) #undef AKANTU_SPECIALIZE_INVERSE_MAP_HELPER #undef INVERSE_MAP template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::inverseMap( const Vector<Real> & real_coords, UInt element, const ElementType & type, Vector<Real> & natural_coords, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); InverseMapHelper<kind>::call(shape_functions, real_coords, element, type, natural_coords, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct ContainsHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) const Vector<Real> & real_coords, __attribute__((unused)) UInt element, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define CONTAINS(type) \ contain = shape_functions.template contains<type>(real_coords, element, \ ghost_type); #define AKANTU_SPECIALIZE_CONTAINS_HELPER(kind) \ template <> struct ContainsHelper<kind> { \ template <template <ElementKind> class S, ElementKind k> \ static bool call(const S<k> & shape_functions, \ const Vector<Real> & real_coords, UInt element, \ const ElementType & type, const GhostType & ghost_type) { \ bool contain = false; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(CONTAINS, kind); \ return contain; \ } \ }; AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_CONTAINS_HELPER, AKANTU_FE_ENGINE_LIST_CONTAINS) #undef AKANTU_SPECIALIZE_CONTAINS_HELPER #undef CONTAINS template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline bool FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::contains( const Vector<Real> & real_coords, UInt element, const ElementType & type, const GhostType & ghost_type) const { return ContainsHelper<kind>::call(shape_functions, real_coords, element, type, ghost_type); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct ComputeShapesHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) const Vector<Real> & real_coords, __attribute__((unused)) UInt element, __attribute__((unused)) const ElementType type, __attribute__((unused)) Vector<Real> & shapes, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define COMPUTE_SHAPES(type) \ shape_functions.template computeShapes<type>(real_coords, element, shapes, \ ghost_type); #define AKANTU_SPECIALIZE_COMPUTE_SHAPES_HELPER(kind) \ template <> struct ComputeShapesHelper<kind> { \ template <class S> \ static void call(const S & shape_functions, \ const Vector<Real> & real_coords, UInt element, \ const ElementType type, Vector<Real> & shapes, \ const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_SHAPES, kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_COMPUTE_SHAPES_HELPER, AKANTU_FE_ENGINE_LIST_COMPUTE_SHAPES) #undef AKANTU_SPECIALIZE_COMPUTE_SHAPES_HELPER #undef COMPUTE_SHAPES template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeShapes( const Vector<Real> & real_coords, UInt element, const ElementType & type, Vector<Real> & shapes, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); ComputeShapesHelper<kind>::call(shape_functions, real_coords, element, type, shapes, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct ComputeShapeDerivativesHelper { template <class S> static void call(__attribute__((unused)) const S & shape_functions, __attribute__((unused)) const Vector<Real> & real_coords, __attribute__((unused)) UInt element, __attribute__((unused)) const ElementType type, __attribute__((unused)) Matrix<Real> & shape_derivatives, __attribute__((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define COMPUTE_SHAPE_DERIVATIVES(type) \ Matrix<Real> coords_mat(real_coords.storage(), shape_derivatives.rows(), 1); \ Tensor3<Real> shapesd_tensor(shape_derivatives.storage(), \ shape_derivatives.rows(), \ shape_derivatives.cols(), 1); \ shape_functions.template computeShapeDerivatives<type>( \ coords_mat, element, shapesd_tensor, ghost_type); #define AKANTU_SPECIALIZE_COMPUTE_SHAPE_DERIVATIVES_HELPER(kind) \ template <> struct ComputeShapeDerivativesHelper<kind> { \ template <class S> \ static void call(const S & shape_functions, \ const Vector<Real> & real_coords, UInt element, \ const ElementType type, Matrix<Real> & shape_derivatives, \ const GhostType & ghost_type) { \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(COMPUTE_SHAPE_DERIVATIVES, kind); \ } \ }; AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_COMPUTE_SHAPE_DERIVATIVES_HELPER, AKANTU_FE_ENGINE_LIST_COMPUTE_SHAPES_DERIVATIVES) #undef AKANTU_SPECIALIZE_COMPUTE_SHAPE_DERIVATIVES_HELPER #undef COMPUTE_SHAPE_DERIVATIVES template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::computeShapeDerivatives( const Vector<Real> & real_coords, UInt element, const ElementType & type, Matrix<Real> & shape_derivatives, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); ComputeShapeDerivativesHelper<kind>::call(shape_functions, real_coords, element, type, shape_derivatives, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct GetNbIntegrationPointsHelper {}; #define GET_NB_INTEGRATION_POINTS(type) \ nb_quad_points = integrator.template getNbIntegrationPoints<type>(ghost_type); #define AKANTU_SPECIALIZE_GET_NB_INTEGRATION_POINTS_HELPER(kind) \ template <> struct GetNbIntegrationPointsHelper<kind> { \ template <template <ElementKind, class> class I, ElementKind k, class IOF> \ static UInt call(const I<k, IOF> & integrator, const ElementType type, \ const GhostType & ghost_type) { \ UInt nb_quad_points = 0; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_NB_INTEGRATION_POINTS, kind); \ return nb_quad_points; \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_GET_NB_INTEGRATION_POINTS_HELPER) #undef AKANTU_SPECIALIZE_GET_NB_INTEGRATION_POINTS_HELPER #undef GET_NB_INTEGRATION template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline UInt FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getNbIntegrationPoints( const ElementType & type, const GhostType & ghost_type) const { return GetNbIntegrationPointsHelper<kind>::call(integrator, type, ghost_type); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct GetShapesHelper {}; #define GET_SHAPES(type) ret = &(shape_functions.getShapes(type, ghost_type)); #define AKANTU_SPECIALIZE_GET_SHAPES_HELPER(kind) \ template <> struct GetShapesHelper<kind> { \ template <class S> \ static const Array<Real> & call(const S & shape_functions, \ const ElementType type, \ const GhostType & ghost_type) { \ const Array<Real> * ret = NULL; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_SHAPES, kind); \ return *ret; \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_GET_SHAPES_HELPER) #undef AKANTU_SPECIALIZE_GET_SHAPES_HELPER #undef GET_SHAPES template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline const Array<Real> & FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getShapes( const ElementType & type, const GhostType & ghost_type, __attribute__((unused)) UInt id) const { return GetShapesHelper<kind>::call(shape_functions, type, ghost_type); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct GetShapesDerivativesHelper { template <template <ElementKind> class S, ElementKind k> static const Array<Real> & call(__attribute__((unused)) const S<k> & shape_functions, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type, __attribute__((unused)) UInt id) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; #define GET_SHAPES_DERIVATIVES(type) \ ret = &(shape_functions.getShapesDerivatives(type, ghost_type)); #define AKANTU_SPECIALIZE_GET_SHAPES_DERIVATIVES_HELPER(kind) \ template <> struct GetShapesDerivativesHelper<kind> { \ template <template <ElementKind> class S, ElementKind k> \ static const Array<Real> & \ call(const S<k> & shape_functions, const ElementType type, \ const GhostType & ghost_type, __attribute__((unused)) UInt id) { \ const Array<Real> * ret = NULL; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_SHAPES_DERIVATIVES, kind); \ return *ret; \ } \ }; AKANTU_BOOST_ALL_KIND_LIST(AKANTU_SPECIALIZE_GET_SHAPES_DERIVATIVES_HELPER, AKANTU_FE_ENGINE_LIST_GET_SHAPES_DERIVATIVES) #undef AKANTU_SPECIALIZE_GET_SHAPE_DERIVATIVES_HELPER #undef GET_SHAPES_DERIVATIVES template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline const Array<Real> & FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getShapesDerivatives( const ElementType & type, const GhostType & ghost_type, __attribute__((unused)) UInt id) const { return GetShapesDerivativesHelper<kind>::call(shape_functions, type, ghost_type, id); } /* -------------------------------------------------------------------------- */ /** * Helper class to be able to write a partial specialization on the element kind */ template <ElementKind kind> struct GetIntegrationPointsHelper {}; #define GET_INTEGRATION_POINTS(type) \ ret = &(integrator.template getIntegrationPoints<type>(ghost_type)); #define AKANTU_SPECIALIZE_GET_INTEGRATION_POINTS_HELPER(kind) \ template <> struct GetIntegrationPointsHelper<kind> { \ template <template <ElementKind, class> class I, ElementKind k, class IOF> \ static const Matrix<Real> & call(const I<k, IOF> & integrator, \ const ElementType type, \ const GhostType & ghost_type) { \ const Matrix<Real> * ret = NULL; \ AKANTU_BOOST_KIND_ELEMENT_SWITCH(GET_INTEGRATION_POINTS, kind); \ return *ret; \ } \ }; AKANTU_BOOST_ALL_KIND(AKANTU_SPECIALIZE_GET_INTEGRATION_POINTS_HELPER) #undef AKANTU_SPECIALIZE_GET_INTEGRATION_POINTS_HELPER #undef GET_INTEGRATION_POINTS template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> inline const Matrix<Real> & FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getIntegrationPoints( const ElementType & type, const GhostType & ghost_type) const { return GetIntegrationPointsHelper<kind>::call(integrator, type, ghost_type); } /* -------------------------------------------------------------------------- */ template <template <ElementKind, class> class I, template <ElementKind> class S, ElementKind kind, class IntegrationOrderFunctor> void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::printself( std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "FEEngineTemplate [" << std::endl; stream << space << " + parent [" << std::endl; FEEngine::printself(stream, indent + 3); stream << space << " ]" << std::endl; stream << space << " + shape functions [" << std::endl; shape_functions.printself(stream, indent + 3); stream << space << " ]" << std::endl; stream << space << " + integrator [" << std::endl; integrator.printself(stream, indent + 3); stream << space << " ]" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ } // akantu #include "integrator_gauss.hh" #include "shape_lagrange.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template <> template <> inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>:: assembleLumpedTemplate<_triangle_6>(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { assembleLumpedDiagonalScaling<_triangle_6>(field, lumped, dof_id, dof_manager, ghost_type); } /* -------------------------------------------------------------------------- */ template <> template <> inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular, DefaultIntegrationOrderFunctor>:: assembleLumpedTemplate<_tetrahedron_10>( const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { assembleLumpedDiagonalScaling<_tetrahedron_10>(field, lumped, dof_id, dof_manager, ghost_type); } /* -------------------------------------------------------------------------- */ template <> template <> inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>:: assembleLumpedTemplate<_quadrangle_8>(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { assembleLumpedDiagonalScaling<_quadrangle_8>(field, lumped, dof_id, dof_manager, ghost_type); } /* -------------------------------------------------------------------------- */ template <> template <> inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular>:: assembleLumpedTemplate<_hexahedron_20>(const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { assembleLumpedDiagonalScaling<_hexahedron_20>(field, lumped, dof_id, dof_manager, ghost_type); } /* -------------------------------------------------------------------------- */ template <> template <> inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular, DefaultIntegrationOrderFunctor>:: assembleLumpedTemplate<_pentahedron_15>( const Array<Real> & field, const ID & lumped, const ID & dof_id, DOFManager & dof_manager, const GhostType & ghost_type) const { assembleLumpedDiagonalScaling<_pentahedron_15>(field, lumped, dof_id, dof_manager, ghost_type); } /* -------------------------------------------------------------------------- */ template <> template <> inline void FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular, DefaultIntegrationOrderFunctor>:: computeNormalsOnIntegrationPoints<_point_1>( const Array<Real> &, Array<Real> & normal, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(mesh.getSpatialDimension() == 1, "Mesh dimension must be 1 to compute normals on points!"); const ElementType type = _point_1; UInt spatial_dimension = mesh.getSpatialDimension(); // UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_points = getNbIntegrationPoints(type, ghost_type); UInt nb_element = mesh.getConnectivity(type, ghost_type).getSize(); normal.resize(nb_element * nb_points); Array<Real>::matrix_iterator normals_on_quad = normal.begin_reinterpret(spatial_dimension, nb_points, nb_element); const Array<std::vector<Element>> & segments = mesh.getElementToSubelement(type, ghost_type); const Array<Real> & coords = mesh.getNodes(); const Mesh * mesh_segment; if (mesh.isMeshFacets()) mesh_segment = &(mesh.getMeshParent()); else mesh_segment = &mesh; for (UInt elem = 0; elem < nb_element; ++elem) { UInt nb_segment = segments(elem).size(); AKANTU_DEBUG_ASSERT( nb_segment > 0, "Impossible to compute a normal on a point connected to 0 segments"); Real normal_value = 1; if (nb_segment == 1) { const Element & segment = segments(elem)[0]; const Array<UInt> & segment_connectivity = mesh_segment->getConnectivity(segment.type, segment.ghost_type); // const Vector<UInt> & segment_points = // segment_connectivity.begin(Mesh::getNbNodesPerElement(segment.type))[segment.element]; Real difference; if (segment_connectivity(0) == elem) { difference = coords(elem) - coords(segment_connectivity(1)); } else { difference = coords(elem) - coords(segment_connectivity(0)); } normal_value = difference / std::abs(difference); } for (UInt n(0); n < nb_points; ++n) { (*normals_on_quad)(0, n) = normal_value; } ++normals_on_quad; } AKANTU_DEBUG_OUT(); } } // akantu diff --git a/src/io/dumper/dumpable_iohelper.hh b/src/io/dumper/dumpable_iohelper.hh index db0a8ee8c..1ffe18fd8 100644 --- a/src/io/dumper/dumpable_iohelper.hh +++ b/src/io/dumper/dumpable_iohelper.hh @@ -1,195 +1,196 @@ /** * @file dumpable_iohelper.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Jan 06 2015 * @date last modification: Thu Nov 19 2015 * * @brief Interface for object who wants to dump themselves * * @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 "dumper_iohelper.hh" +/* -------------------------------------------------------------------------- */ +#include <set> /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_DUMPABLE_IOHELPER_HH__ #define __AKANTU_DUMPABLE_IOHELPER_HH__ /* -------------------------------------------------------------------------- */ -#include "dumper_iohelper.hh" -#include <set> - namespace akantu { class Dumpable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Dumpable(); virtual ~Dumpable(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// create a new dumper (of templated type T) and register it under /// dumper_name. file_name is used for construction of T. is default states if /// this dumper is the default dumper. template<class T> inline void registerDumper(const std::string & dumper_name, const std::string & file_name = "", const bool is_default = false); /// register an externally created dumper void registerExternalDumper(DumperIOHelper & dumper, const std::string & dumper_name, const bool is_default = false); /// register a mesh to the default dumper void addDumpMesh(const Mesh & mesh, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); /// register a mesh to the default identified by its name void addDumpMeshToDumper(const std::string & dumper_name, const Mesh & mesh, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); /// register a filtered mesh as the default dumper void addDumpFilteredMesh(const Mesh & mesh, const ElementTypeMapArray<UInt> & elements_filter, const Array<UInt> & nodes_filter, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); /// register a filtered mesh and provides a name void addDumpFilteredMeshToDumper(const std::string & dumper_name, const Mesh & mesh, const ElementTypeMapArray<UInt> & elements_filter, const Array<UInt> & nodes_filter, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); /// to implement virtual void addDumpField(const std::string & field_id); /// to implement virtual void addDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id); /// add a field virtual void addDumpFieldExternal(const std::string & field_id, dumper::Field * field); virtual void addDumpFieldExternalToDumper(const std::string & dumper_name, const std::string & field_id, dumper::Field * field); template<typename T> inline void addDumpFieldExternal(const std::string & field_id, const Array<T> & field); template<typename T> inline void addDumpFieldExternalToDumper(const std::string & dumper_name, const std::string & field_id, const Array<T> & field); template<typename T> inline void addDumpFieldExternal(const std::string & field_id, const ElementTypeMapArray<T> & field, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); template<typename T> inline void addDumpFieldExternalToDumper(const std::string & dumper_name, const std::string & field_id, const ElementTypeMapArray<T> & field, UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & element_kind = _ek_not_defined); void removeDumpField(const std::string & field_id); void removeDumpFieldFromDumper(const std::string & dumper_name, const std::string & field_id); virtual void addDumpFieldVector(const std::string & field_id); virtual void addDumpFieldVectorToDumper(const std::string & dumper_name, const std::string & field_id); virtual void addDumpFieldTensor(const std::string & field_id); virtual void addDumpFieldTensorToDumper(const std::string & dumper_name, const std::string & field_id); void setDirectory(const std::string & directory); void setDirectoryToDumper(const std::string & dumper_name, const std::string & directory); void setBaseName(const std::string & basename); void setBaseNameToDumper(const std::string & dumper_name, const std::string & basename); void setTimeStepToDumper(Real time_step); void setTimeStepToDumper(const std::string & dumper_name, Real time_step); void setTextModeToDumper(const std::string & dumper_name); void setTextModeToDumper(); virtual void dump(); virtual void dump(UInt step); virtual void dump(Real time, UInt step); virtual void dump(const std::string & dumper_name); virtual void dump(const std::string & dumper_name, UInt step); virtual void dump(const std::string & dumper_name, Real time, UInt step); public: void internalAddDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id, dumper::Field * field); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: DumperIOHelper & getDumper(); DumperIOHelper & getDumper(const std::string & dumper_name); template<class T> T & getDumper(const std::string & dumper_name); std::string getDefaultDumperName() const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: typedef std::map<std::string, DumperIOHelper *> DumperMap; typedef std::set<std::string> DumperSet; DumperMap dumpers; std::string default_dumper; }; } // akantu #endif /* __AKANTU_DUMPABLE_IOHELPER_HH__ */ diff --git a/src/mesh/element_type_map_tmpl.hh b/src/mesh/element_type_map_tmpl.hh index cac4ae88c..6a6e038e3 100644 --- a/src/mesh/element_type_map_tmpl.hh +++ b/src/mesh/element_type_map_tmpl.hh @@ -1,623 +1,623 @@ /** * @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" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_TYPE_MAP_TMPL_HH__ #define __AKANTU_ELEMENT_TYPE_MAP_TMPL_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ /* ElementTypeMap */ /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline std::string ElementTypeMap<Stored, SupportType>::printType(const SupportType & type, const GhostType & ghost_type) { std::stringstream sstr; sstr << "(" << ghost_type << ":" << type << ")"; return sstr.str(); } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline bool ElementTypeMap<Stored, SupportType>::exists( const SupportType & type, const GhostType & ghost_type) const { return this->getData(ghost_type).find(type) != this->getData(ghost_type).end(); } /* -------------------------------------------------------------------------- */ template <class Stored, typename SupportType> inline const Stored & ElementTypeMap<Stored, SupportType>:: operator()(const SupportType & type, const GhostType & ghost_type) const { 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; 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) << 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; DataMap & data = this->getData(gt); typename DataMap::const_iterator it; for (it = data.begin(); it != data.end(); ++it) { dealloc(it->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; DataMap & data = this->getData(gt); typename DataMap::const_iterator it; for (it = data.begin(); it != data.end(); ++it) { it->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); if (renumbering.getSize() == 0) continue; Array<T> & vect = this->operator()(type, gt); UInt 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 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 ElementKind & element_kind = _ek_regular); UInt size(const ElementType & type) const override; 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, _all_dimensions), - 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())); + 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, 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 b3a7e9e17..18afdb476 100644 --- a/src/mesh/group_manager.cc +++ b/src/mesh/group_manager.cc @@ -1,1029 +1,1030 @@ /** * @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_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"); } /* -------------------------------------------------------------------------- */ //// \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) { 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 = element_dimension, + 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, _nb_component = element_dimension, + seen_elements.initialize(mesh, _spatial_dimension = element_dimension, _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); 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( 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 9caf83c86..d4b7dc1a3 100644 --- a/src/mesh/group_manager.hh +++ b/src/mesh/group_manager.hh @@ -1,295 +1,294 @@ /** * @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; - } +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 *> ; + 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, std::string cluster_name_prefix = "cluster", const ClusteringFilter & filter = ClusteringFilter(), Mesh * mesh_facets = nullptr); /// 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> - inline dumper::Field * createElementalField( + 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> - inline dumper::Field * createElementalField( + 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> - inline dumper::Field * - createElementalField(const ElementTypeMapArray<T> & field, - const std::string & group_name, UInt spatial_dimension, - const ElementKind & kind, - ElementTypeMap<UInt> nb_data_per_elem); + 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> - inline dumper::Field * createNodalField(const ftype<type, flag> * field, - const std::string & group_name, - UInt padding_size = 0); + 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> - inline dumper::Field * - createStridedNodalField(const ftype<type, flag> * field, - const std::string & group_name, UInt size, - UInt stride, UInt padding_size); + 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; } -} // akantu +} // namespace akantu #endif /* __AKANTU_GROUP_MANAGER_HH__ */ diff --git a/src/mesh_utils/mesh_utils.cc b/src/mesh_utils/mesh_utils.cc index 78771cdb7..61ee0a24a 100644 --- a/src/mesh_utils/mesh_utils.cc +++ b/src/mesh_utils/mesh_utils.cc @@ -1,2346 +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::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); + 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); + 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"); } } } } /* -------------------------------------------------------------------------- */ 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/model/common/non_local_toolbox/non_local_neighborhood.hh b/src/model/common/non_local_toolbox/non_local_neighborhood.hh index 0020bf03b..cff16242e 100644 --- a/src/model/common/non_local_toolbox/non_local_neighborhood.hh +++ b/src/model/common/non_local_toolbox/non_local_neighborhood.hh @@ -1,131 +1,131 @@ /** * @file non_local_neighborhood.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Wed Nov 25 2015 * * @brief Non-local neighborhood for non-local averaging based on * weight 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/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LOCAL_NEIGHBORHOOD_HH__ #define __AKANTU_NON_LOCAL_NEIGHBORHOOD_HH__ /* -------------------------------------------------------------------------- */ #include "base_weight_function.hh" #include "non_local_neighborhood_base.hh" #include "parsable.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class NonLocalManager; class BaseWeightFunction; } // namespace akantu namespace akantu { template <class WeightFunction = BaseWeightFunction> class NonLocalNeighborhood : public NonLocalNeighborhoodBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NonLocalNeighborhood(NonLocalManager & manager, const ElementTypeMapReal & quad_coordinates, const ID & id = "neighborhood", const MemoryID & memory_id = 0); virtual ~NonLocalNeighborhood(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// compute the weights for non-local averaging void computeWeights(); /// save the pair of weights in a file - void saveWeights(const std::string & filename) const; + void saveWeights(const std::string & filename) const override; /// compute the non-local counter part for a given element type map // compute the non-local counter part for a given element type map void weightedAverageOnNeighbours(const ElementTypeMapReal & to_accumulate, ElementTypeMapReal & accumulated, UInt nb_degree_of_freedom, const GhostType & ghost_type2) const override; /// update the weights based on the weight function void updateWeights(); /// register a new non-local variable in the neighborhood //void registerNonLocalVariable(const ID & id); protected: 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; /* -------------------------------------------------------------------------- */ /* Accessor */ /* -------------------------------------------------------------------------- */ AKANTU_GET_MACRO(NonLocalManager, non_local_manager, const NonLocalManager &); AKANTU_GET_MACRO_NOT_CONST(NonLocalManager, non_local_manager, NonLocalManager &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// Pointer to non-local manager class NonLocalManager & non_local_manager; /// the weights associated to the pairs std::array<std::unique_ptr<Array<Real>>, 2> pair_weight; /// weight function std::unique_ptr<WeightFunction> weight_function; }; } // namespace akantu /* -------------------------------------------------------------------------- */ /* Implementation of template functions */ /* -------------------------------------------------------------------------- */ #include "non_local_neighborhood_tmpl.hh" /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "non_local_neighborhood_inline_impl.cc" #endif /* __AKANTU_NON_LOCAL_NEIGHBORHOOD_HH__ */ diff --git a/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh b/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh index 85cd6725b..7c02c8483 100644 --- a/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh +++ b/src/model/common/non_local_toolbox/non_local_neighborhood_base.hh @@ -1,122 +1,125 @@ /** * @file non_local_neighborhood_base.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Wed Nov 25 2015 * * @brief Non-local neighborhood base class * * @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 "neighborhood_base.hh" #include "parsable.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LOCAL_NEIGHBORHOOD_BASE_HH__ #define __AKANTU_NON_LOCAL_NEIGHBORHOOD_BASE_HH__ namespace akantu { class Model; } /* -------------------------------------------------------------------------- */ namespace akantu { class NonLocalNeighborhoodBase : public NeighborhoodBase, public Parsable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NonLocalNeighborhoodBase(Model & model, const ElementTypeMapReal & quad_coordinates, const ID & id = "non_local_neighborhood", const MemoryID & memory_id = 0); virtual ~NonLocalNeighborhoodBase(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// create grid synchronizer and exchange ghost cells void createGridSynchronizer() override; /// compute weights, for instance needed for non-local damage computation virtual void computeWeights(){}; // compute the non-local counter part for a given element type map virtual void weightedAverageOnNeighbours(const ElementTypeMapReal & to_accumulate, ElementTypeMapReal & accumulated, UInt nb_degree_of_freedom, const GhostType & ghost_type2) const = 0; /// update the weights for the non-local averaging virtual void updateWeights() = 0; + /// update the weights for the non-local averaging + virtual void saveWeights(const std::string & ) const { AKANTU_DEBUG_TO_IMPLEMENT(); } + /// register a new non-local variable in the neighborhood virtual void registerNonLocalVariable(const ID & id); /// clean up the unneccessary ghosts void cleanupExtraGhostElements(std::set<Element> & relevant_ghost_elements); protected: /// create the grid void createGrid(); /* -------------------------------------------------------------------------- */ /* DataAccessor inherited members */ /* -------------------------------------------------------------------------- */ public: 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 {} /* -------------------------------------------------------------------------- */ /* Accessors */ /* -------------------------------------------------------------------------- */ public: AKANTU_GET_MACRO(NonLocalVariables, non_local_variables, const std::set<ID> &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// list of non-local variables associated to the neighborhood std::set<ID> non_local_variables; }; } // namespace akantu #endif /* __AKANTU_NON_LOCAL_NEIGHBORHOOD_BASE_HH__ */ diff --git a/src/model/solid_mechanics/material.hh b/src/model/solid_mechanics/material.hh index 84b66a2ef..0969d76de 100644 --- a/src/model/solid_mechanics/material.hh +++ b/src/model/solid_mechanics/material.hh @@ -1,653 +1,680 @@ /** * @file material.hh * * @author Daniel Pino Muñoz <daniel.pinomunoz@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: Wed Nov 25 2015 * * @brief Mother class for all materials * * @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_factory.hh" #include "aka_voigthelper.hh" #include "data_accessor.hh" #include "integration_point.hh" #include "parsable.hh" #include "parser.hh" /* -------------------------------------------------------------------------- */ #include "internal_field.hh" #include "random_internal_field.hh" /* -------------------------------------------------------------------------- */ #include "mesh_events.hh" #include "solid_mechanics_model_event_handler.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_HH__ #define __AKANTU_MATERIAL_HH__ /* -------------------------------------------------------------------------- */ namespace akantu { class Model; class SolidMechanicsModel; } // namespace akantu namespace akantu { /** * Interface of all materials * Prerequisites for a new material * - inherit from this class * - implement the following methods: * \code * virtual Real getStableTimeStep(Real h, const Element & element = * ElementNull); * * virtual void computeStress(ElementType el_type, * GhostType ghost_type = _not_ghost); * * virtual void computeTangentStiffness(const ElementType & el_type, * Array<Real> & tangent_matrix, * GhostType ghost_type = _not_ghost); * \endcode * */ class Material : public Memory, public DataAccessor<Element>, public Parsable, public MeshEventHandler, protected SolidMechanicsModelEventHandler { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: #if __cplusplus > 199711L Material(const Material & mat) = delete; Material & operator=(const Material & mat) = delete; #endif /// Initialize material with defaults Material(SolidMechanicsModel & model, const ID & id = ""); /// Initialize material with custom mesh & fe_engine Material(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id = ""); /// Destructor virtual ~Material(); protected: void initialize(); /* ------------------------------------------------------------------------ */ /* Function that materials can/should reimplement */ /* ------------------------------------------------------------------------ */ protected: /// constitutive law virtual void computeStress(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the tangent stiffness matrix virtual void computeTangentModuli(__attribute__((unused)) const ElementType & el_type, __attribute__((unused)) Array<Real> & tangent_matrix, __attribute__((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the potential energy virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the potential energy for an element virtual void computePotentialEnergyByElement(__attribute__((unused)) ElementType type, __attribute__((unused)) UInt index, __attribute__((unused)) Vector<Real> & epot_on_quad_points) { AKANTU_DEBUG_TO_IMPLEMENT(); } virtual void updateEnergies(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) {} virtual void updateEnergiesAfterDamage(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) {} /// set the material to steady state (to be implemented for materials that /// need it) virtual void setToSteadyState(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) {} /// function called to update the internal parameters when the modifiable /// parameters are modified virtual void updateInternalParameters() {} public: /// extrapolate internal values virtual void extrapolateInternal(const ID & id, const Element & element, const Matrix<Real> & points, Matrix<Real> & extrapolated); /// compute the p-wave speed in the material virtual Real getPushWaveSpeed(__attribute__((unused)) const Element & element) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the s-wave speed in the material virtual Real getShearWaveSpeed(__attribute__((unused)) const Element & element) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// get a material celerity to compute the stable time step (default: is the /// push wave speed) virtual Real getCelerity(const Element & element) const { return getPushWaveSpeed(element); } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: template <typename T> void registerInternal(__attribute__((unused)) InternalField<T> & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); } template <typename T> void unregisterInternal(__attribute__((unused)) InternalField<T> & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// initialize the material computed parameter virtual void initMaterial(); /// compute the residual for this material // virtual void updateResidual(GhostType ghost_type = _not_ghost); /// assemble the residual for this material virtual void assembleInternalForces(GhostType ghost_type); /// save the stress in the previous_stress if needed virtual void savePreviousState(); /// compute the stresses for this material virtual void computeAllStresses(GhostType ghost_type = _not_ghost); virtual void computeAllStressesFromTangentModuli(GhostType ghost_type = _not_ghost); virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost); /// set material to steady state void setToSteadyState(GhostType ghost_type = _not_ghost); /// compute the stiffness matrix virtual void assembleStiffnessMatrix(GhostType ghost_type); /// add an element to the local mesh filter inline UInt addElement(const ElementType & type, UInt element, const GhostType & ghost_type); /// add many elements at once void addElements(const Array<Element> & elements_to_add); /// remove many element at once void removeElements(const Array<Element> & elements_to_remove); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /** * interpolate stress on given positions for each element by means * of a geometrical interpolation on quadrature points */ void interpolateStress(ElementTypeMapArray<Real> & result, const GhostType ghost_type = _not_ghost); /** * interpolate stress on given positions for each element by means * of a geometrical interpolation on quadrature points and store the * results per facet */ void interpolateStressOnFacets(ElementTypeMapArray<Real> & result, ElementTypeMapArray<Real> & by_elem_result, const GhostType ghost_type = _not_ghost); /** * function to initialize the elemental field interpolation * function by inverting the quadrature points' coordinates */ void initElementalFieldInterpolation( const ElementTypeMapArray<Real> & interpolation_points_coordinates); /* ------------------------------------------------------------------------ */ /* Common part */ /* ------------------------------------------------------------------------ */ protected: /* ------------------------------------------------------------------------ */ inline UInt getTangentStiffnessVoigtSize(UInt spatial_dimension) const; /// compute the potential energy by element void computePotentialEnergyByElements(); /// resize the intenals arrays virtual void resizeInternals(); /* ------------------------------------------------------------------------ */ /* Finite deformation functions */ /* This functions area implementing what is described in the paper of Bathe */ /* et al, in IJNME, Finite Element Formulations For Large Deformation */ /* Dynamic Analysis, Vol 9, 353-386, 1975 */ /* ------------------------------------------------------------------------ */ protected: /// assemble the residual template <UInt dim> void assembleInternalForces(GhostType ghost_type); /// Computation of Cauchy stress tensor in the case of finite deformation from /// the 2nd Piola-Kirchhoff for a given element type template <UInt dim> void computeCauchyStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// Computation the Cauchy stress the 2nd Piola-Kirchhoff and the deformation /// gradient template <UInt dim> inline void computeCauchyStressOnQuad(const Matrix<Real> & F, const Matrix<Real> & S, Matrix<Real> & cauchy, const Real & C33 = 1.0) const; template <UInt dim> void computeAllStressesFromTangentModuli(const ElementType & type, GhostType ghost_type); template <UInt dim> void assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type); /// assembling in finite deformation template <UInt dim> void assembleStiffnessMatrixNL(const ElementType & type, GhostType ghost_type); template <UInt dim> void assembleStiffnessMatrixL2(const ElementType & type, GhostType ghost_type); /// Size of the Stress matrix for the case of finite deformation see: Bathe et /// al, IJNME, Vol 9, 353-386, 1975 inline UInt getCauchyStressMatrixSize(UInt spatial_dimension) const; /// Sets the stress matrix according to Bathe et al, IJNME, Vol 9, 353-386, /// 1975 template <UInt dim> inline void setCauchyStressMatrix(const Matrix<Real> & S_t, Matrix<Real> & sigma); /// write the stress tensor in the Voigt notation. template <UInt dim> inline void setCauchyStressArray(const Matrix<Real> & S_t, Matrix<Real> & sigma_voight); /* ------------------------------------------------------------------------ */ /* Conversion functions */ /* ------------------------------------------------------------------------ */ public: template <UInt dim> static inline void gradUToF(const Matrix<Real> & grad_u, Matrix<Real> & F); static inline void rightCauchy(const Matrix<Real> & F, Matrix<Real> & C); static inline void leftCauchy(const Matrix<Real> & F, Matrix<Real> & B); template <UInt dim> static inline void gradUToEpsilon(const Matrix<Real> & grad_u, Matrix<Real> & epsilon); template <UInt dim> static inline void gradUToGreenStrain(const Matrix<Real> & grad_u, Matrix<Real> & epsilon); static inline Real stressToVonMises(const Matrix<Real> & stress); protected: /// converts global element to local element inline Element convertToLocalElement(const Element & global_element) const; /// converts local element to global element inline Element convertToGlobalElement(const Element & local_element) const; /// converts global quadrature point to local quadrature point inline IntegrationPoint convertToLocalPoint(const IntegrationPoint & global_point) const; /// converts local quadrature point to global quadrature point inline IntegrationPoint convertToGlobalPoint(const IntegrationPoint & local_point) const; /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: virtual inline UInt getNbData(const Array<Element> & elements, const SynchronizationTag & tag) const; virtual inline void packData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) const; virtual inline void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag); template <typename T> inline void packElementDataHelper(const ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer, const Array<Element> & elements, const ID & fem_id = ID()) const; template <typename T> inline void unpackElementDataHelper(ElementTypeMapArray<T> & data_to_unpack, CommunicationBuffer & buffer, const Array<Element> & elements, const ID & fem_id = ID()); /* ------------------------------------------------------------------------ */ /* MeshEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ virtual void onNodesAdded(const Array<UInt> &, const NewNodesEvent &){}; virtual void onNodesRemoved(const Array<UInt> &, const Array<UInt> &, const RemovedNodesEvent &){}; virtual void onElementsAdded(const Array<Element> & element_list, const NewElementsEvent & event); virtual void onElementsRemoved(const Array<Element> & element_list, const ElementTypeMapArray<UInt> & new_numbering, const RemovedElementsEvent & event); virtual void onElementsChanged(const Array<Element> &, const Array<Element> &, const ElementTypeMapArray<UInt> &, const ChangedElementsEvent &){}; /* ------------------------------------------------------------------------ */ /* SolidMechanicsModelEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: virtual void onBeginningSolveStep(const AnalysisMethod & method); virtual void onEndSolveStep(const AnalysisMethod & method); virtual void onDamageIteration(); virtual void onDamageUpdate(); virtual void onDump(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(Name, name, const std::string &); AKANTU_GET_MACRO(Model, model, const SolidMechanicsModel &) AKANTU_GET_MACRO(ID, Memory::getID(), const ID &); AKANTU_GET_MACRO(Rho, rho, Real); AKANTU_SET_MACRO(Rho, rho, Real); AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); /// return the potential energy for the subset of elements contained by the /// material Real getPotentialEnergy(); /// return the potential energy for the provided element Real getPotentialEnergy(ElementType & type, UInt index); /// return the energy (identified by id) for the subset of elements contained /// by the material virtual Real getEnergy(std::string energy_id); /// return the energy (identified by id) for the provided element virtual Real getEnergy(std::string energy_id, ElementType type, UInt index); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(GradU, gradu, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PotentialEnergy, potential_energy, Real); AKANTU_GET_MACRO(GradU, gradu, const ElementTypeMapArray<Real> &); AKANTU_GET_MACRO(Stress, stress, const ElementTypeMapArray<Real> &); AKANTU_GET_MACRO(ElementFilter, element_filter, const ElementTypeMapArray<UInt> &); AKANTU_GET_MACRO(FEEngine, fem, FEEngine &); bool isNonLocal() const { return is_non_local; } template <typename T> const Array<T> & getArray(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost) const; template <typename T> Array<T> & getArray(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost); template <typename T> const InternalField<T> & getInternal(const ID & id) const; template <typename T> InternalField<T> & getInternal(const ID & id); template <typename T> inline bool isInternal(const ID & id, const ElementKind & element_kind) const; template <typename T> ElementTypeMap<UInt> getInternalDataPerElem(const ID & id, const ElementKind & element_kind) const; bool isFiniteDeformation() const { return finite_deformation; } bool isInelasticDeformation() const { return inelastic_deformation; } template <typename T> inline void setParam(const ID & param, T value); inline const Parameter & getParam(const ID & param) const; template <typename T> void flattenInternal(const std::string & field_id, ElementTypeMapArray<T> & internal_flat, const GhostType ghost_type = _not_ghost, ElementKind element_kind = _ek_not_defined) const; /// apply a constant eigengrad_u everywhere in the material virtual void applyEigenGradU(const Matrix<Real> & prescribed_eigen_grad_u, const GhostType = _not_ghost); /// specify if the matrix need to be recomputed for this material virtual bool hasStiffnessMatrixChanged() { return true; } protected: bool isInit() const { return is_init; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// boolean to know if the material has been initialized bool is_init; std::map<ID, InternalField<Real> *> internal_vectors_real; std::map<ID, InternalField<UInt> *> internal_vectors_uint; std::map<ID, InternalField<bool> *> internal_vectors_bool; protected: /// Link to the fem object in the model FEEngine & fem; /// Finite deformation bool finite_deformation; /// Finite deformation bool inelastic_deformation; /// material name std::string name; /// The model to witch the material belong SolidMechanicsModel & model; /// density : rho Real rho; /// spatial dimension UInt spatial_dimension; /// list of element handled by the material ElementTypeMapArray<UInt> element_filter; /// stresses arrays ordered by element types InternalField<Real> stress; /// eigengrad_u arrays ordered by element types InternalField<Real> eigengradu; /// grad_u arrays ordered by element types InternalField<Real> gradu; /// Green Lagrange strain (Finite deformation) InternalField<Real> green_strain; /// Second Piola-Kirchhoff stress tensor arrays ordered by element types /// (Finite deformation) InternalField<Real> piola_kirchhoff_2; /// potential energy by element InternalField<Real> potential_energy; /// tell if using in non local mode or not bool is_non_local; /// tell if the material need the previous stress state bool use_previous_stress; /// tell if the material need the previous strain state bool use_previous_gradu; /// elemental field interpolation coordinates InternalField<Real> interpolation_inverse_coordinates; /// elemental field interpolation points InternalField<Real> interpolation_points_matrices; /// vector that contains the names of all the internals that need to /// be transferred when material interfaces move std::vector<ID> internals_to_transfer; }; /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const Material & _this) { _this.printself(stream); return stream; } } // namespace akantu #include "material_inline_impl.cc" #include "internal_field_tmpl.hh" #include "random_internal_field_tmpl.hh" /* -------------------------------------------------------------------------- */ /* Auto loop */ /* -------------------------------------------------------------------------- */ /// This can be used to automatically write the loop on quadrature points in /// functions such as computeStress. This macro in addition to write the loop /// provides two tensors (matrices) sigma and grad_u #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type) \ Array<Real>::matrix_iterator gradu_it = \ this->gradu(el_type, ghost_type) \ .begin(this->spatial_dimension, this->spatial_dimension); \ Array<Real>::matrix_iterator gradu_end = \ this->gradu(el_type, ghost_type) \ .end(this->spatial_dimension, this->spatial_dimension); \ \ this->stress(el_type, ghost_type) \ .resize(this->gradu(el_type, ghost_type).getSize()); \ \ Array<Real>::iterator<Matrix<Real>> stress_it = \ this->stress(el_type, ghost_type) \ .begin(this->spatial_dimension, this->spatial_dimension); \ \ if (this->isFiniteDeformation()) { \ this->piola_kirchhoff_2(el_type, ghost_type) \ .resize(this->gradu(el_type, ghost_type).getSize()); \ stress_it = this->piola_kirchhoff_2(el_type, ghost_type) \ .begin(this->spatial_dimension, this->spatial_dimension); \ } \ \ for (; gradu_it != gradu_end; ++gradu_it, ++stress_it) { \ Matrix<Real> & __attribute__((unused)) grad_u = *gradu_it; \ Matrix<Real> & __attribute__((unused)) sigma = *stress_it #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END } /// This can be used to automatically write the loop on quadrature points in /// functions such as computeTangentModuli. This macro in addition to write the /// loop provides two tensors (matrices) sigma_tensor, grad_u, and a matrix /// where the elemental tangent moduli should be stored in Voigt Notation #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_mat) \ Array<Real>::matrix_iterator gradu_it = \ this->gradu(el_type, ghost_type) \ .begin(this->spatial_dimension, this->spatial_dimension); \ Array<Real>::matrix_iterator gradu_end = \ this->gradu(el_type, ghost_type) \ .end(this->spatial_dimension, this->spatial_dimension); \ Array<Real>::matrix_iterator sigma_it = \ this->stress(el_type, ghost_type) \ .begin(this->spatial_dimension, this->spatial_dimension); \ \ tangent_mat.resize(this->gradu(el_type, ghost_type).getSize()); \ \ UInt tangent_size = \ this->getTangentStiffnessVoigtSize(this->spatial_dimension); \ Array<Real>::matrix_iterator tangent_it = \ tangent_mat.begin(tangent_size, tangent_size); \ \ for (; gradu_it != gradu_end; ++gradu_it, ++sigma_it, ++tangent_it) { \ Matrix<Real> & __attribute__((unused)) grad_u = *gradu_it; \ Matrix<Real> & __attribute__((unused)) sigma_tensor = *sigma_it; \ Matrix<Real> & tangent = *tangent_it #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END } /* -------------------------------------------------------------------------- */ -#define INSTANTIATE_MATERIAL(mat_name) \ +namespace akantu { +using MaterialFactory = + Factory<Material, UInt, const ID &, SolidMechanicsModel &, const ID &>; +} // namespace akantu + +#define INSTANTIATE_MATERIAL_ONLY(mat_name) \ template class mat_name<1>; \ template class mat_name<2>; \ template class mat_name<3> -#endif /* __AKANTU_MATERIAL_HH__ */ +#define MATERIAL_DEFAULT_PER_DIM_ALLOCATOR(id, mat_name) \ + [](UInt dim, const ID &, SolidMechanicsModel & model, \ + const ID & id) -> std::unique_ptr<Material> { \ + switch (dim) { \ + case 1: \ + return std::make_unique<mat_name<1>>(model, id); \ + case 2: \ + return std::make_unique<mat_name<2>>(model, id); \ + case 3: \ + return std::make_unique<mat_name<3>>(model, id); \ + default: \ + AKANTU_EXCEPTION("The dimension " \ + << dim << "is not a valid dimension for the material " \ + << #id); \ + } \ + } + +#define INSTANTIATE_MATERIAL(id, mat_name) \ + INSTANTIATE_MATERIAL_ONLY(mat_name); \ + static bool material_is_alocated_##id = \ + MaterialFactory::getInstance().registerAllocator( \ + #id, MATERIAL_DEFAULT_PER_DIM_ALLOCATOR(id, mat_name)) -// LocalWords: ElementNull +#endif /* __AKANTU_MATERIAL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.cc index 27d48cc8d..8e9c52889 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_bilinear.cc @@ -1,211 +1,211 @@ /** * @file material_cohesive_bilinear.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Feb 22 2012 * @date last modification: Thu Oct 15 2015 * * @brief Bilinear cohesive constitutive law * * @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 "material_cohesive_bilinear.hh" #include "solid_mechanics_model_cohesive.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialCohesiveBilinear<spatial_dimension>::MaterialCohesiveBilinear(SolidMechanicsModel & model, const ID & id) : MaterialCohesiveLinear<spatial_dimension>(model, id) { AKANTU_DEBUG_IN(); this->registerParam("delta_0", delta_0, Real(0.), _pat_parsable | _pat_readable, "Elastic limit displacement"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveBilinear<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); this->sigma_c_eff.setRandomDistribution(this->sigma_c.getRandomParameter()); MaterialCohesiveLinear<spatial_dimension>::initMaterial(); this->delta_max .setDefaultValue(delta_0); this->insertion_stress.setDefaultValue(0); this->delta_max .reset(); this->insertion_stress.reset(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveBilinear<spatial_dimension>::onElementsAdded(const Array<Element> & element_list, const NewElementsEvent & event) { AKANTU_DEBUG_IN(); MaterialCohesiveLinear<spatial_dimension>::onElementsAdded(element_list, event); bool scale_traction = false; // don't scale sigma_c if volume_s hasn't been specified by the user if (!Math::are_float_equal(this->volume_s, 0.)) scale_traction = true; Array<Element>::const_scalar_iterator el_it = element_list.begin(); Array<Element>::const_scalar_iterator el_end = element_list.end(); for (; el_it != el_end; ++el_it) { // filter not ghost cohesive elements if (el_it->ghost_type != _not_ghost || el_it->kind != _ek_cohesive) continue; UInt index = el_it->element; ElementType type = el_it->type; UInt nb_element = this->model->getMesh().getNbElement(type); UInt nb_quad_per_element = this->fem_cohesive->getNbIntegrationPoints(type); Array<Real>::vector_iterator sigma_c_begin = this->sigma_c_eff(type).begin_reinterpret(nb_quad_per_element, nb_element); Vector<Real> sigma_c_vec = sigma_c_begin[index]; Array<Real>::vector_iterator delta_c_begin = this->delta_c_eff(type).begin_reinterpret(nb_quad_per_element, nb_element); Vector<Real> delta_c_vec = delta_c_begin[index]; if (scale_traction) scaleTraction(*el_it, sigma_c_vec); /** * Recompute sigma_c as * @f$ {\sigma_c}_\textup{new} = * \frac{{\sigma_c}_\textup{old} \delta_c} {\delta_c - \delta_0} @f$ */ for (UInt q = 0; q < nb_quad_per_element; ++q) { delta_c_vec(q) = 2 * this->G_c / sigma_c_vec(q); if (delta_c_vec(q) - delta_0 < Math::getTolerance()) AKANTU_DEBUG_ERROR("delta_0 = " << delta_0 << " must be lower than delta_c = " << delta_c_vec(q) << ", modify your material file"); sigma_c_vec(q) *= delta_c_vec(q) / (delta_c_vec(q) - delta_0); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveBilinear<spatial_dimension>::scaleTraction(const Element & el, Vector<Real> & sigma_c_vec) { AKANTU_DEBUG_IN(); Real base_sigma_c = this->sigma_c_eff; const Mesh & mesh_facets = this->model->getMeshFacets(); const FEEngine & fe_engine = this->model->getFEEngine(); Array<Element>::const_vector_iterator coh_element_to_facet_begin = mesh_facets.getSubelementToElement(el.type).begin(2); const Vector<Element> & coh_element_to_facet = coh_element_to_facet_begin[el.element]; // compute bounding volume Real volume = 0; // loop over facets for (UInt f = 0; f < 2; ++f) { const Element & facet = coh_element_to_facet(f); const Array< std::vector<Element> > & facet_to_element = mesh_facets.getElementToSubelement(facet.type, facet.ghost_type); const std::vector<Element> & element_list = facet_to_element(facet.element); std::vector<Element>::const_iterator elem = element_list.begin(); std::vector<Element>::const_iterator elem_end = element_list.end(); // loop over elements connected to each facet for (; elem != elem_end; ++elem) { // skip cohesive elements and dummy elements if (*elem == ElementNull || elem->kind == _ek_cohesive) continue; // unit vector for integration in order to obtain the volume UInt nb_quadrature_points = fe_engine.getNbIntegrationPoints(elem->type); Vector<Real> unit_vector(nb_quadrature_points, 1); volume += fe_engine.integrate(unit_vector, elem->type, elem->element, elem->ghost_type); } } // scale sigma_c sigma_c_vec -= base_sigma_c; sigma_c_vec *= std::pow(this->volume_s / volume, 1. / this->m_s); sigma_c_vec += base_sigma_c; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveBilinear<spatial_dimension>::computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialCohesiveLinear<spatial_dimension>::computeTraction(normal, el_type, ghost_type); // adjust damage Array<Real>::scalar_iterator delta_c_it = this->delta_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_max_it = this->delta_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_it = this->damage(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_end = this->damage(el_type, ghost_type).end(); for (; damage_it != damage_end; ++damage_it, ++delta_max_it, ++delta_c_it) { *damage_it = std::max((*delta_max_it - delta_0) / (*delta_c_it - delta_0), Real(0.)); *damage_it = std::min(*damage_it, Real(1.)); } } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialCohesiveBilinear); +INSTANTIATE_MATERIAL(cohesive_bilinear, MaterialCohesiveBilinear); } // akantu diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.cc index 7e9b2b4ea..ff2e48708 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_exponential.cc @@ -1,358 +1,358 @@ /** * @file material_cohesive_exponential.cc * * @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Mon Jul 09 2012 * @date last modification: Tue Aug 04 2015 * * @brief Exponential irreversible cohesive law of mixed mode loading * * @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 "material_cohesive_exponential.hh" #include "dof_synchronizer.hh" #include "solid_mechanics_model.hh" #include "sparse_matrix.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialCohesiveExponential<spatial_dimension>::MaterialCohesiveExponential( SolidMechanicsModel & model, const ID & id) : MaterialCohesive(model, id) { AKANTU_DEBUG_IN(); this->registerParam("beta", beta, Real(0.), _pat_parsable, "Beta parameter"); this->registerParam("exponential_penalty", exp_penalty, true, _pat_parsable, "Is contact penalty following the exponential law?"); this->registerParam( "contact_tangent", contact_tangent, Real(1.0), _pat_parsable, "Ratio of contact tangent over the initial exponential tangent"); // this->initInternalArray(delta_max, 1, _ek_cohesive); use_previous_delta_max = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialCohesive::initMaterial(); if ((exp_penalty) && (contact_tangent != 1)) { contact_tangent = 1; AKANTU_DEBUG_WARNING("The parsed paramter <contact_tangent> is forced to " "1.0 when the contact penalty follows the exponential " "law"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::computeTraction( const Array<Real> & normal, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::vector_iterator traction_it = tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator opening_it = opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::const_vector_iterator normal_it = normal.begin(spatial_dimension); Array<Real>::vector_iterator traction_end = tractions(el_type, ghost_type).end(spatial_dimension); Array<Real>::iterator<Real> delta_max_it = delta_max(el_type, ghost_type).begin(); Array<Real>::iterator<Real> delta_max_prev_it = delta_max.previous(el_type, ghost_type).begin(); /// compute scalars Real beta2 = beta * beta; /// loop on each quadrature point for (; traction_it != traction_end; ++traction_it, ++opening_it, ++normal_it, ++delta_max_it, ++delta_max_prev_it) { /// compute normal and tangential opening vectors Real normal_opening_norm = opening_it->dot(*normal_it); Vector<Real> normal_opening(spatial_dimension); normal_opening = (*normal_it); normal_opening *= normal_opening_norm; Vector<Real> tangential_opening(spatial_dimension); tangential_opening = *opening_it; tangential_opening -= normal_opening; Real tangential_opening_norm = tangential_opening.norm(); /** * compute effective opening displacement * @f$ \delta = \sqrt{ * \beta^2 \Delta_t^2 + \Delta_n^2 } @f$ */ Real delta = tangential_opening_norm; delta *= delta * beta2; delta += normal_opening_norm * normal_opening_norm; delta = sqrt(delta); if ((normal_opening_norm < 0) && (std::abs(normal_opening_norm) > Math::getTolerance())) { Vector<Real> op_n(*normal_it); op_n *= normal_opening_norm; Vector<Real> delta_s(*opening_it); delta_s -= op_n; delta = tangential_opening_norm * beta; computeCoupledTraction(*traction_it, *normal_it, delta, delta_s, *delta_max_it, *delta_max_prev_it); computeCompressiveTraction(*traction_it, *normal_it, normal_opening_norm, *opening_it); } else computeCoupledTraction(*traction_it, *normal_it, delta, *opening_it, *delta_max_it, *delta_max_prev_it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::computeCoupledTraction( Vector<Real> & tract, const Vector<Real> & normal, Real delta, const Vector<Real> & opening, Real & delta_max_new, Real delta_max) { AKANTU_DEBUG_IN(); /// full damage case if (std::abs(delta) < Math::getTolerance()) { /// set traction to zero tract.clear(); } else { /// element not fully damaged /** * Compute traction loading @f$ \mathbf{T} = * e \sigma_c \frac{\delta}{\delta_c} e^{-\delta/ \delta_c}@f$ */ /** * Compute traction unloading @f$ \mathbf{T} = * \frac{t_{max}}{\delta_{max}} \delta @f$ */ Real beta2 = beta * beta; Real normal_open_norm = opening.dot(normal); Vector<Real> op_n_n(spatial_dimension); op_n_n = normal; op_n_n *= (1 - beta2); op_n_n *= normal_open_norm; tract = beta2 * opening; tract += op_n_n; delta_max_new = std::max(delta_max, delta); tract *= exp(1) * sigma_c * exp(-delta_max_new / delta_c) / delta_c; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::computeCompressiveTraction( Vector<Real> & tract, const Vector<Real> & normal, Real delta_n, __attribute__((unused)) const Vector<Real> & opening) { Vector<Real> temp_tract(normal); if (exp_penalty) { temp_tract *= delta_n * exp(1) * sigma_c * exp(-delta_n / delta_c) / delta_c; } else { Real initial_tg = contact_tangent * exp(1) * sigma_c * delta_n / delta_c; temp_tract *= initial_tg; } tract += temp_tract; } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::computeTangentTraction( const ElementType & el_type, Array<Real> & tangent_matrix, const Array<Real> & normal, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real>::matrix_iterator tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension); Array<Real>::const_vector_iterator normal_it = normal.begin(spatial_dimension); Array<Real>::vector_iterator opening_it = opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::iterator<Real> delta_max_it = delta_max.previous(el_type, ghost_type).begin(); Real beta2 = beta * beta; /** * compute tangent matrix @f$ \frac{\partial \mathbf{t}} * {\partial \delta} = \hat{\mathbf{t}} \otimes * \frac{\partial (t/\delta)}{\partial \delta} * \frac{\hat{\mathbf{t}}}{\delta}+ \frac{t}{\delta} [ \beta^2 \mathbf{I} + * (1-\beta^2) (\mathbf{n} \otimes \mathbf{n})] @f$ **/ /** * In which @f$ * \frac{\partial(t/ \delta)}{\partial \delta} = * \left\{\begin{array} {l l} * -e \frac{\sigma_c}{\delta_c^2 }e^{-\delta / \delta_c} & \quad if * \delta \geq \delta_{max} \\ * 0 & \quad if \delta < \delta_{max}, \delta_n > 0 * \end{array}\right. @f$ **/ for (; tangent_it != tangent_end; ++tangent_it, ++normal_it, ++opening_it, ++delta_max_it) { Real normal_opening_norm = opening_it->dot(*normal_it); Vector<Real> normal_opening(spatial_dimension); normal_opening = (*normal_it); normal_opening *= normal_opening_norm; Vector<Real> tangential_opening(spatial_dimension); tangential_opening = *opening_it; tangential_opening -= normal_opening; Real tangential_opening_norm = tangential_opening.norm(); Real delta = tangential_opening_norm; delta *= delta * beta2; delta += normal_opening_norm * normal_opening_norm; delta = sqrt(delta); if ((normal_opening_norm < 0) && (std::abs(normal_opening_norm) > Math::getTolerance())) { Vector<Real> op_n(*normal_it); op_n *= normal_opening_norm; Vector<Real> delta_s(*opening_it); delta_s -= op_n; delta = tangential_opening_norm * beta; computeCoupledTangent(*tangent_it, *normal_it, delta, delta_s, *delta_max_it); computeCompressivePenalty(*tangent_it, *normal_it, normal_opening_norm); } else computeCoupledTangent(*tangent_it, *normal_it, delta, *opening_it, *delta_max_it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::computeCoupledTangent( Matrix<Real> & tangent, const Vector<Real> & normal, Real delta, const Vector<Real> & opening, Real) { AKANTU_DEBUG_IN(); Real beta2 = beta * beta; Matrix<Real> J(spatial_dimension, spatial_dimension); J.eye(beta2); if (std::abs(delta) < Math::getTolerance()) { delta = Math::getTolerance(); } Real opening_normal; opening_normal = opening.dot(normal); Vector<Real> delta_e(normal); delta_e *= opening_normal; delta_e *= (1 - beta2); delta_e += (beta2 * opening); Real exponent = exp(1 - delta / delta_c) * sigma_c / delta_c; Matrix<Real> first_term(spatial_dimension, spatial_dimension); first_term.outerProduct(normal, normal); first_term *= (1 - beta2); first_term += J; Matrix<Real> second_term(spatial_dimension, spatial_dimension); second_term.outerProduct(delta_e, delta_e); second_term /= delta; second_term /= delta_c; Matrix<Real> diff(first_term); diff -= second_term; tangent = diff; tangent *= exponent; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveExponential<spatial_dimension>::computeCompressivePenalty( Matrix<Real> & tangent, const Vector<Real> & normal, Real delta_n) { if (!exp_penalty) delta_n = 0; Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension); n_outer_n.outerProduct(normal, normal); Real normal_tg = contact_tangent * exp(1) * sigma_c * exp(-delta_n / delta_c) * (1 - delta_n / delta_c) / delta_c; n_outer_n *= normal_tg; tangent += n_outer_n; } -INSTANTIATE_MATERIAL(MaterialCohesiveExponential); +INSTANTIATE_MATERIAL(cohesive_exponential, MaterialCohesiveExponential); } // akantu diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc index 669d3e684..9277b1bb1 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc @@ -1,700 +1,700 @@ /** * @file material_cohesive_linear.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Wed Feb 22 2012 * @date last modification: Thu Jan 14 2016 * * @brief Linear irreversible cohesive law of mixed mode loading with * random stress definition for extrinsic 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 <algorithm> #include <numeric> /* -------------------------------------------------------------------------- */ #include "dof_synchronizer.hh" #include "material_cohesive_linear.hh" #include "solid_mechanics_model_cohesive.hh" #include "sparse_matrix.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialCohesiveLinear<spatial_dimension>::MaterialCohesiveLinear( SolidMechanicsModel & model, const ID & id) : MaterialCohesive(model, id), sigma_c_eff("sigma_c_eff", *this), delta_c_eff("delta_c_eff", *this), insertion_stress("insertion_stress", *this), opening_prec("opening_prec", *this), reduction_penalty("reduction_penalty", *this) { AKANTU_DEBUG_IN(); this->registerParam("beta", beta, Real(0.), _pat_parsable | _pat_readable, "Beta parameter"); this->registerParam("G_c", G_c, Real(0.), _pat_parsable | _pat_readable, "Mode I fracture energy"); this->registerParam("penalty", penalty, Real(0.), _pat_parsable | _pat_readable, "Penalty coefficient"); this->registerParam("volume_s", volume_s, Real(0.), _pat_parsable | _pat_readable, "Reference volume for sigma_c scaling"); this->registerParam("m_s", m_s, Real(1.), _pat_parsable | _pat_readable, "Weibull exponent for sigma_c scaling"); this->registerParam("kappa", kappa, Real(1.), _pat_parsable | _pat_readable, "Kappa parameter"); this->registerParam( "contact_after_breaking", contact_after_breaking, false, _pat_parsable | _pat_readable, "Activation of contact when the elements are fully damaged"); this->registerParam("max_quad_stress_insertion", max_quad_stress_insertion, false, _pat_parsable | _pat_readable, "Insertion of cohesive element when stress is high " "enough just on one quadrature point"); this->registerParam("recompute", recompute, false, _pat_parsable | _pat_modifiable, "recompute solution"); this->use_previous_delta_max = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialCohesive::initMaterial(); /// compute scalars beta2_kappa2 = beta * beta / kappa / kappa; beta2_kappa = beta * beta / kappa; if (Math::are_float_equal(beta, 0)) beta2_inv = 0; else beta2_inv = 1. / beta / beta; sigma_c_eff.initialize(1); delta_c_eff.initialize(1); insertion_stress.initialize(spatial_dimension); opening_prec.initialize(spatial_dimension); reduction_penalty.initialize(1); if (!Math::are_float_equal(delta_c, 0.)) delta_c_eff.setDefaultValue(delta_c); else delta_c_eff.setDefaultValue(2 * G_c / sigma_c); if (model->getIsExtrinsic()) scaleInsertionTraction(); opening_prec.initializeHistory(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::scaleInsertionTraction() { AKANTU_DEBUG_IN(); // do nothing if volume_s hasn't been specified by the user if (Math::are_float_equal(volume_s, 0.)) return; const Mesh & mesh_facets = model->getMeshFacets(); const FEEngine & fe_engine = model->getFEEngine(); const FEEngine & fe_engine_facet = model->getFEEngine("FacetsFEEngine"); // loop over facet type Mesh::type_iterator first = mesh_facets.firstType(spatial_dimension - 1); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1); Real base_sigma_c = sigma_c; for (; first != last; ++first) { ElementType type_facet = *first; const Array<std::vector<Element> > & facet_to_element = mesh_facets.getElementToSubelement(type_facet); UInt nb_facet = facet_to_element.getSize(); UInt nb_quad_per_facet = fe_engine_facet.getNbIntegrationPoints(type_facet); // iterator to modify sigma_c for all the quadrature points of a facet Array<Real>::vector_iterator sigma_c_iterator = sigma_c(type_facet).begin_reinterpret(nb_quad_per_facet, nb_facet); for (UInt f = 0; f < nb_facet; ++f, ++sigma_c_iterator) { const std::vector<Element> & element_list = facet_to_element(f); // compute bounding volume Real volume = 0; std::vector<Element>::const_iterator elem = element_list.begin(); std::vector<Element>::const_iterator elem_end = element_list.end(); for (; elem != elem_end; ++elem) { if (*elem == ElementNull) continue; // unit vector for integration in order to obtain the volume UInt nb_quadrature_points = fe_engine.getNbIntegrationPoints(elem->type); Vector<Real> unit_vector(nb_quadrature_points, 1); volume += fe_engine.integrate(unit_vector, elem->type, elem->element, elem->ghost_type); } // scale sigma_c *sigma_c_iterator -= base_sigma_c; *sigma_c_iterator *= std::pow(volume_s / volume, 1. / m_s); *sigma_c_iterator += base_sigma_c; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::checkInsertion( bool check_only) { AKANTU_DEBUG_IN(); const Mesh & mesh_facets = model->getMeshFacets(); CohesiveElementInserter & inserter = model->getElementInserter(); Real tolerance = Math::getTolerance(); Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1); for (; it != last; ++it) { ElementType type_facet = *it; ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet); const Array<bool> & facets_check = inserter.getCheckFacets(type_facet); Array<bool> & f_insertion = inserter.getInsertionFacets(type_facet); Array<UInt> & f_filter = facet_filter(type_facet); Array<Real> & sig_c_eff = sigma_c_eff(type_cohesive); Array<Real> & del_c = delta_c_eff(type_cohesive); Array<Real> & ins_stress = insertion_stress(type_cohesive); Array<Real> & trac_old = tractions_old(type_cohesive); Array<Real> & open_prec = opening_prec(type_cohesive); Array<bool> & red_penalty = reduction_penalty(type_cohesive); const Array<Real> & f_stress = model->getStressOnFacets(type_facet); const Array<Real> & sigma_lim = sigma_c(type_facet); Real max_ratio = 0.; UInt index_f = 0; UInt index_filter = 0; UInt nn = 0; UInt nb_quad_facet = model->getFEEngine("FacetsFEEngine").getNbIntegrationPoints(type_facet); UInt nb_quad_cohesive = model->getFEEngine("CohesiveFEEngine") .getNbIntegrationPoints(type_cohesive); AKANTU_DEBUG_ASSERT(nb_quad_cohesive == nb_quad_facet, "The cohesive element and the corresponding facet do " "not have the same numbers of integration points"); UInt nb_facet = f_filter.getSize(); // if (nb_facet == 0) continue; Array<Real>::const_iterator<Real> sigma_lim_it = sigma_lim.begin(); Matrix<Real> stress_tmp(spatial_dimension, spatial_dimension); Matrix<Real> normal_traction(spatial_dimension, nb_quad_facet); Vector<Real> stress_check(nb_quad_facet); UInt sp2 = spatial_dimension * spatial_dimension; const Array<Real> & tangents = model->getTangents(type_facet); const Array<Real> & normals = model->getFEEngine("FacetsFEEngine") .getNormalsOnIntegrationPoints(type_facet); Array<Real>::const_vector_iterator normal_begin = normals.begin(spatial_dimension); Array<Real>::const_vector_iterator tangent_begin = tangents.begin(tangents.getNbComponent()); Array<Real>::const_matrix_iterator facet_stress_begin = f_stress.begin(spatial_dimension, spatial_dimension * 2); std::vector<Real> new_sigmas; std::vector<Vector<Real> > new_normal_traction; std::vector<Real> new_delta_c; // loop over each facet belonging to this material for (UInt f = 0; f < nb_facet; ++f, ++sigma_lim_it) { UInt facet = f_filter(f); // skip facets where check shouldn't be realized if (!facets_check(facet)) continue; // compute the effective norm on each quadrature point of the facet for (UInt q = 0; q < nb_quad_facet; ++q) { UInt current_quad = facet * nb_quad_facet + q; const Vector<Real> & normal = normal_begin[current_quad]; const Vector<Real> & tangent = tangent_begin[current_quad]; const Matrix<Real> & facet_stress_it = facet_stress_begin[current_quad]; // compute average stress on the current quadrature point Matrix<Real> stress_1(facet_stress_it.storage(), spatial_dimension, spatial_dimension); Matrix<Real> stress_2(facet_stress_it.storage() + sp2, spatial_dimension, spatial_dimension); stress_tmp.copy(stress_1); stress_tmp += stress_2; stress_tmp /= 2.; Vector<Real> normal_traction_vec(normal_traction(q)); // compute normal and effective stress stress_check(q) = computeEffectiveNorm(stress_tmp, normal, tangent, normal_traction_vec); } // verify if the effective stress overcomes the threshold Real final_stress = stress_check.mean(); if (max_quad_stress_insertion) final_stress = *std::max_element( stress_check.storage(), stress_check.storage() + nb_quad_facet); if (final_stress > (*sigma_lim_it - tolerance)) { if (model->isDefaultSolverExplicit()) { f_insertion(facet) = true; if (!check_only) { // store the new cohesive material parameters for each quadrature // point for (UInt q = 0; q < nb_quad_facet; ++q) { Real new_sigma = stress_check(q); Vector<Real> normal_traction_vec(normal_traction(q)); if (spatial_dimension != 3) normal_traction_vec *= -1.; new_sigmas.push_back(new_sigma); new_normal_traction.push_back(normal_traction_vec); Real new_delta; // set delta_c in function of G_c or a given delta_c value if (Math::are_float_equal(delta_c, 0.)) new_delta = 2 * G_c / new_sigma; else new_delta = (*sigma_lim_it) / new_sigma * delta_c; new_delta_c.push_back(new_delta); } } } else { Real ratio = final_stress / (*sigma_lim_it); if (ratio > max_ratio) { ++nn; max_ratio = ratio; index_f = f; index_filter = f_filter(f); } } } } /// Insertion of only 1 cohesive element in case of implicit approach. The /// one subjected to the highest stress. if (!model->isDefaultSolverExplicit()) { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Array<Real> abs_max(comm.getNbProc()); abs_max(comm.whoAmI()) = max_ratio; comm.allGather(abs_max); Array<Real>::scalar_iterator it = std::max_element(abs_max.begin(), abs_max.end()); Int pos = it - abs_max.begin(); if (pos != comm.whoAmI()) { AKANTU_DEBUG_OUT(); return; } if (nn) { f_insertion(index_filter) = true; if (!check_only) { // Array<Real>::iterator<Matrix<Real> > normal_traction_it = // normal_traction.begin_reinterpret(nb_quad_facet, // spatial_dimension, nb_facet); Array<Real>::const_iterator<Real> sigma_lim_it = sigma_lim.begin(); for (UInt q = 0; q < nb_quad_cohesive; ++q) { Real new_sigma = (sigma_lim_it[index_f]); Vector<Real> normal_traction_vec(spatial_dimension, 0.0); new_sigmas.push_back(new_sigma); new_normal_traction.push_back(normal_traction_vec); Real new_delta; // set delta_c in function of G_c or a given delta_c value if (!Math::are_float_equal(delta_c, 0.)) new_delta = delta_c; else new_delta = 2 * G_c / (new_sigma); new_delta_c.push_back(new_delta); } } } } // update material data for the new elements UInt old_nb_quad_points = sig_c_eff.getSize(); UInt new_nb_quad_points = new_sigmas.size(); sig_c_eff.resize(old_nb_quad_points + new_nb_quad_points); ins_stress.resize(old_nb_quad_points + new_nb_quad_points); trac_old.resize(old_nb_quad_points + new_nb_quad_points); del_c.resize(old_nb_quad_points + new_nb_quad_points); open_prec.resize(old_nb_quad_points + new_nb_quad_points); red_penalty.resize(old_nb_quad_points + new_nb_quad_points); for (UInt q = 0; q < new_nb_quad_points; ++q) { sig_c_eff(old_nb_quad_points + q) = new_sigmas[q]; del_c(old_nb_quad_points + q) = new_delta_c[q]; red_penalty(old_nb_quad_points + q) = false; for (UInt dim = 0; dim < spatial_dimension; ++dim) { ins_stress(old_nb_quad_points + q, dim) = new_normal_traction[q](dim); trac_old(old_nb_quad_points + q, dim) = new_normal_traction[q](dim); open_prec(old_nb_quad_points + q, dim) = 0.; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::computeTraction( const Array<Real> & normal, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::vector_iterator traction_it = tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator opening_it = opening(el_type, ghost_type).begin(spatial_dimension); /// opening_prec is the opening of the previous step in the /// Newton-Raphson loop Array<Real>::vector_iterator opening_prec_it = opening_prec(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_traction_it = contact_tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_opening_it = contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::const_vector_iterator normal_it = normal.begin(spatial_dimension); Array<Real>::vector_iterator traction_end = tractions(el_type, ghost_type).end(spatial_dimension); Array<Real>::scalar_iterator sigma_c_it = sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_max_it = delta_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_max_prev_it = delta_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_c_it = delta_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_it = damage(el_type, ghost_type).begin(); Array<Real>::vector_iterator insertion_stress_it = insertion_stress(el_type, ghost_type).begin(spatial_dimension); Array<bool>::scalar_iterator reduction_penalty_it = reduction_penalty(el_type, ghost_type).begin(); Vector<Real> normal_opening(spatial_dimension); Vector<Real> tangential_opening(spatial_dimension); if (!this->model->isDefaultSolverExplicit()) this->delta_max(el_type, ghost_type) .copy(this->delta_max.previous(el_type, ghost_type)); /// loop on each quadrature point for (; traction_it != traction_end; ++traction_it, ++opening_it, ++opening_prec_it, ++normal_it, ++sigma_c_it, ++delta_max_it, ++delta_c_it, ++damage_it, ++contact_traction_it, ++insertion_stress_it, ++contact_opening_it, ++delta_max_prev_it, ++reduction_penalty_it) { Real normal_opening_norm, tangential_opening_norm; bool penetration; Real current_penalty = 0.; this->computeTractionOnQuad( *traction_it, *delta_max_it, *delta_max_prev_it, *delta_c_it, *insertion_stress_it, *sigma_c_it, *opening_it, *opening_prec_it, *normal_it, normal_opening, tangential_opening, normal_opening_norm, tangential_opening_norm, *damage_it, penetration, *reduction_penalty_it, current_penalty, *contact_traction_it, *contact_opening_it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::checkDeltaMax( GhostType ghost_type) { AKANTU_DEBUG_IN(); /** * This function set a predefined value to the parameter * delta_max_prev of the elements that have been inserted in the * last loading step for which convergence has not been * reached. This is done before reducing the loading and re-doing * the step. Otherwise, the updating of delta_max_prev would be * done with reference to the non-convergent solution. In this * function also other variables related to the contact and * friction behavior are correctly set. */ Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); /** * the variable "recompute" is set to true to activate the * procedure that reduce the penalty parameter for * compression. This procedure is set true only during the phase of * load_reduction, that has to be set in the maiin file. The * penalty parameter will be reduced only for the elements having * reduction_penalty = true. */ recompute = true; for (; it != last_type; ++it) { Array<UInt> & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element == 0) continue; ElementType el_type = *it; /// define iterators Array<Real>::scalar_iterator delta_max_it = delta_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_max_end = delta_max(el_type, ghost_type).end(); Array<Real>::scalar_iterator delta_max_prev_it = delta_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_c_it = delta_c_eff(el_type, ghost_type).begin(); Array<Real>::vector_iterator opening_prec_it = opening_prec(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator opening_prec_prev_it = opening_prec.previous(el_type, ghost_type).begin(spatial_dimension); /// loop on each quadrature point for (; delta_max_it != delta_max_end; ++delta_max_it, ++delta_max_prev_it, ++delta_c_it, ++opening_prec_it, ++opening_prec_prev_it) { if (*delta_max_prev_it == 0) /// elements inserted in the last incremental step, that did /// not converge *delta_max_it = *delta_c_it / 1000; else /// elements introduced in previous incremental steps, for /// which a correct value of delta_max_prev already exists *delta_max_it = *delta_max_prev_it; /// in case convergence is not reached, set opening_prec to the /// value referred to the previous incremental step *opening_prec_it = *opening_prec_prev_it; } } } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::resetVariables( GhostType ghost_type) { AKANTU_DEBUG_IN(); /** * This function set the variables "recompute" and * "reduction_penalty" to false. It is called by solveStepCohesive * when convergence is reached. Such variables, in fact, have to be * false at the beginning of a new incremental step. */ Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); recompute = false; for (; it != last_type; ++it) { Array<UInt> & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element == 0) continue; ElementType el_type = *it; Array<bool>::scalar_iterator reduction_penalty_it = reduction_penalty(el_type, ghost_type).begin(); Array<bool>::scalar_iterator reduction_penalty_end = reduction_penalty(el_type, ghost_type).end(); /// loop on each quadrature point for (; reduction_penalty_it != reduction_penalty_end; ++reduction_penalty_it) { *reduction_penalty_it = false; } } } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::computeTangentTraction( const ElementType & el_type, Array<Real> & tangent_matrix, const Array<Real> & normal, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::matrix_iterator tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension); Array<Real>::const_vector_iterator normal_it = normal.begin(spatial_dimension); Array<Real>::vector_iterator opening_it = opening(el_type, ghost_type).begin(spatial_dimension); /// NB: delta_max_it points on delta_max_previous, i.e. the /// delta_max related to the solution of the previous incremental /// step Array<Real>::scalar_iterator delta_max_it = delta_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator sigma_c_it = sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_c_it = delta_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_it = damage(el_type, ghost_type).begin(); Array<Real>::vector_iterator contact_opening_it = contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<bool>::scalar_iterator reduction_penalty_it = reduction_penalty(el_type, ghost_type).begin(); Vector<Real> normal_opening(spatial_dimension); Vector<Real> tangential_opening(spatial_dimension); for (; tangent_it != tangent_end; ++tangent_it, ++normal_it, ++opening_it, ++delta_max_it, ++sigma_c_it, ++delta_c_it, ++damage_it, ++contact_opening_it, ++reduction_penalty_it) { Real normal_opening_norm, tangential_opening_norm; bool penetration; Real current_penalty = 0.; this->computeTangentTractionOnQuad( *tangent_it, *delta_max_it, *delta_c_it, *sigma_c_it, *opening_it, *normal_it, normal_opening, tangential_opening, normal_opening_norm, tangential_opening_norm, *damage_it, penetration, *reduction_penalty_it, current_penalty, *contact_opening_it); // check if the tangential stiffness matrix is symmetric // for (UInt h = 0; h < spatial_dimension; ++h){ // for (UInt l = h; l < spatial_dimension; ++l){ // if (l > h){ // Real k_ls = (*tangent_it)[spatial_dimension*h+l]; // Real k_us = (*tangent_it)[spatial_dimension*l+h]; // // std::cout << "k_ls = " << k_ls << std::endl; // // std::cout << "k_us = " << k_us << std::endl; // if (std::abs(k_ls) > 1e-13 && std::abs(k_us) > 1e-13){ // Real error = std::abs((k_ls - k_us) / k_us); // if (error > 1e-10){ // std::cout << "non symmetric cohesive matrix" << std::endl; // // std::cout << "error " << error << std::endl; // } // } // } // } // } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialCohesiveLinear); +INSTANTIATE_MATERIAL(cohesive_linear, MaterialCohesiveLinear); } // akantu diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.cc index 27b8ac4b5..7bf8ea644 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_fatigue.cc @@ -1,296 +1,296 @@ /** * @file material_cohesive_linear_fatigue.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Fri Feb 20 2015 * @date last modification: Tue Jan 12 2016 * * @brief See material_cohesive_linear_fatigue.hh for information * * @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 "material_cohesive_linear_fatigue.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialCohesiveLinearFatigue<spatial_dimension> ::MaterialCohesiveLinearFatigue(SolidMechanicsModel & model, const ID & id) : MaterialCohesiveLinear<spatial_dimension>(model, id), delta_prec("delta_prec", *this), K_plus("K_plus", *this), K_minus("K_minus", *this), T_1d("T_1d", *this), switches("switches", *this), delta_dot_prec("delta_dot_prec", *this), normal_regime("normal_regime", *this) { this->registerParam("delta_f", delta_f, Real(-1.) , _pat_parsable | _pat_readable, "delta_f"); this->registerParam("progressive_delta_f", progressive_delta_f, false, _pat_parsable | _pat_readable, "Whether or not delta_f is equal to delta_max"); this->registerParam("count_switches", count_switches, false, _pat_parsable | _pat_readable, "Count the opening/closing switches per element"); this->registerParam("fatigue_ratio", fatigue_ratio, Real(1.), _pat_parsable | _pat_readable, "What portion of the cohesive law is subjected to fatigue"); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinearFatigue<spatial_dimension>::initMaterial() { MaterialCohesiveLinear<spatial_dimension>::initMaterial(); // check that delta_f has a proper value or assign a defaul value if (delta_f < 0) delta_f = this->delta_c_eff; else if (delta_f < this->delta_c_eff) AKANTU_DEBUG_ERROR("Delta_f must be greater or equal to delta_c"); delta_prec.initialize(1); K_plus.initialize(1); K_minus.initialize(1); T_1d.initialize(1); normal_regime.initialize(1); if (count_switches) { switches.initialize(1); delta_dot_prec.initialize(1); } } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinearFatigue<spatial_dimension> ::computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::vector_iterator traction_it = this->tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_traction_it = this->contact_tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_opening_it = this->contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::const_vector_iterator normal_it = normal.begin(spatial_dimension); Array<Real>::vector_iterator traction_end = this->tractions(el_type, ghost_type).end(spatial_dimension); const Array<Real> & sigma_c_array = this->sigma_c_eff(el_type, ghost_type); Array<Real> & delta_max_array = this->delta_max(el_type, ghost_type); const Array<Real> & delta_c_array = this->delta_c_eff(el_type, ghost_type); Array<Real> & damage_array = this->damage(el_type, ghost_type); Array<Real>::vector_iterator insertion_stress_it = this->insertion_stress(el_type, ghost_type).begin(spatial_dimension); Array<Real> & delta_prec_array = delta_prec(el_type, ghost_type); Array<Real> & K_plus_array = K_plus(el_type, ghost_type); Array<Real> & K_minus_array = K_minus(el_type, ghost_type); Array<Real> & T_1d_array = T_1d(el_type, ghost_type); Array<bool> & normal_regime_array = normal_regime(el_type, ghost_type); Array<UInt> * switches_array = NULL; Array<Real> * delta_dot_prec_array = NULL; if (count_switches) { switches_array = &switches(el_type, ghost_type); delta_dot_prec_array = &delta_dot_prec(el_type, ghost_type); } Real * memory_space = new Real[2*spatial_dimension]; Vector<Real> normal_opening(memory_space, spatial_dimension); Vector<Real> tangential_opening(memory_space + spatial_dimension, spatial_dimension); Real tolerance = Math::getTolerance(); /// loop on each quadrature point for (UInt q = 0; traction_it != traction_end; ++traction_it, ++opening_it, ++normal_it, ++contact_traction_it, ++insertion_stress_it, ++contact_opening_it, ++q) { /// compute normal and tangential opening vectors Real normal_opening_norm = opening_it->dot(*normal_it); normal_opening = (*normal_it); normal_opening *= normal_opening_norm; tangential_opening = *opening_it; tangential_opening -= normal_opening; Real tangential_opening_norm = tangential_opening.norm(); /** * compute effective opening displacement * @f$ \delta = \sqrt{ * \frac{\beta^2}{\kappa^2} \Delta_t^2 + \Delta_n^2 } @f$ */ Real delta = tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2; bool penetration = normal_opening_norm < -tolerance; if (this->contact_after_breaking == false && Math::are_float_equal(damage_array(q), 1.)) penetration = false; if (penetration) { /// use penalty coefficient in case of penetration *contact_traction_it = normal_opening; *contact_traction_it *= this->penalty; *contact_opening_it = normal_opening; /// don't consider penetration contribution for delta *opening_it = tangential_opening; normal_opening.clear(); } else { delta += normal_opening_norm * normal_opening_norm; contact_traction_it->clear(); contact_opening_it->clear(); } delta = std::sqrt(delta); /** * Compute traction @f$ \mathbf{T} = \left( * \frac{\beta^2}{\kappa} \Delta_t \mathbf{t} + \Delta_n * \mathbf{n} \right) \frac{\sigma_c}{\delta} \left( 1- * \frac{\delta}{\delta_c} \right)@f$ */ // update maximum displacement and damage delta_max_array(q) = std::max(delta, delta_max_array(q)); damage_array(q) = std::min(delta_max_array(q) / delta_c_array(q), Real(1.)); Real delta_dot = delta - delta_prec_array(q); // count switches if asked if (count_switches) { if ( (delta_dot > 0. && (*delta_dot_prec_array)(q) <= 0.) || (delta_dot < 0. && (*delta_dot_prec_array)(q) >= 0.) ) ++((*switches_array)(q)); (*delta_dot_prec_array)(q) = delta_dot; } // set delta_f equal to delta_max if desired if (progressive_delta_f) delta_f = delta_max_array(q); // broken element case if (Math::are_float_equal(damage_array(q), 1.)) traction_it->clear(); // just inserted element case else if (Math::are_float_equal(damage_array(q), 0.)) { if (penetration) traction_it->clear(); else *traction_it = *insertion_stress_it; // initialize the 1d traction to sigma_c T_1d_array(q) = sigma_c_array(q); } // normal case else { // if element is closed then there are zero tractions if (delta <= tolerance) traction_it->clear(); // otherwise compute new tractions if the new delta is different // than the previous one else if (std::abs(delta_dot) > tolerance) { // loading case if (delta_dot > 0.) { if (!normal_regime_array(q)) { // equation (4) of the article K_plus_array(q) *= 1. - delta_dot / delta_f; // equivalent to equation (2) of the article T_1d_array(q) += K_plus_array(q) * delta_dot; // in case of reloading, traction must not exceed that of the // envelop of the cohesive law Real max_traction = sigma_c_array(q) * (1 - delta / delta_c_array(q)); bool max_traction_exceeded = T_1d_array(q) > max_traction; if (max_traction_exceeded) T_1d_array(q) = max_traction; // switch to standard linear cohesive law if (delta_max_array(q) > fatigue_ratio * delta_c_array(q)) { // reset delta_max to avoid big jumps in the traction delta_max_array(q) = sigma_c_array(q) / (T_1d_array(q) / delta + sigma_c_array(q) / delta_c_array(q)); damage_array(q) = std::min(delta_max_array(q) / delta_c_array(q), Real(1.)); K_minus_array(q) = sigma_c_array(q) / delta_max_array(q) * (1. - damage_array(q)); normal_regime_array(q) = true; } else { // equation (3) of the article K_minus_array(q) = T_1d_array(q) / delta; // if the traction is following the cohesive envelop, then // K_plus has to be reset if (max_traction_exceeded) K_plus_array(q) = K_minus_array(q); } } else { // compute stiffness according to the standard law K_minus_array(q) = sigma_c_array(q) / delta_max_array(q) * (1. - damage_array(q)); } } // unloading case else if (!normal_regime_array(q)) { // equation (4) of the article K_plus_array(q) += (K_plus_array(q) - K_minus_array(q)) * delta_dot / delta_f; // equivalent to equation (2) of the article T_1d_array(q) = K_minus_array(q) * delta; } // applying the actual stiffness *traction_it = tangential_opening; *traction_it *= this->beta2_kappa; *traction_it += normal_opening; *traction_it *= K_minus_array(q); } } // update precendent delta delta_prec_array(q) = delta; } delete [] memory_space; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialCohesiveLinearFatigue); +INSTANTIATE_MATERIAL(cohesive_linear_fatigue, MaterialCohesiveLinearFatigue); } // akantu diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.cc index d5d96e9cc..c21e2ff4b 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_friction.cc @@ -1,386 +1,386 @@ /** * @file material_cohesive_linear_friction.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Tue Jan 12 2016 * @date last modification: Thu Jan 14 2016 * * @brief Linear irreversible cohesive law of mixed mode loading with * random stress definition for extrinsic type * * @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 "material_cohesive_linear_friction.hh" #include "solid_mechanics_model_cohesive.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialCohesiveLinearFriction<spatial_dimension>:: MaterialCohesiveLinearFriction(SolidMechanicsModel & model, const ID & id) : MaterialParent(model, id), residual_sliding("residual_sliding", *this), friction_force("friction_force", *this) { AKANTU_DEBUG_IN(); this->registerParam("mu", mu_max, Real(0.), _pat_parsable | _pat_readable, "Maximum value of the friction coefficient"); this->registerParam("penalty_for_friction", friction_penalty, Real(0.), _pat_parsable | _pat_readable, "Penalty parameter for the friction behavior"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinearFriction<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialParent::initMaterial(); friction_force.initialize(spatial_dimension); residual_sliding.initialize(1); residual_sliding.initializeHistory(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinearFriction<spatial_dimension>::computeTraction( __attribute__((unused)) const Array<Real> & normal, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); residual_sliding.resize(); friction_force.resize(); /// define iterators Array<Real>::vector_iterator traction_it = this->tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator traction_end = this->tractions(el_type, ghost_type).end(spatial_dimension); Array<Real>::vector_iterator opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension); /// opening_prec is the opening at the end of the previous step in /// the Newton-Raphson loop Array<Real>::vector_iterator opening_prec_it = this->opening_prec(el_type, ghost_type).begin(spatial_dimension); /// opening_prec_prev is the opening (opening + penetration) /// referred to the convergence of the previous incremental step Array<Real>::vector_iterator opening_prec_prev_it = this->opening_prec.previous(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_traction_it = this->contact_tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_opening_it = this->contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::const_iterator<Vector<Real>> normal_it = this->normal.begin(spatial_dimension); Array<Real>::iterator<Real> sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::iterator<Real> delta_max_it = this->delta_max(el_type, ghost_type).begin(); Array<Real>::iterator<Real> delta_max_prev_it = this->delta_max.previous(el_type, ghost_type).begin(); Array<Real>::iterator<Real> delta_c_it = this->delta_c_eff(el_type, ghost_type).begin(); Array<Real>::iterator<Real> damage_it = this->damage(el_type, ghost_type).begin(); Array<Real>::vector_iterator insertion_stress_it = this->insertion_stress(el_type, ghost_type).begin(spatial_dimension); Array<Real>::iterator<Real> res_sliding_it = this->residual_sliding(el_type, ghost_type).begin(); Array<Real>::iterator<Real> res_sliding_prev_it = this->residual_sliding.previous(el_type, ghost_type).begin(); Array<Real>::vector_iterator friction_force_it = this->friction_force(el_type, ghost_type).begin(spatial_dimension); Array<bool>::iterator<bool> reduction_penalty_it = this->reduction_penalty(el_type, ghost_type).begin(); Vector<Real> normal_opening(spatial_dimension); Vector<Real> tangential_opening(spatial_dimension); if (!this->model->isDefaultSolverExplicit()) this->delta_max(el_type, ghost_type) .copy(this->delta_max.previous(el_type, ghost_type)); /// loop on each quadrature point for (; traction_it != traction_end; ++traction_it, ++opening_it, ++opening_prec_prev_it, ++opening_prec_it, ++normal_it, ++sigma_c_it, ++delta_max_it, ++delta_c_it, ++damage_it, ++contact_traction_it, ++insertion_stress_it, ++contact_opening_it, ++delta_max_prev_it, ++res_sliding_it, ++res_sliding_prev_it, ++friction_force_it, ++reduction_penalty_it) { Real normal_opening_norm, tangential_opening_norm; bool penetration; Real current_penalty = 0.; this->computeTractionOnQuad( *traction_it, *delta_max_it, *delta_max_prev_it, *delta_c_it, *insertion_stress_it, *sigma_c_it, *opening_it, *opening_prec_it, *normal_it, normal_opening, tangential_opening, normal_opening_norm, tangential_opening_norm, *damage_it, penetration, *reduction_penalty_it, current_penalty, *contact_traction_it, *contact_opening_it); if (penetration) { /// the friction coefficient mu increases with the damage. It /// equals the maximum value when damage = 1. // Real damage = std::min(*delta_max_prev_it / *delta_c_it, // Real(1.)); Real mu = mu_max; // * damage; /// the definition of tau_max refers to the opening /// (penetration) of the previous incremental step Real normal_opening_prev_norm = std::min(opening_prec_prev_it->dot(*normal_it), Real(0.)); // Vector<Real> normal_opening_prev = (*normal_it); // normal_opening_prev *= normal_opening_prev_norm; Real tau_max = mu * current_penalty * (std::abs(normal_opening_prev_norm)); Real delta_sliding_norm = std::abs(tangential_opening_norm - *res_sliding_prev_it); /// tau is the norm of the friction force, acting tangentially to the /// surface Real tau = std::min(friction_penalty * delta_sliding_norm, tau_max); if ((tangential_opening_norm - *res_sliding_prev_it) < 0.0) tau = -tau; /// from tau get the x and y components of friction, to be added in the /// force vector Vector<Real> tangent_unit_vector(spatial_dimension); tangent_unit_vector = tangential_opening / tangential_opening_norm; *friction_force_it = tau * tangent_unit_vector; /// update residual_sliding *res_sliding_it = tangential_opening_norm - (std::abs(tau) / friction_penalty); } else { friction_force_it->clear(); } *traction_it += *friction_force_it; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinearFriction<spatial_dimension>::checkDeltaMax( GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialParent::checkDeltaMax(); Mesh & mesh = this->fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); for (; it != last_type; ++it) { Array<UInt> & elem_filter = this->element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element == 0) continue; ElementType el_type = *it; /// define iterators Array<Real>::iterator<Real> delta_max_it = this->delta_max(el_type, ghost_type).begin(); Array<Real>::iterator<Real> delta_max_end = this->delta_max(el_type, ghost_type).end(); Array<Real>::iterator<Real> res_sliding_it = this->residual_sliding(el_type, ghost_type).begin(); Array<Real>::iterator<Real> res_sliding_prev_it = this->residual_sliding.previous(el_type, ghost_type).begin(); /// loop on each quadrature point for (; delta_max_it != delta_max_end; ++delta_max_it, ++res_sliding_it, ++res_sliding_prev_it) { /** * in case convergence is not reached, set "residual_sliding" * for the friction behaviour to the value referred to the * previous incremental step */ *res_sliding_it = *res_sliding_prev_it; } } } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinearFriction<spatial_dimension>::computeTangentTraction( const ElementType & el_type, Array<Real> & tangent_matrix, __attribute__((unused)) const Array<Real> & normal, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::matrix_iterator tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension); Array<Real>::const_vector_iterator normal_it = this->normal.begin(spatial_dimension); Array<Real>::vector_iterator opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator opening_prec_prev_it = this->opening_prec.previous(el_type, ghost_type).begin(spatial_dimension); /** * NB: delta_max_it points on delta_max_previous, i.e. the * delta_max related to the solution of the previous incremental * step */ Array<Real>::iterator<Real> delta_max_it = this->delta_max.previous(el_type, ghost_type).begin(); Array<Real>::iterator<Real> sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::iterator<Real> delta_c_it = this->delta_c_eff(el_type, ghost_type).begin(); Array<Real>::iterator<Real> damage_it = this->damage(el_type, ghost_type).begin(); Array<Real>::iterator<Vector<Real>> contact_opening_it = this->contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::iterator<Real> res_sliding_prev_it = this->residual_sliding.previous(el_type, ghost_type).begin(); Array<bool>::iterator<bool> reduction_penalty_it = this->reduction_penalty(el_type, ghost_type).begin(); Vector<Real> normal_opening(spatial_dimension); Vector<Real> tangential_opening(spatial_dimension); for (; tangent_it != tangent_end; ++tangent_it, ++normal_it, ++opening_it, ++opening_prec_prev_it, ++delta_max_it, ++sigma_c_it, ++delta_c_it, ++damage_it, ++contact_opening_it, ++res_sliding_prev_it, ++reduction_penalty_it) { Real normal_opening_norm, tangential_opening_norm; bool penetration; Real current_penalty = 0.; this->computeTangentTractionOnQuad( *tangent_it, *delta_max_it, *delta_c_it, *sigma_c_it, *opening_it, *normal_it, normal_opening, tangential_opening, normal_opening_norm, tangential_opening_norm, *damage_it, penetration, *reduction_penalty_it, current_penalty, *contact_opening_it); if (penetration) { // Real damage = std::min(*delta_max_it / *delta_c_it, Real(1.)); Real mu = mu_max; // * damage; Real normal_opening_prev_norm = std::min(opening_prec_prev_it->dot(*normal_it), Real(0.)); // Vector<Real> normal_opening_prev = (*normal_it); // normal_opening_prev *= normal_opening_prev_norm; Real tau_max = mu * current_penalty * (std::abs(normal_opening_prev_norm)); Real delta_sliding_norm = std::abs(tangential_opening_norm - *res_sliding_prev_it); // tau is the norm of the friction force, acting tangentially to the // surface Real tau = std::min(friction_penalty * delta_sliding_norm, tau_max); if (tau < tau_max && tau_max > Math::getTolerance()) { Matrix<Real> I(spatial_dimension, spatial_dimension); I.eye(1.); Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension); n_outer_n.outerProduct(*normal_it, *normal_it); Matrix<Real> nn(n_outer_n); I -= nn; *tangent_it += I * friction_penalty; } } // check if the tangential stiffness matrix is symmetric // for (UInt h = 0; h < spatial_dimension; ++h){ // for (UInt l = h; l < spatial_dimension; ++l){ // if (l > h){ // Real k_ls = (*tangent_it)[spatial_dimension*h+l]; // Real k_us = (*tangent_it)[spatial_dimension*l+h]; // // std::cout << "k_ls = " << k_ls << std::endl; // // std::cout << "k_us = " << k_us << std::endl; // if (std::abs(k_ls) > 1e-13 && std::abs(k_us) > 1e-13){ // Real error = std::abs((k_ls - k_us) / k_us); // if (error > 1e-10){ // std::cout << "non symmetric cohesive matrix" << std::endl; // // std::cout << "error " << error << std::endl; // } // } // } // } // } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialCohesiveLinearFriction); +INSTANTIATE_MATERIAL(cohesive_linear_friction, MaterialCohesiveLinearFriction); } // akantu diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.cc index 1ff0268e4..aba88eece 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear_uncoupled.cc @@ -1,596 +1,596 @@ /** * @file material_cohesive_linear_uncoupled.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date creation: Wed Feb 22 2012 * @date last modification: Thu Jan 14 2016 * * @brief Linear irreversible cohesive law of mixed mode loading with * random stress definition for extrinsic 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 <algorithm> #include <numeric> /* -------------------------------------------------------------------------- */ #include "material_cohesive_linear_uncoupled.hh" #include "solid_mechanics_model_cohesive.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialCohesiveLinearUncoupled<spatial_dimension>:: MaterialCohesiveLinearUncoupled(SolidMechanicsModel & model, const ID & id) : MaterialCohesiveLinear<spatial_dimension>(model, id), delta_n_max("delta_n_max", *this), delta_t_max("delta_t_max", *this), damage_n("damage_n", *this), damage_t("damage_t", *this) { AKANTU_DEBUG_IN(); this->registerParam( "roughness", R, Real(1.), _pat_parsable | _pat_readable, "Roughness to define coupling between mode II and mode I"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinearUncoupled<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialCohesiveLinear<spatial_dimension>::initMaterial(); delta_n_max.initialize(1); delta_t_max.initialize(1); damage_n.initialize(1); damage_t.initialize(1); delta_n_max.initializeHistory(); delta_t_max.initializeHistory(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinearUncoupled<spatial_dimension>::computeTraction( const Array<Real> &, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); delta_n_max.resize(); delta_t_max.resize(); damage_n.resize(); damage_t.resize(); /// define iterators Array<Real>::vector_iterator traction_it = this->tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator traction_end = this->tractions(el_type, ghost_type).end(spatial_dimension); Array<Real>::vector_iterator opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension); /// opening_prec is the opening of the previous step in the /// Newton-Raphson loop Array<Real>::vector_iterator opening_prec_it = this->opening_prec(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_traction_it = this->contact_tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator contact_opening_it = this->contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::const_vector_iterator normal_it = this->normal.begin(spatial_dimension); Array<Real>::scalar_iterator sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_n_max_it = delta_n_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_t_max_it = delta_t_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_c_it = this->delta_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_n_it = damage_n(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_t_it = damage_t(el_type, ghost_type).begin(); Array<Real>::vector_iterator insertion_stress_it = this->insertion_stress(el_type, ghost_type).begin(spatial_dimension); Array<bool>::scalar_iterator reduction_penalty_it = this->reduction_penalty(el_type, ghost_type).begin(); Vector<Real> normal_opening(spatial_dimension); Vector<Real> tangential_opening(spatial_dimension); if (!this->model->isDefaultSolverExplicit()) { this->delta_n_max(el_type, ghost_type) .copy(this->delta_n_max.previous(el_type, ghost_type)); this->delta_t_max(el_type, ghost_type) .copy(this->delta_t_max.previous(el_type, ghost_type)); } /// loop on each quadrature point for (; traction_it != traction_end; ++traction_it, ++opening_it, ++opening_prec_it, ++contact_traction_it, ++contact_opening_it, ++normal_it, ++sigma_c_it, ++delta_n_max_it, ++delta_t_max_it, ++delta_c_it, ++damage_n_it, ++damage_t_it, ++insertion_stress_it, ++reduction_penalty_it) { Real normal_opening_norm, tangential_opening_norm; bool penetration; Real current_penalty = 0.; Real delta_c2_R2 = *delta_c_it * (*delta_c_it) / R / R; /// compute normal and tangential opening vectors normal_opening_norm = opening_it->dot(*normal_it); Vector<Real> normal_opening = *normal_it; normal_opening *= normal_opening_norm; // std::cout<< "normal_opening_norm = " << normal_opening_norm // <<std::endl; Vector<Real> tangential_opening = *opening_it; tangential_opening -= normal_opening; tangential_opening_norm = tangential_opening.norm(); /// compute effective opening displacement Real delta_n = tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2; Real delta_t = tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2; penetration = normal_opening_norm < 0.0; if (this->contact_after_breaking == false && Math::are_float_equal(*damage_n_it, 1.)) penetration = false; /** * If during the convergence loop a cohesive element continues to * jumps from penetration to opening, and convergence is not * reached, its penalty parameter will be reduced in the * recomputation of the same incremental step. Recompute is set * equal to true when convergence is not reached in the * solveStepCohesive function and the execution of the program * goes back to the main file where the variable load_reduction * is set equal to true. */ Real normal_opening_prec_norm = opening_prec_it->dot(*normal_it); // Vector<Real> normal_opening_prec = *normal_it; // normal_opening_prec *= normal_opening_prec_norm; if (!this->model->isDefaultSolverExplicit()) // && !this->recompute) if ((normal_opening_prec_norm * normal_opening_norm) < 0.0) *reduction_penalty_it = true; *opening_prec_it = *opening_it; if (penetration) { if (this->recompute && *reduction_penalty_it) { /// the penalty parameter is locally reduced current_penalty = this->penalty / 100.; } else current_penalty = this->penalty; /// use penalty coefficient in case of penetration *contact_traction_it = normal_opening; *contact_traction_it *= current_penalty; *contact_opening_it = normal_opening; /// don't consider penetration contribution for delta *opening_it = tangential_opening; normal_opening.clear(); } else { delta_n += normal_opening_norm * normal_opening_norm; delta_t += normal_opening_norm * normal_opening_norm * delta_c2_R2; contact_traction_it->clear(); contact_opening_it->clear(); } delta_n = std::sqrt(delta_n); delta_t = std::sqrt(delta_t); /// update maximum displacement and damage *delta_n_max_it = std::max(*delta_n_max_it, delta_n); *damage_n_it = std::min(*delta_n_max_it / *delta_c_it, Real(1.)); *delta_t_max_it = std::max(*delta_t_max_it, delta_t); *damage_t_it = std::min(*delta_t_max_it / *delta_c_it, Real(1.)); Vector<Real> normal_traction(spatial_dimension); Vector<Real> shear_traction(spatial_dimension); /// NORMAL TRACTIONS if (Math::are_float_equal(*damage_n_it, 1.)) normal_traction.clear(); else if (Math::are_float_equal(*damage_n_it, 0.)) { if (penetration) normal_traction.clear(); else normal_traction = *insertion_stress_it; } else { // the following formulation holds both in loading and in // unloading-reloading normal_traction = normal_opening; AKANTU_DEBUG_ASSERT(*delta_n_max_it != 0., "Division by zero, tolerance might be too low"); normal_traction *= *sigma_c_it / (*delta_n_max_it) * (1. - *damage_n_it); } /// SHEAR TRACTIONS if (Math::are_float_equal(*damage_t_it, 1.)) shear_traction.clear(); else if (Math::are_float_equal(*damage_t_it, 0.)) { shear_traction.clear(); } else { shear_traction = tangential_opening; AKANTU_DEBUG_ASSERT(*delta_t_max_it != 0., "Division by zero, tolerance might be too low"); shear_traction *= this->beta2_kappa; shear_traction *= *sigma_c_it / (*delta_t_max_it) * (1. - *damage_t_it); } *traction_it = normal_traction; *traction_it += shear_traction; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinearUncoupled<spatial_dimension>::checkDeltaMax( GhostType ghost_type) { AKANTU_DEBUG_IN(); /** * This function set a predefined value to the parameter * delta_max_prev of the elements that have been inserted in the * last loading step for which convergence has not been * reached. This is done before reducing the loading and re-doing * the step. Otherwise, the updating of delta_max_prev would be * done with reference to the non-convergent solution. In this * function also other variables related to the contact and * friction behavior are correctly set. */ Mesh & mesh = this->fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); /** * the variable "recompute" is set to true to activate the * procedure that reduces the penalty parameter for * compression. This procedure is available only during the phase of * load_reduction, that has to be set in the main file. The * penalty parameter will be reduced only for the elements having * reduction_penalty = true. */ this->recompute = true; for (; it != last_type; ++it) { Array<UInt> & elem_filter = this->element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element == 0) continue; ElementType el_type = *it; // std::cout << "element type: " << el_type << std::endl; /// define iterators Array<Real>::scalar_iterator delta_n_max_it = delta_n_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_n_max_end = delta_n_max(el_type, ghost_type).end(); Array<Real>::scalar_iterator delta_n_max_prev_it = delta_n_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_t_max_it = delta_t_max(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_t_max_prev_it = delta_t_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_c_it = this->delta_c_eff(el_type, ghost_type).begin(); Array<Real>::vector_iterator opening_prec_it = this->opening_prec(el_type, ghost_type).begin(spatial_dimension); Array<Real>::vector_iterator opening_prec_prev_it = this->opening_prec.previous(el_type, ghost_type) .begin(spatial_dimension); Int it = 0; /// loop on each quadrature point for (; delta_n_max_it != delta_n_max_end; ++delta_n_max_it, ++delta_t_max_it, ++delta_c_it, ++delta_n_max_prev_it, ++delta_t_max_prev_it, ++opening_prec_it, ++opening_prec_prev_it) { ++it; if (*delta_n_max_prev_it == 0) { /// elements inserted in the last incremental step, that did /// not converge *delta_n_max_it = *delta_c_it / 1000.; } else /// elements introduced in previous incremental steps, for /// which a correct value of delta_max_prev already exists *delta_n_max_it = *delta_n_max_prev_it; if (*delta_t_max_prev_it == 0) { *delta_t_max_it = *delta_c_it * this->kappa / this->beta / 1000.; } else *delta_t_max_it = *delta_t_max_prev_it; /// in case convergence is not reached, set opening_prec to the /// value referred to the previous incremental step *opening_prec_it = *opening_prec_prev_it; } } } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialCohesiveLinearUncoupled<spatial_dimension>::computeTangentTraction( const ElementType & el_type, Array<Real> & tangent_matrix, const Array<Real> &, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::matrix_iterator tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension); Array<Real>::const_vector_iterator normal_it = this->normal.begin(spatial_dimension); Array<Real>::vector_iterator opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension); /// NB: delta_max_it points on delta_max_previous, i.e. the /// delta_max related to the solution of the previous incremental /// step Array<Real>::scalar_iterator delta_n_max_it = delta_n_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_t_max_it = delta_t_max.previous(el_type, ghost_type).begin(); Array<Real>::scalar_iterator sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator delta_c_it = this->delta_c_eff(el_type, ghost_type).begin(); Array<Real>::scalar_iterator damage_n_it = damage_n(el_type, ghost_type).begin(); Array<Real>::vector_iterator contact_opening_it = this->contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<bool>::scalar_iterator reduction_penalty_it = this->reduction_penalty(el_type, ghost_type).begin(); Vector<Real> normal_opening(spatial_dimension); Vector<Real> tangential_opening(spatial_dimension); for (; tangent_it != tangent_end; ++tangent_it, ++normal_it, ++opening_it, ++sigma_c_it, ++delta_c_it, ++delta_n_max_it, ++delta_t_max_it, ++damage_n_it, ++contact_opening_it, ++reduction_penalty_it) { Real normal_opening_norm, tangential_opening_norm; bool penetration; Real current_penalty = 0.; Real delta_c2_R2 = *delta_c_it * (*delta_c_it) / R / R; /** * During the update of the residual the interpenetrations are * stored in the array "contact_opening", therefore, in the case * of penetration, in the array "opening" there are only the * tangential components. */ *opening_it += *contact_opening_it; /// compute normal and tangential opening vectors normal_opening_norm = opening_it->dot(*normal_it); Vector<Real> normal_opening = *normal_it; normal_opening *= normal_opening_norm; Vector<Real> tangential_opening = *opening_it; tangential_opening -= normal_opening; tangential_opening_norm = tangential_opening.norm(); Real delta_n = tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2; Real delta_t = tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2; penetration = normal_opening_norm < 0.0; if (this->contact_after_breaking == false && Math::are_float_equal(*damage_n_it, 1.)) penetration = false; Real derivative = 0; // derivative = d(t/delta)/ddelta Real T = 0; /// TANGENT STIFFNESS FOR NORMAL TRACTIONS Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension); n_outer_n.outerProduct(*normal_it, *normal_it); if (penetration) { if (this->recompute && *reduction_penalty_it) current_penalty = this->penalty / 100.; else current_penalty = this->penalty; /// stiffness in compression given by the penalty parameter *tangent_it = n_outer_n; *tangent_it *= current_penalty; *opening_it = tangential_opening; normal_opening.clear(); } else { delta_n += normal_opening_norm * normal_opening_norm; delta_n = std::sqrt(delta_n); delta_t += normal_opening_norm * normal_opening_norm * delta_c2_R2; /** * Delta has to be different from 0 to have finite values of * tangential stiffness. At the element insertion, delta = * 0. Therefore, a fictictious value is defined, for the * evaluation of the first value of K. */ if (delta_n < Math::getTolerance()) delta_n = *delta_c_it / 1000.; // loading if (delta_n >= *delta_n_max_it) { if (delta_n <= *delta_c_it) { derivative = -(*sigma_c_it) / (delta_n * delta_n); T = *sigma_c_it * (1 - delta_n / *delta_c_it); } else { derivative = 0.; T = 0.; } // unloading-reloading } else if (delta_n < *delta_n_max_it) { Real T_max = *sigma_c_it * (1 - *delta_n_max_it / *delta_c_it); derivative = 0.; T = T_max / *delta_n_max_it * delta_n; } /// computation of the derivative of the constitutive law (dT/ddelta) Matrix<Real> nn(n_outer_n); nn *= T / delta_n; Vector<Real> Delta_tilde(normal_opening); Delta_tilde *= (1. - this->beta2_kappa2); Vector<Real> mm(*opening_it); mm *= this->beta2_kappa2; Delta_tilde += mm; Vector<Real> Delta_hat(normal_opening); Matrix<Real> prov(spatial_dimension, spatial_dimension); prov.outerProduct(Delta_hat, Delta_tilde); prov *= derivative / delta_n; prov += nn; Matrix<Real> prov_t = prov.transpose(); *tangent_it = prov_t; } derivative = 0.; T = 0.; /// TANGENT STIFFNESS FOR SHEAR TRACTIONS delta_t = std::sqrt(delta_t); /** * Delta has to be different from 0 to have finite values of * tangential stiffness. At the element insertion, delta = * 0. Therefore, a fictictious value is defined, for the * evaluation of the first value of K. */ if (delta_t < Math::getTolerance()) delta_t = *delta_c_it / 1000.; // loading if (delta_t >= *delta_t_max_it) { if (delta_t <= *delta_c_it) { derivative = -(*sigma_c_it) / (delta_t * delta_t); T = *sigma_c_it * (1 - delta_t / *delta_c_it); } else { derivative = 0.; T = 0.; } // unloading-reloading } else if (delta_t < *delta_t_max_it) { Real T_max = *sigma_c_it * (1 - *delta_t_max_it / *delta_c_it); derivative = 0.; T = T_max / *delta_t_max_it * delta_t; } /// computation of the derivative of the constitutive law (dT/ddelta) Matrix<Real> I(spatial_dimension, spatial_dimension); I.eye(); Matrix<Real> nn(n_outer_n); I -= nn; I *= T / delta_t; Vector<Real> Delta_tilde(normal_opening); Delta_tilde *= (delta_c2_R2 - this->beta2_kappa2); Vector<Real> mm(*opening_it); mm *= this->beta2_kappa2; Delta_tilde += mm; Vector<Real> Delta_hat(tangential_opening); Delta_hat *= this->beta2_kappa; Matrix<Real> prov(spatial_dimension, spatial_dimension); prov.outerProduct(Delta_hat, Delta_tilde); prov *= derivative / delta_t; prov += I; Matrix<Real> prov_t = prov.transpose(); *tangent_it += prov_t; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialCohesiveLinearUncoupled); +INSTANTIATE_MATERIAL(cohesive_linear_uncoupled, MaterialCohesiveLinearUncoupled); } // akantu diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo.cc b/src/model/solid_mechanics/materials/material_damage/material_marigo.cc index cdf3cb3b3..83738f986 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_marigo.cc +++ b/src/model/solid_mechanics/materials/material_damage/material_marigo.cc @@ -1,107 +1,107 @@ /** * @file material_marigo.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 08 2015 * * @brief Specialization of the material class for the marigo material * * @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 "material_marigo.hh" #include "solid_mechanics_model.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialMarigo<spatial_dimension>::MaterialMarigo(SolidMechanicsModel & model, const ID & id) : MaterialDamage<spatial_dimension>(model, id), Yd("Yd", *this), damage_in_y(false), yc_limit(false) { AKANTU_DEBUG_IN(); this->registerParam("Sd", Sd, Real(5000.), _pat_parsable | _pat_modifiable); this->registerParam("epsilon_c", epsilon_c, Real(0.), _pat_parsable, "Critical strain"); this->registerParam("Yc limit", yc_limit, false, _pat_internal, "As the material a critical Y"); this->registerParam("damage_in_y", damage_in_y, false, _pat_parsable, "Use threshold (1-D)Y"); this->registerParam("Yd", Yd, _pat_parsable, "Damaging energy threshold"); this->Yd.initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMarigo<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialDamage<spatial_dimension>::initMaterial(); updateInternalParameters(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMarigo<spatial_dimension>::updateInternalParameters() { MaterialDamage<spatial_dimension>::updateInternalParameters(); Yc = .5 * epsilon_c * this->E * epsilon_c; if (std::abs(epsilon_c) > std::numeric_limits<Real>::epsilon()) yc_limit = true; else yc_limit = false; } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMarigo<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real>::scalar_iterator dam = this->damage(el_type, ghost_type).begin(); Array<Real>::scalar_iterator Yd_q = this->Yd(el_type, ghost_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Real Y = 0.; computeStressOnQuad(grad_u, sigma, *dam, Y, *Yd_q); ++dam; ++Yd_q; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } -INSTANTIATE_MATERIAL(MaterialMarigo); +INSTANTIATE_MATERIAL(marigo, MaterialMarigo); } // namespace akantu diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local_inline_impl.cc b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.cc similarity index 89% rename from src/model/solid_mechanics/materials/material_damage/material_marigo_non_local_inline_impl.cc rename to src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.cc index dedf2d443..7258ef8db 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local_inline_impl.cc +++ b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.cc @@ -1,114 +1,106 @@ /** - * @file material_marigo_non_local_inline_impl.cc + * @file material_marigo_non_local.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 15 2015 * * @brief Marigo non-local inline function implementation * * @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 "material_marigo_non_local.hh" #include "non_local_neighborhood_base.hh" /* -------------------------------------------------------------------------- */ -#if defined(AKANTU_DEBUG_TOOLS) -#include "aka_debug_tools.hh" -#include <string> -#endif -/* -------------------------------------------------------------------------- */ - -#ifndef __AKANTU_MATERIAL_MARIGO_NON_LOCAL_INLINE_IMPL_CC__ -#define __AKANTU_MATERIAL_MARIGO_NON_LOCAL_INLINE_IMPL_CC__ namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialMarigoNonLocal<spatial_dimension>::MaterialMarigoNonLocal( SolidMechanicsModel & model, const ID & id) : MaterialMarigoNonLocalParent(model, id), Y("Y", *this), Ynl("Y non local", *this) { AKANTU_DEBUG_IN(); this->is_non_local = true; this->Y.initialize(1); this->Ynl.initialize(1); this->model.registerNonLocalVariable(this->Y.getName(), Ynl.getName(), 1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMarigoNonLocal<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialMarigoNonLocalParent::initMaterial(); this->model.getNeighborhood(this->name).registerNonLocalVariable(Ynl.getName()); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMarigoNonLocal<spatial_dimension>::computeStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = this->damage(el_type, ghost_type).storage(); Real * Yt = this->Y(el_type, ghost_type).storage(); Real * Ydq = this->Yd(el_type, ghost_type).storage(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); MaterialMarigo<spatial_dimension>::computeStressOnQuad(grad_u, sigma, *dam, *Yt, *Ydq); ++dam; ++Yt; ++Ydq; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMarigoNonLocal<spatial_dimension>::computeNonLocalStress( ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = this->damage(type, ghost_type).storage(); Real * Ydq = this->Yd(type, ghost_type).storage(); Real * Ynlt = this->Ynl(type, ghost_type).storage(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(type, ghost_type); this->computeDamageAndStressOnQuad(sigma, *dam, *Ynlt, *Ydq); ++dam; ++Ynlt; ++Ydq; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } -} // namespace akantu +INSTANTIATE_MATERIAL(marigo_non_local, MaterialMarigoNonLocal); -#endif /* __AKANTU_MATERIAL_MARIGO_NON_LOCAL_INLINE_IMPL_CC__ */ +} // namespace akantu diff --git a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh index 76e170825..17743144b 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh +++ b/src/model/solid_mechanics/materials/material_damage/material_marigo_non_local.hh @@ -1,98 +1,96 @@ /** * @file material_marigo_non_local.hh * * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 15 2015 * * @brief Marigo non-local description * * @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 "material_damage_non_local.hh" #include "material_marigo.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_MARIGO_NON_LOCAL_HH__ #define __AKANTU_MATERIAL_MARIGO_NON_LOCAL_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ /** * Material Marigo * * parameters in the material files : */ template <UInt spatial_dimension> class MaterialMarigoNonLocal : public MaterialDamageNonLocal<spatial_dimension, MaterialMarigo<spatial_dimension>> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef MaterialDamageNonLocal<spatial_dimension, MaterialMarigo<spatial_dimension>> MaterialMarigoNonLocalParent; MaterialMarigoNonLocal(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialMarigoNonLocal(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); protected: /// constitutive law void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); void computeNonLocalStress(ElementType type, GhostType ghost_type = _not_ghost); private: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Y, Y, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: InternalField<Real> Y; InternalField<Real> Ynl; }; } // namespace akantu -#include "material_marigo_non_local_inline_impl.cc" - #endif /* __AKANTU_MATERIAL_MARIGO_NON_LOCAL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars.cc b/src/model/solid_mechanics/materials/material_damage/material_mazars.cc index 52e5ddfbf..fdba78438 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_mazars.cc +++ b/src/model/solid_mechanics/materials/material_damage/material_mazars.cc @@ -1,82 +1,82 @@ /** * @file material_mazars.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Aug 18 2015 * * @brief Specialization of the material class for the damage material * * @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 "material_mazars.hh" #include "solid_mechanics_model.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialMazars<spatial_dimension>::MaterialMazars(SolidMechanicsModel & model, const ID & id) : MaterialDamage<spatial_dimension>(model, id), K0("K0", *this), damage_in_compute_stress(true) { AKANTU_DEBUG_IN(); this->registerParam("K0", K0, _pat_parsable, "K0"); this->registerParam("At", At, Real(0.8), _pat_parsable, "At"); this->registerParam("Ac", Ac, Real(1.4), _pat_parsable, "Ac"); this->registerParam("Bc", Bc, Real(1900.), _pat_parsable, "Bc"); this->registerParam("Bt", Bt, Real(12000.), _pat_parsable, "Bt"); this->registerParam("beta", beta, Real(1.06), _pat_parsable, "beta"); this->K0.initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMazars<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = this->damage(el_type, ghost_type).storage(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Real Ehat = 0; computeStressOnQuad(grad_u, sigma, *dam, Ehat); ++dam; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialMazars); +INSTANTIATE_MATERIAL(mazars, MaterialMazars); } // namespace akantu diff --git a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc index 93d3211d3..07e1f2a05 100644 --- a/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc +++ b/src/model/solid_mechanics/materials/material_damage/material_mazars_non_local.cc @@ -1,147 +1,147 @@ /** * @file material_mazars_non_local.cc * * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Thu Oct 15 2015 * * @brief Specialization of the material class for the non-local mazars * material * * @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 "material_mazars_non_local.hh" #include "solid_mechanics_model.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialMazarsNonLocal<spatial_dimension>::MaterialMazarsNonLocal( SolidMechanicsModel & model, const ID & id) : MaterialNonLocalParent(model, id), Ehat("epsilon_equ", *this) { AKANTU_DEBUG_IN(); this->is_non_local = true; this->Ehat.initialize(1); this->registerParam("average_on_damage", this->damage_in_compute_stress, false, _pat_parsable | _pat_modifiable, "Is D the non local variable"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMazarsNonLocal<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialNonLocalParent::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMazarsNonLocal<spatial_dimension>::computeStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * damage = this->damage(el_type, ghost_type).storage(); Real * epsilon_equ = this->Ehat(el_type, ghost_type).storage(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); MaterialMazars<spatial_dimension>::computeStressOnQuad(grad_u, sigma, *damage, *epsilon_equ); ++damage; ++epsilon_equ; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMazarsNonLocal<spatial_dimension>::computeNonLocalStresses( __attribute__((unused)) GhostType ghost_type) { AKANTU_DEBUG_IN(); InternalField<Real> nl_var("Non local variable", *this); nl_var.initialize(1); // if(this->damage_in_compute_stress) // this->weightedAvergageOnNeighbours(this->damage, nl_var, 1); // else // this->weightedAvergageOnNeighbours(this->Ehat, nl_var, 1); // Mesh::type_iterator it = // this->model->getFEEngine().getMesh().firstType(spatial_dimension, // ghost_type); // Mesh::type_iterator last_type = // this->model->getFEEngine().getMesh().lastType(spatial_dimension, // ghost_type); // for(; it != last_type; ++it) { // this->computeNonLocalStress(nl_var(*it, ghost_type), *it, ghost_type); // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMazarsNonLocal<spatial_dimension>::computeNonLocalStress( Array<Real> & non_loc_var, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * damage; Real * epsilon_equ; if (this->damage_in_compute_stress) { damage = non_loc_var.storage(); epsilon_equ = this->Ehat(el_type, ghost_type).storage(); } else { damage = this->damage(el_type, ghost_type).storage(); epsilon_equ = non_loc_var.storage(); } MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); this->computeDamageAndStressOnQuad(grad_u, sigma, *damage, *epsilon_equ); ++damage; ++epsilon_equ; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialMazarsNonLocal< spatial_dimension>::nonLocalVariableToNeighborhood() {} -INSTANTIATE_MATERIAL(MaterialMazarsNonLocal); +INSTANTIATE_MATERIAL(mazars_non_local, MaterialMazarsNonLocal); } // akantu diff --git a/src/model/solid_mechanics/materials/material_elastic.cc b/src/model/solid_mechanics/materials/material_elastic.cc index 34a25ce7d..b108afe8b 100644 --- a/src/model/solid_mechanics/materials/material_elastic.cc +++ b/src/model/solid_mechanics/materials/material_elastic.cc @@ -1,254 +1,254 @@ /** * @file material_elastic.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@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 Oct 15 2015 * * @brief Specialization of the material class for the elastic material * * @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 "material_elastic.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialElastic<dim>::MaterialElastic(SolidMechanicsModel & model, const ID & id) : Parent(model, id), was_stiffness_assembled(false) { AKANTU_DEBUG_IN(); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialElastic<dim>::MaterialElastic(SolidMechanicsModel & model, __attribute__((unused)) UInt a_dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id) : Parent(model, dim, mesh, fe_engine, id), was_stiffness_assembled(false) { AKANTU_DEBUG_IN(); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElastic<dim>::initialize() { this->registerParam("lambda", lambda, _pat_readable, "First Lamé coefficient"); this->registerParam("mu", mu, _pat_readable, "Second Lamé coefficient"); this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient"); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElastic<dim>::initMaterial() { AKANTU_DEBUG_IN(); Parent::initMaterial(); if (dim == 1) this->nu = 0.; this->updateInternalParameters(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElastic<dim>::updateInternalParameters() { MaterialThermal<dim>::updateInternalParameters(); this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2 * this->nu)); this->mu = this->E / (2 * (1 + this->nu)); this->kpa = this->lambda + 2. / 3. * this->mu; this->was_stiffness_assembled = false; } /* -------------------------------------------------------------------------- */ template <> void MaterialElastic<2>::updateInternalParameters() { MaterialThermal<2>::updateInternalParameters(); this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2 * this->nu)); this->mu = this->E / (2 * (1 + this->nu)); if (this->plane_stress) this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - this->nu)); this->kpa = this->lambda + 2. / 3. * this->mu; this->was_stiffness_assembled = false; } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialElastic<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Parent::computeStress(el_type, ghost_type); Array<Real>::const_scalar_iterator sigma_th_it = this->sigma_th(el_type, ghost_type).begin(); if (!this->finite_deformation) { MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); const Real & sigma_th = *sigma_th_it; this->computeStressOnQuad(grad_u, sigma, sigma_th); ++sigma_th_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } else { /// finite gradus Matrix<Real> E(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); /// compute E this->template gradUToGreenStrain<spatial_dimension>(grad_u, E); const Real & sigma_th = *sigma_th_it; /// compute second Piola-Kirchhoff stress tensor this->computeStressOnQuad(E, sigma, sigma_th); ++sigma_th_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialElastic<spatial_dimension>::computeTangentModuli( const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type) { AKANTU_DEBUG_IN(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); this->computeTangentModuliOnQuad(tangent); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; this->was_stiffness_assembled = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> Real MaterialElastic<spatial_dimension>::getPushWaveSpeed( const Element &) const { return sqrt((lambda + 2 * mu) / this->rho); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> Real MaterialElastic<spatial_dimension>::getShearWaveSpeed( const Element &) const { return sqrt(mu / this->rho); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialElastic<spatial_dimension>::computePotentialEnergy( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialThermal<spatial_dimension>::computePotentialEnergy(el_type, ghost_type); if (ghost_type != _not_ghost) return; auto epot = this->potential_energy(el_type, ghost_type).begin(); if (!this->finite_deformation) { MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); this->computePotentialEnergyOnQuad(grad_u, sigma, *epot); ++epot; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } else { Matrix<Real> E(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); this->template gradUToGreenStrain<spatial_dimension>(grad_u, E); this->computePotentialEnergyOnQuad(E, sigma, *epot); ++epot; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialElastic<spatial_dimension>::computePotentialEnergyByElement( ElementType type, UInt index, Vector<Real> & epot_on_quad_points) { auto gradu_it = this->gradu(type).begin(spatial_dimension, spatial_dimension); auto gradu_end = this->gradu(type).begin(spatial_dimension, spatial_dimension); auto stress_it = this->stress(type).begin(spatial_dimension, spatial_dimension); if (this->finite_deformation) stress_it = this->piola_kirchhoff_2(type).begin(spatial_dimension, spatial_dimension); UInt nb_quadrature_points = this->fem.getNbIntegrationPoints(type); gradu_it += index * nb_quadrature_points; gradu_end += (index + 1) * nb_quadrature_points; stress_it += index * nb_quadrature_points; Real * epot_quad = epot_on_quad_points.storage(); Matrix<Real> grad_u(spatial_dimension, spatial_dimension); for (; gradu_it != gradu_end; ++gradu_it, ++stress_it, ++epot_quad) { if (this->finite_deformation) this->template gradUToGreenStrain<spatial_dimension>(*gradu_it, grad_u); else grad_u.copy(*gradu_it); this->computePotentialEnergyOnQuad(grad_u, *stress_it, *epot_quad); } } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialElastic); +INSTANTIATE_MATERIAL(elastic, MaterialElastic); } // akantu diff --git a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc index 3780a6fea..89ef1e5c9 100644 --- a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc +++ b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc @@ -1,313 +1,313 @@ /** * @file material_elastic_linear_anisotropic.cc * * @author Till Junge <till.junge@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Sep 25 2013 * @date last modification: Thu Oct 15 2015 * * @brief Anisotropic elastic material * * @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 "material_elastic_linear_anisotropic.hh" #include "solid_mechanics_model.hh" #include <algorithm> #include <sstream> namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialElasticLinearAnisotropic<dim>::MaterialElasticLinearAnisotropic( SolidMechanicsModel & model, const ID & id, bool symmetric) : Material(model, id), rot_mat(dim, dim), Cprime(dim * dim, dim * dim), C(voigt_h::size, voigt_h::size), eigC(voigt_h::size), symmetric(symmetric), alpha(0), was_stiffness_assembled(false) { AKANTU_DEBUG_IN(); this->dir_vecs.push_back(new Vector<Real>(dim)); (*this->dir_vecs.back())[0] = 1.; this->registerParam("n1", *(this->dir_vecs.back()), _pat_parsmod, "Direction of main material axis"); this->dir_vecs.push_back(new Vector<Real>(dim)); (*this->dir_vecs.back())[1] = 1.; this->registerParam("n2", *(this->dir_vecs.back()), _pat_parsmod, "Direction of secondary material axis"); if (dim > 2) { this->dir_vecs.push_back(new Vector<Real>(dim)); (*this->dir_vecs.back())[2] = 1.; this->registerParam("n3", *(this->dir_vecs.back()), _pat_parsmod, "Direction of tertiary material axis"); } for (UInt i = 0; i < voigt_h::size; ++i) { UInt start = 0; if (this->symmetric) { start = i; } for (UInt j = start; j < voigt_h::size; ++j) { std::stringstream param("C"); param << "C" << i + 1 << j + 1; this->registerParam(param.str(), this->Cprime(i, j), Real(0.), _pat_parsmod, "Coefficient " + param.str()); } } this->registerParam("alpha", this->alpha, _pat_parsmod, "Proportion of viscous stress"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialElasticLinearAnisotropic<dim>::~MaterialElasticLinearAnisotropic() { for (UInt i = 0; i < dim; ++i) { delete this->dir_vecs[i]; } } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElasticLinearAnisotropic<dim>::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); updateInternalParameters(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElasticLinearAnisotropic<dim>::updateInternalParameters() { Material::updateInternalParameters(); if (this->symmetric) { for (UInt i = 0; i < voigt_h::size; ++i) { for (UInt j = i + 1; j < voigt_h::size; ++j) { this->Cprime(j, i) = this->Cprime(i, j); } } } this->rotateCprime(); this->C.eig(this->eigC); this->was_stiffness_assembled = false; } /* -------------------------------------------------------------------------- */ template <UInt Dim> void MaterialElasticLinearAnisotropic<Dim>::rotateCprime() { // start by filling the empty parts fo Cprime UInt diff = Dim * Dim - voigt_h::size; for (UInt i = voigt_h::size; i < Dim * Dim; ++i) { for (UInt j = 0; j < Dim * Dim; ++j) { this->Cprime(i, j) = this->Cprime(i - diff, j); } } for (UInt i = 0; i < Dim * Dim; ++i) { for (UInt j = voigt_h::size; j < Dim * Dim; ++j) { this->Cprime(i, j) = this->Cprime(i, j - diff); } } // construction of rotator tensor // normalise rotation matrix for (UInt j = 0; j < Dim; ++j) { Vector<Real> rot_vec = this->rot_mat(j); rot_vec = *this->dir_vecs[j]; rot_vec.normalize(); } // make sure the vectors form a right-handed base Vector<Real> test_axis(3); Vector<Real> v1(3), v2(3), v3(3); if (Dim == 2) { for (UInt i = 0; i < Dim; ++i) { v1[i] = this->rot_mat(0, i); v2[i] = this->rot_mat(1, i); v3[i] = 0.; } v3[2] = 1.; v1[2] = 0.; v2[2] = 0.; } else if (Dim == 3) { v1 = this->rot_mat(0); v2 = this->rot_mat(1); v3 = this->rot_mat(2); } test_axis.crossProduct(v1, v2); test_axis -= v3; if (test_axis.norm() > 8 * std::numeric_limits<Real>::epsilon()) { AKANTU_DEBUG_ERROR("The axis vectors do not form a right-handed coordinate " << "system. I. e., ||n1 x n2 - n3|| should be zero, but " << "it is " << test_axis.norm() << "."); } // create the rotator and the reverse rotator Matrix<Real> rotator(Dim * Dim, Dim * Dim); Matrix<Real> revrotor(Dim * Dim, Dim * Dim); for (UInt i = 0; i < Dim; ++i) { for (UInt j = 0; j < Dim; ++j) { for (UInt k = 0; k < Dim; ++k) { for (UInt l = 0; l < Dim; ++l) { UInt I = voigt_h::mat[i][j]; UInt J = voigt_h::mat[k][l]; rotator(I, J) = this->rot_mat(k, i) * this->rot_mat(l, j); revrotor(I, J) = this->rot_mat(i, k) * this->rot_mat(j, l); } } } } // create the full rotated matrix Matrix<Real> Cfull(Dim * Dim, Dim * Dim); Cfull = rotator * Cprime * revrotor; for (UInt i = 0; i < voigt_h::size; ++i) { for (UInt j = 0; j < voigt_h::size; ++j) { this->C(i, j) = Cfull(i, j); } } } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElasticLinearAnisotropic<dim>::computeStress( ElementType el_type, GhostType ghost_type) { // Wikipedia convention: // 2*eps_ij (i!=j) = voigt_eps_I // http://en.wikipedia.org/wiki/Voigt_notation AKANTU_DEBUG_IN(); Array<Real>::iterator<Matrix<Real>> gradu_it = this->gradu(el_type, ghost_type).begin(dim, dim); Array<Real>::iterator<Matrix<Real>> gradu_end = this->gradu(el_type, ghost_type).end(dim, dim); UInt nb_quad_pts = gradu_end - gradu_it; // create array for strains and stresses of all dof of all gauss points // for efficient computation of stress Matrix<Real> voigt_strains(voigt_h::size, nb_quad_pts); Matrix<Real> voigt_stresses(voigt_h::size, nb_quad_pts); // copy strains Matrix<Real> strain(dim, dim); for (UInt q = 0; gradu_it != gradu_end; ++gradu_it, ++q) { Matrix<Real> & grad_u = *gradu_it; for (UInt I = 0; I < voigt_h::size; ++I) { Real voigt_factor = voigt_h::factors[I]; UInt i = voigt_h::vec[I][0]; UInt j = voigt_h::vec[I][1]; voigt_strains(I, q) = voigt_factor * (grad_u(i, j) + grad_u(j, i)) / 2.; } } // compute the strain rate proportional part if needed // bool viscous = this->alpha == 0.; // only works if default value bool viscous = false; if (viscous) { Array<Real> strain_rate(0, dim * dim, "strain_rate"); Array<Real> & velocity = this->model.getVelocity(); const Array<UInt> & elem_filter = this->element_filter(el_type, ghost_type); this->fem.gradientOnIntegrationPoints( velocity, strain_rate, dim, el_type, ghost_type, elem_filter); Array<Real>::matrix_iterator gradu_dot_it = strain_rate.begin(dim, dim); Array<Real>::matrix_iterator gradu_dot_end = strain_rate.end(dim, dim); Matrix<Real> strain_dot(dim, dim); for (UInt q = 0; gradu_dot_it != gradu_dot_end; ++gradu_dot_it, ++q) { Matrix<Real> & grad_u_dot = *gradu_dot_it; for (UInt I = 0; I < voigt_h::size; ++I) { Real voigt_factor = voigt_h::factors[I]; UInt i = voigt_h::vec[I][0]; UInt j = voigt_h::vec[I][1]; voigt_strains(I, q) = this->alpha * voigt_factor * (grad_u_dot(i, j) + grad_u_dot(j, i)) / 2.; } } } // compute stresses voigt_stresses = this->C * voigt_strains; // copy stresses back Array<Real>::iterator<Matrix<Real>> stress_it = this->stress(el_type, ghost_type).begin(dim, dim); Array<Real>::iterator<Matrix<Real>> stress_end = this->stress(el_type, ghost_type).end(dim, dim); for (UInt q = 0; stress_it != stress_end; ++stress_it, ++q) { Matrix<Real> & stress = *stress_it; for (UInt I = 0; I < voigt_h::size; ++I) { UInt i = voigt_h::vec[I][0]; UInt j = voigt_h::vec[I][1]; stress(i, j) = stress(j, i) = voigt_stresses(I, q); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialElasticLinearAnisotropic<dim>::computeTangentModuli( const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type) { AKANTU_DEBUG_IN(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); tangent.copy(this->C); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; this->was_stiffness_assembled = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> Real MaterialElasticLinearAnisotropic<dim>::getCelerity( __attribute__((unused)) const Element & element) const { return std::sqrt(this->eigC(0) / rho); } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialElasticLinearAnisotropic); +INSTANTIATE_MATERIAL(elastic_anisotropic, MaterialElasticLinearAnisotropic); } // akantu diff --git a/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc b/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc index 97c6db813..5b81ee1fe 100644 --- a/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc +++ b/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc @@ -1,213 +1,213 @@ /** * @file material_elastic_orthotropic.cc * * @author Till Junge <till.junge@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 Oct 15 2015 * * @brief Orthotropic elastic material * * @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 "material_elastic_orthotropic.hh" #include "solid_mechanics_model.hh" #include <algorithm> namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt Dim> MaterialElasticOrthotropic<Dim>::MaterialElasticOrthotropic(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialElasticLinearAnisotropic<Dim>(model, id) { AKANTU_DEBUG_IN(); this->registerParam("E1", E1 , Real(0.), _pat_parsmod, "Young's modulus (n1)"); this->registerParam("E2", E2 , Real(0.), _pat_parsmod, "Young's modulus (n2)"); this->registerParam("nu12", nu12, Real(0.), _pat_parsmod, "Poisson's ratio (12)"); this->registerParam("G12", G12 , Real(0.), _pat_parsmod, "Shear modulus (12)"); if (Dim > 2) { this->registerParam("E3" , E3 , Real(0.), _pat_parsmod, "Young's modulus (n3)"); this->registerParam("nu13", nu13, Real(0.), _pat_parsmod, "Poisson's ratio (13)"); this->registerParam("nu23", nu23, Real(0.), _pat_parsmod, "Poisson's ratio (23)"); this->registerParam("G13" , G13 , Real(0.), _pat_parsmod, "Shear modulus (13)"); this->registerParam("G23" , G23 , Real(0.), _pat_parsmod, "Shear modulus (23)"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt Dim> MaterialElasticOrthotropic<Dim>::~MaterialElasticOrthotropic() { } /* -------------------------------------------------------------------------- */ template<UInt Dim> void MaterialElasticOrthotropic<Dim>::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); updateInternalParameters(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline Real vector_norm(Vector<Real> & vec) { Real norm = 0; for (UInt i = 0 ; i < vec.size() ; ++i) { norm += vec(i)*vec(i); } return std::sqrt(norm); } /* -------------------------------------------------------------------------- */ template<UInt Dim> void MaterialElasticOrthotropic<Dim>::updateInternalParameters() { /* 1) construction of temporary material frame stiffness tensor------------ */ // http://solidmechanics.org/Text/Chapter3_2/Chapter3_2.php#Sect3_2_13 Real nu21 = nu12 * E2 / E1; Real nu31 = nu13 * E3 / E1; Real nu32 = nu23 * E3 / E2; // Full (i.e. dim^2 by dim^2) stiffness tensor in material frame if (Dim == 1) { AKANTU_DEBUG_ERROR("Dimensions 1 not implemented: makes no sense to have orthotropy for 1D"); } Real Gamma; if (Dim == 3) Gamma = 1/(1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 - 2 * nu21 * nu32 * nu13); if (Dim == 2) Gamma = 1/(1 - nu12 * nu21); // Lamé's first parameters this->Cprime(0, 0) = E1 * (1 - nu23 * nu32) * Gamma; this->Cprime(1, 1) = E2 * (1 - nu13 * nu31) * Gamma; if (Dim == 3) this->Cprime(2, 2) = E3 * (1 - nu12 * nu21) * Gamma; // normalised poisson's ratio's this->Cprime(1, 0) = this->Cprime(0, 1) = E1 * (nu21 + nu31 * nu23) * Gamma; if (Dim == 3) { this->Cprime(2, 0) = this->Cprime(0, 2) = E1 * (nu31 + nu21 * nu32) * Gamma; this->Cprime(2, 1) = this->Cprime(1, 2) = E2 * (nu32 + nu12 * nu31) * Gamma; } // Lamé's second parameters (shear moduli) if (Dim == 3) { this->Cprime(3, 3) = G23; this->Cprime(4, 4) = G13; this->Cprime(5, 5) = G12; } else this->Cprime(2, 2) = G12; /* 1) rotation of C into the global frame */ this->rotateCprime(); this->C.eig(this->eigC); } /* -------------------------------------------------------------------------- */ template<UInt dim> inline void MaterialElasticOrthotropic<dim>::computePotentialEnergyOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & sigma, Real & epot) { epot = .5 * sigma.doubleDot(grad_u); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialElasticOrthotropic<spatial_dimension>::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Material::computePotentialEnergy(el_type, ghost_type); AKANTU_DEBUG_ASSERT(!this->finite_deformation,"finite deformation not possible in material orthotropic (TO BE IMPLEMENTED)"); if(ghost_type != _not_ghost) return; Array<Real>::scalar_iterator epot = this->potential_energy(el_type, ghost_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computePotentialEnergyOnQuad(grad_u, sigma, *epot); ++epot; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialElasticOrthotropic<spatial_dimension>::computePotentialEnergyByElement(ElementType type, UInt index, Vector<Real> & epot_on_quad_points) { AKANTU_DEBUG_ASSERT(!this->finite_deformation,"finite deformation not possible in material orthotropic (TO BE IMPLEMENTED)"); Array<Real>::matrix_iterator gradu_it = this->gradu(type).begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator gradu_end = this->gradu(type).begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator stress_it = this->stress(type).begin(spatial_dimension, spatial_dimension); UInt nb_quadrature_points = this->fem.getNbIntegrationPoints(type); gradu_it += index*nb_quadrature_points; gradu_end += (index+1)*nb_quadrature_points; stress_it += index*nb_quadrature_points; Real * epot_quad = epot_on_quad_points.storage(); Matrix<Real> grad_u(spatial_dimension, spatial_dimension); for(;gradu_it != gradu_end; ++gradu_it, ++stress_it, ++epot_quad) { grad_u.copy(*gradu_it); computePotentialEnergyOnQuad(grad_u, *stress_it, *epot_quad); } } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialElasticOrthotropic); +INSTANTIATE_MATERIAL(elastic_orthotropic, MaterialElasticOrthotropic); } // akantu diff --git a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc index 23bedea4a..b9af218c6 100644 --- a/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc +++ b/src/model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc @@ -1,292 +1,292 @@ /** * @file material_neohookean.cc * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * * @date creation: Mon Apr 08 2013 * @date last modification: Tue Aug 04 2015 * * @brief Specialization of the material class for finite deformation * neo-hookean material * * @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 "material_neohookean.hh" #include "solid_mechanics_model.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialNeohookean<spatial_dimension>::MaterialNeohookean( SolidMechanicsModel & model, const ID & id) : PlaneStressToolbox<spatial_dimension>(model, id) { AKANTU_DEBUG_IN(); this->registerParam("E", E, Real(0.), _pat_parsable | _pat_modifiable, "Young's modulus"); this->registerParam("nu", nu, Real(0.5), _pat_parsable | _pat_modifiable, "Poisson's ratio"); this->registerParam("lambda", lambda, _pat_readable, "First Lamé coefficient"); this->registerParam("mu", mu, _pat_readable, "Second Lamé coefficient"); this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient"); this->finite_deformation = true; this->initialize_third_axis_deformation = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialNeohookean<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); PlaneStressToolbox<spatial_dimension>::initMaterial(); if (spatial_dimension == 1) nu = 0.; this->updateInternalParameters(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::initMaterial() { AKANTU_DEBUG_IN(); PlaneStressToolbox<2>::initMaterial(); this->updateInternalParameters(); if (this->plane_stress) this->third_axis_deformation.setDefaultValue(1.); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialNeohookean<spatial_dimension>::updateInternalParameters() { lambda = nu * E / ((1 + nu) * (1 - 2 * nu)); mu = E / (2 * (1 + nu)); kpa = lambda + 2. / 3. * mu; } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialNeohookean<dim>::computeCauchyStressPlaneStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); PlaneStressToolbox<dim>::computeCauchyStressPlaneStress(el_type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::computeCauchyStressPlaneStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real>::matrix_iterator gradu_it = this->gradu(el_type, ghost_type).begin(2, 2); Array<Real>::matrix_iterator gradu_end = this->gradu(el_type, ghost_type).end(2, 2); Array<Real>::matrix_iterator piola_it = this->piola_kirchhoff_2(el_type, ghost_type).begin(2, 2); Array<Real>::matrix_iterator stress_it = this->stress(el_type, ghost_type).begin(2, 2); Array<Real>::const_scalar_iterator c33_it = this->third_axis_deformation(el_type, ghost_type).begin(); Matrix<Real> F_tensor(2, 2); for (; gradu_it != gradu_end; ++gradu_it, ++piola_it, ++stress_it, ++c33_it) { Matrix<Real> & grad_u = *gradu_it; Matrix<Real> & piola = *piola_it; Matrix<Real> & sigma = *stress_it; gradUToF<2>(grad_u, F_tensor); computeCauchyStressOnQuad<2>(F_tensor, piola, sigma, *c33_it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialNeohookean<dim>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computeStressOnQuad(grad_u, sigma); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if (this->plane_stress) { PlaneStressToolbox<2>::computeStress(el_type, ghost_type); Array<Real>::const_scalar_iterator c33_it = this->third_axis_deformation(el_type, ghost_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computeStressOnQuad(grad_u, sigma, *c33_it); ++c33_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } else { MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computeStressOnQuad(grad_u, sigma); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialNeohookean<dim>::computeThirdAxisDeformation( __attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::computeThirdAxisDeformation(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(this->plane_stress, "The third component of the strain " "can only be computed for 2D " "problems in Plane Stress!!"); Array<Real>::scalar_iterator c33_it = this->third_axis_deformation(el_type, ghost_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computeThirdAxisDeformationOnQuad(grad_u, *c33_it); ++c33_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialNeohookean<spatial_dimension>::computePotentialEnergy( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Material::computePotentialEnergy(el_type, ghost_type); if (ghost_type != _not_ghost) return; Array<Real>::scalar_iterator epot = this->potential_energy(el_type, ghost_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); computePotentialEnergyOnQuad(grad_u, *epot); ++epot; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialNeohookean<spatial_dimension>::computeTangentModuli( __attribute__((unused)) const ElementType & el_type, Array<Real> & tangent_matrix, __attribute__((unused)) GhostType ghost_type) { AKANTU_DEBUG_IN(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); computeTangentModuliOnQuad(tangent, grad_u); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> void MaterialNeohookean<2>::computeTangentModuli(__attribute__((unused)) const ElementType & el_type, Array<Real> & tangent_matrix, __attribute__((unused)) GhostType ghost_type) { AKANTU_DEBUG_IN(); if (this->plane_stress) { PlaneStressToolbox<2>::computeStress(el_type, ghost_type); Array<Real>::const_scalar_iterator c33_it = this->third_axis_deformation(el_type, ghost_type).begin(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); computeTangentModuliOnQuad(tangent, grad_u, *c33_it); ++c33_it; MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; } else { MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); computeTangentModuliOnQuad(tangent, grad_u); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> Real MaterialNeohookean<spatial_dimension>::getPushWaveSpeed( __attribute__((unused)) const Element & element) const { return sqrt((this->lambda + 2 * this->mu) / this->rho); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> Real MaterialNeohookean<spatial_dimension>::getShearWaveSpeed( __attribute__((unused)) const Element & element) const { return sqrt(this->mu / this->rho); } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialNeohookean); +INSTANTIATE_MATERIAL(neohookean, MaterialNeohookean); } // akantu diff --git a/src/model/solid_mechanics/materials/material_non_local_tmpl.hh b/src/model/solid_mechanics/materials/material_non_local_tmpl.hh index 0ec5feca7..7b9d6f66a 100644 --- a/src/model/solid_mechanics/materials/material_non_local_tmpl.hh +++ b/src/model/solid_mechanics/materials/material_non_local_tmpl.hh @@ -1,132 +1,133 @@ /** * @file material_non_local.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Tue Dec 08 2015 * * @brief Implementation of material non-local * * @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 "material.hh" #include "material_non_local.hh" #include "non_local_neighborhood.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt dim, class LocalParent> MaterialNonLocal<dim, LocalParent>::MaterialNonLocal( SolidMechanicsModel & model, const ID & id) : LocalParent(model, id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim, class LocalParent> void MaterialNonLocal<dim, LocalParent>::initMaterial() { MaterialNonLocalInterface::initMaterial(); } /* -------------------------------------------------------------------------- */ template <UInt dim, class LocalParent> void MaterialNonLocal<dim, LocalParent>::insertIntegrationPointsInNeighborhoods( const GhostType & ghost_type, const ElementTypeMapReal & quadrature_points_coordinates) { IntegrationPoint q; q.ghost_type = ghost_type; q.kind = _ek_regular; + auto & neighborhood = this->model.getNeighborhood(this->name); + for (auto & type : this->element_filter.elementTypes(dim, ghost_type, _ek_regular)) { q.type = type; const auto & elem_filter = this->element_filter(type, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element) { UInt nb_quad = this->getFEEngine().getNbIntegrationPoints(type, ghost_type); const auto & quads = quadrature_points_coordinates(type, ghost_type); auto nb_total_element = this->model.getMesh().getNbElement(type, ghost_type); auto quads_it = quads.begin_reinterpret(dim, nb_quad, nb_total_element); for (auto & elem : elem_filter) { Matrix<Real> quads = quads_it[elem]; q.element = elem; for (UInt nq = 0; nq < nb_quad; ++nq) { q.num_point = nq; q.global_num = q.element * nb_quad + nq; - this->model.getNeighborhood(this->name) - .insertIntegrationPoint(q, quads(nq)); + neighborhood.insertIntegrationPoint(q, quads(nq)); } } } } } /* -------------------------------------------------------------------------- */ template <UInt dim, class LocalParent> void MaterialNonLocal<dim, LocalParent>::updateNonLocalInternals( ElementTypeMapReal & non_local_flattened, const ID & field_id, const GhostType & ghost_type, const ElementKind & kind) { /// loop over all types in the material for (auto & el_type : this->element_filter.elementTypes(dim, ghost_type, kind)) { Array<Real> & internal = this->template getInternal<Real>(field_id)(el_type, ghost_type); auto & internal_flat = non_local_flattened(el_type, ghost_type); auto nb_component = internal_flat.getNbComponent(); auto internal_it = internal.begin(nb_component); auto internal_flat_it = internal_flat.begin(nb_component); /// loop all elements for the given type const auto & filter = this->element_filter(el_type, ghost_type); UInt nb_quads = this->getFEEngine().getNbIntegrationPoints(el_type, ghost_type); for (auto & elem : filter) { for (UInt q = 0; q < nb_quads; ++q, ++internal_it) { UInt global_quad = elem * nb_quads + q; *internal_it = internal_flat_it[global_quad]; } } } } /* -------------------------------------------------------------------------- */ template <UInt dim, class LocalParent> void MaterialNonLocal<dim, LocalParent>::registerNeighborhood() { this->model.registerNeighborhood(this->name, this->name); } } // namespace akantu diff --git a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc index bc16a9186..f209f0d85 100644 --- a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc +++ b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc @@ -1,200 +1,200 @@ /** * @file material_linear_isotropic_hardening.cc * * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch> * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Benjamin Paccaud <benjamin.paccaud@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Apr 07 2014 * @date last modification: Tue Aug 18 2015 * * @brief Specialization of the material class for isotropic finite deformation * linear hardening plasticity * * @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 "material_linear_isotropic_hardening.hh" #include "solid_mechanics_model.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt dim> MaterialLinearIsotropicHardening<dim>::MaterialLinearIsotropicHardening( SolidMechanicsModel & model, const ID & id) : MaterialPlastic<dim>(model, id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialLinearIsotropicHardening<spatial_dimension>:: MaterialLinearIsotropicHardening(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id) : MaterialPlastic<spatial_dimension>(model, dim, mesh, fe_engine, id) {} /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialLinearIsotropicHardening<spatial_dimension>::computeStress( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialThermal<spatial_dimension>::computeStress(el_type, ghost_type); // infinitesimal and finite deformation auto sigma_th_it = this->sigma_th(el_type, ghost_type).begin(); auto previous_sigma_th_it = this->sigma_th.previous(el_type, ghost_type).begin(); auto previous_gradu_it = this->gradu.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto previous_stress_it = this->stress.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto inelastic_strain_it = this->inelastic_strain(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto previous_inelastic_strain_it = this->inelastic_strain.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto iso_hardening_it = this->iso_hardening(el_type, ghost_type).begin(); auto previous_iso_hardening_it = this->iso_hardening.previous(el_type, ghost_type).begin(); // // Finite Deformations // if (this->finite_deformation) { auto previous_piola_kirchhoff_2_it = this->piola_kirchhoff_2.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto green_strain_it = this->green_strain(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); auto & inelastic_strain_tensor = *inelastic_strain_it; auto & previous_inelastic_strain_tensor = *previous_inelastic_strain_it; auto & previous_grad_u = *previous_gradu_it; auto & previous_sigma = *previous_piola_kirchhoff_2_it; auto & green_strain = *green_strain_it; this->template gradUToGreenStrain<spatial_dimension>(grad_u, green_strain); Matrix<Real> previous_green_strain(spatial_dimension, spatial_dimension); this->template gradUToGreenStrain<spatial_dimension>(previous_grad_u, previous_green_strain); Matrix<Real> F_tensor(spatial_dimension, spatial_dimension); this->template gradUToF<spatial_dimension>(grad_u, F_tensor); computeStressOnQuad(green_strain, previous_green_strain, sigma, previous_sigma, inelastic_strain_tensor, previous_inelastic_strain_tensor, *iso_hardening_it, *previous_iso_hardening_it, *sigma_th_it, *previous_sigma_th_it, F_tensor); ++sigma_th_it; ++inelastic_strain_it; ++iso_hardening_it; ++previous_sigma_th_it; //++previous_stress_it; ++previous_gradu_it; ++green_strain_it; ++previous_inelastic_strain_it; ++previous_iso_hardening_it; ++previous_piola_kirchhoff_2_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } // Infinitesimal deformations else { MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); auto & inelastic_strain_tensor = *inelastic_strain_it; auto & previous_inelastic_strain_tensor = *previous_inelastic_strain_it; auto & previous_grad_u = *previous_gradu_it; auto & previous_sigma = *previous_stress_it; computeStressOnQuad( grad_u, previous_grad_u, sigma, previous_sigma, inelastic_strain_tensor, previous_inelastic_strain_tensor, *iso_hardening_it, *previous_iso_hardening_it, *sigma_th_it, *previous_sigma_th_it); ++sigma_th_it; ++inelastic_strain_it; ++iso_hardening_it; ++previous_sigma_th_it; ++previous_stress_it; ++previous_gradu_it; ++previous_inelastic_strain_it; ++previous_iso_hardening_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialLinearIsotropicHardening<spatial_dimension>::computeTangentModuli( const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type) { AKANTU_DEBUG_IN(); auto previous_gradu_it = this->gradu.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto previous_stress_it = this->stress.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); auto iso_hardening = this->iso_hardening(el_type, ghost_type).begin(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); computeTangentModuliOnQuad(tangent, grad_u, *previous_gradu_it, sigma_tensor, *previous_stress_it, *iso_hardening); ++previous_gradu_it; ++previous_stress_it; ++iso_hardening; MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; this->was_stiffness_assembled = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialLinearIsotropicHardening); +INSTANTIATE_MATERIAL(plastic_linear_isotropic_hardening, MaterialLinearIsotropicHardening); } // akantu diff --git a/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc b/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc index a16772bf5..2f407b6e0 100644 --- a/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc +++ b/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc @@ -1,209 +1,209 @@ /** * @file material_plastic.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Mon Apr 07 2014 * @date last modification: Tue Aug 18 2015 * * @brief Implemantation of the akantu::MaterialPlastic 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 "material_plastic.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> MaterialPlastic<spatial_dimension>::MaterialPlastic(SolidMechanicsModel & model, const ID & id) : MaterialElastic<spatial_dimension>(model, id), iso_hardening("iso_hardening", *this), inelastic_strain("inelastic_strain", *this), plastic_energy("plastic_energy", *this), d_plastic_energy("d_plastic_energy", *this) { AKANTU_DEBUG_IN(); this->initialize(); AKANTU_DEBUG_OUT(); } template <UInt spatial_dimension> MaterialPlastic<spatial_dimension>::MaterialPlastic(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id) : MaterialElastic<spatial_dimension>(model, dim, mesh, fe_engine, id), iso_hardening("iso_hardening", *this, dim, fe_engine, this->element_filter), inelastic_strain("inelastic_strain", *this, dim, fe_engine, this->element_filter), plastic_energy("plastic_energy", *this, dim, fe_engine, this->element_filter), d_plastic_energy("d_plastic_energy", *this, dim, fe_engine, this->element_filter) { AKANTU_DEBUG_IN(); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialPlastic<spatial_dimension>::initialize() { this->registerParam("h", h, Real(0.), _pat_parsable | _pat_modifiable, "Hardening modulus"); this->registerParam("sigma_y", sigma_y, Real(0.), _pat_parsable | _pat_modifiable, "Yield stress"); this->iso_hardening.initialize(1); this->iso_hardening.initializeHistory(); this->plastic_energy.initialize(1); this->d_plastic_energy.initialize(1); this->use_previous_stress = true; this->use_previous_gradu = true; this->use_previous_stress_thermal = true; this->inelastic_strain.initialize(spatial_dimension * spatial_dimension); this->inelastic_strain.initializeHistory(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> Real MaterialPlastic<spatial_dimension>::getEnergy(std::string type) { if (type == "plastic") return getPlasticEnergy(); else return MaterialElastic<spatial_dimension>::getEnergy(type); return 0.; } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> Real MaterialPlastic<spatial_dimension>::getPlasticEnergy() { AKANTU_DEBUG_IN(); Real penergy = 0.; for (auto & type : this->element_filter.elementTypes(spatial_dimension, _not_ghost)) { penergy += this->fem.integrate(plastic_energy(type, _not_ghost), type, _not_ghost, this->element_filter(type, _not_ghost)); } AKANTU_DEBUG_OUT(); return penergy; } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialPlastic<spatial_dimension>::computePotentialEnergy( ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if (ghost_type != _not_ghost) return; Array<Real>::scalar_iterator epot = this->potential_energy(el_type, ghost_type).begin(); Array<Real>::const_iterator<Matrix<Real>> inelastic_strain_it = this->inelastic_strain(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> elastic_strain(spatial_dimension, spatial_dimension); elastic_strain.copy(grad_u); elastic_strain -= *inelastic_strain_it; MaterialElastic<spatial_dimension>::computePotentialEnergyOnQuad( elastic_strain, sigma, *epot); ++epot; ++inelastic_strain_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt spatial_dimension> void MaterialPlastic<spatial_dimension>::updateEnergies(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialElastic<spatial_dimension>::updateEnergies(el_type, ghost_type); Array<Real>::iterator<> pe_it = this->plastic_energy(el_type, ghost_type).begin(); Array<Real>::iterator<> wp_it = this->d_plastic_energy(el_type, ghost_type).begin(); Array<Real>::iterator<Matrix<Real>> inelastic_strain_it = this->inelastic_strain(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); Array<Real>::iterator<Matrix<Real>> previous_inelastic_strain_it = this->inelastic_strain.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator previous_sigma = this->stress.previous(el_type, ghost_type) .begin(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> delta_strain_it(*inelastic_strain_it); delta_strain_it -= *previous_inelastic_strain_it; Matrix<Real> sigma_h(sigma); sigma_h += *previous_sigma; *wp_it = .5 * sigma_h.doubleDot(delta_strain_it); *pe_it += *wp_it; ++pe_it; ++wp_it; ++inelastic_strain_it; ++previous_inelastic_strain_it; ++previous_sigma; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialPlastic); +INSTANTIATE_MATERIAL_ONLY(MaterialPlastic); } // namespace akantu diff --git a/src/model/solid_mechanics/materials/material_thermal.cc b/src/model/solid_mechanics/materials/material_thermal.cc index f0491b3a0..171a5aee3 100644 --- a/src/model/solid_mechanics/materials/material_thermal.cc +++ b/src/model/solid_mechanics/materials/material_thermal.cc @@ -1,123 +1,123 @@ /** * @file material_thermal.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Aug 04 2015 * * @brief Specialization of the material class for the thermal material * * @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 "material_thermal.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialThermal<spatial_dimension>::MaterialThermal(SolidMechanicsModel & model, const ID & id) : Material(model, id), delta_T("delta_T", *this), sigma_th("sigma_th", *this), use_previous_stress_thermal(false) { AKANTU_DEBUG_IN(); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialThermal<spatial_dimension>::MaterialThermal(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id) : Material(model, dim, mesh, fe_engine, id), delta_T("delta_T", *this, dim, fe_engine, this->element_filter), sigma_th("sigma_th", *this, dim, fe_engine, this->element_filter), use_previous_stress_thermal(false) { AKANTU_DEBUG_IN(); this->initialize(); AKANTU_DEBUG_OUT(); } template<UInt spatial_dimension> void MaterialThermal<spatial_dimension>::initialize() { this->registerParam("E" , E , Real(0. ) , _pat_parsable | _pat_modifiable, "Young's modulus" ); this->registerParam("nu" , nu , Real(0.5) , _pat_parsable | _pat_modifiable, "Poisson's ratio" ); this->registerParam("alpha" , alpha , Real(0. ) , _pat_parsable | _pat_modifiable, "Thermal expansion coefficient"); this->registerParam("delta_T", delta_T, _pat_parsable | _pat_modifiable, "Uniform temperature field"); delta_T.initialize(1); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialThermal<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); sigma_th.initialize(1); if(use_previous_stress_thermal) { sigma_th.initializeHistory(); } Material::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialThermal<dim>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real>::iterator<> delta_t_it = this->delta_T(el_type, ghost_type).begin(); Array<Real>::iterator<> sigma_th_it = this->sigma_th(el_type, ghost_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); /// TODO : implement with the matrix alpha if (dim == 1) { *sigma_th_it = - this->E * this->alpha * *delta_t_it; } else { *sigma_th_it = - this->E/(1.-2.*this->nu) * this->alpha * *delta_t_it; } ++delta_t_it; ++sigma_th_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialThermal); +INSTANTIATE_MATERIAL_ONLY(MaterialThermal); } // akantu diff --git a/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc b/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc index 3ed32f2d6..9aac29ef4 100644 --- a/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc +++ b/src/model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc @@ -1,295 +1,295 @@ /** * @file material_standard_linear_solid_deviatoric.cc * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Vladislav Yastrebov <vladislav.yastrebov@epfl.ch> * * @date creation: Wed May 04 2011 * @date last modification: Thu Oct 15 2015 * * @brief Material Visco-elastic * * @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 "material_standard_linear_solid_deviatoric.hh" #include "solid_mechanics_model.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialStandardLinearSolidDeviatoric<spatial_dimension>::MaterialStandardLinearSolidDeviatoric(SolidMechanicsModel & model, const ID & id) : MaterialElastic<spatial_dimension>(model, id), stress_dev("stress_dev", *this), history_integral("history_integral", *this), dissipated_energy("dissipated_energy", *this) { AKANTU_DEBUG_IN(); this->registerParam("Eta", eta, Real(1.), _pat_parsable | _pat_modifiable, "Viscosity"); this->registerParam("Ev", Ev, Real(1.), _pat_parsable | _pat_modifiable, "Stiffness of the viscous element"); this->registerParam("Einf", E_inf, Real(1.), _pat_readable, "Stiffness of the elastic element"); UInt stress_size = spatial_dimension * spatial_dimension; this->stress_dev .initialize(stress_size); this->history_integral .initialize(stress_size); this->dissipated_energy.initialize(1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); updateInternalParameters(); MaterialElastic<spatial_dimension>::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::updateInternalParameters() { MaterialElastic<spatial_dimension>::updateInternalParameters(); E_inf = this->E - this->Ev; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::setToSteadyState(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real> & stress_dev_vect = stress_dev(el_type, ghost_type); Array<Real> & history_int_vect = history_integral(el_type, ghost_type); Array<Real>::matrix_iterator stress_d = stress_dev_vect.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator history_int = history_int_vect.begin(spatial_dimension, spatial_dimension); /// Loop on all quadrature points MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> & dev_s = *stress_d; Matrix<Real> & h = *history_int; /// Compute the first invariant of strain Real Theta = grad_u.trace(); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) { dev_s(i, j) = 2 * this->mu * (.5 * (grad_u(i,j) + grad_u(j,i)) - 1./3. * Theta *(i == j)); h(i, j) = 0.; } /// Save the deviator of stress ++stress_d; ++history_int; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real tau = 0.; // if(std::abs(Ev) > std::numeric_limits<Real>::epsilon()) tau = eta / Ev; Array<Real> & stress_dev_vect = stress_dev(el_type, ghost_type); Array<Real> & history_int_vect = history_integral(el_type, ghost_type); Array<Real>::matrix_iterator stress_d = stress_dev_vect.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator history_int = history_int_vect.begin(spatial_dimension, spatial_dimension); Matrix<Real> s(spatial_dimension, spatial_dimension); Real dt = this->model.getTimeStep(); Real exp_dt_tau = exp( -dt/tau ); Real exp_dt_tau_2 = exp( -.5*dt/tau ); Matrix<Real> epsilon_d(spatial_dimension, spatial_dimension); Matrix<Real> epsilon_v(spatial_dimension, spatial_dimension); /// Loop on all quadrature points MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> & dev_s = *stress_d; Matrix<Real> & h = *history_int; s.clear(); sigma.clear(); /// Compute the first invariant of strain Real gamma_inf = E_inf / this->E; Real gamma_v = Ev / this->E; this->template gradUToEpsilon<spatial_dimension>(grad_u, epsilon_d); Real Theta = epsilon_d.trace(); epsilon_v.eye(Theta / Real(3.)); epsilon_d -= epsilon_v; Matrix<Real> U_rond_prim(spatial_dimension, spatial_dimension); U_rond_prim.eye(gamma_inf * this->kpa * Theta); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) { s(i, j) = 2 * this->mu * epsilon_d(i, j); h(i, j) = exp_dt_tau * h(i, j) + exp_dt_tau_2 * (s(i, j) - dev_s(i, j)); dev_s(i, j) = s(i, j); sigma(i, j) = U_rond_prim(i,j) + gamma_inf * s(i, j) + gamma_v * h(i, j); } /// Save the deviator of stress ++stress_d; ++history_int; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; this->updateDissipatedEnergy(el_type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialStandardLinearSolidDeviatoric<spatial_dimension>::updateDissipatedEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); // if(ghost_type == _ghost) return 0.; Real tau = 0.; tau = eta / Ev; Real * dis_energy = dissipated_energy(el_type, ghost_type).storage(); Array<Real> & stress_dev_vect = stress_dev(el_type, ghost_type); Array<Real> & history_int_vect = history_integral(el_type, ghost_type); Array<Real>::matrix_iterator stress_d = stress_dev_vect.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator history_int = history_int_vect.begin(spatial_dimension, spatial_dimension); Matrix<Real> q(spatial_dimension, spatial_dimension); Matrix<Real> q_rate(spatial_dimension, spatial_dimension); Matrix<Real> epsilon_d(spatial_dimension, spatial_dimension); Matrix<Real> epsilon_v(spatial_dimension, spatial_dimension); Real dt = this->model.getTimeStep(); Real gamma_v = Ev / this->E; Real alpha = 1. / (2. * this->mu * gamma_v); /// Loop on all quadrature points MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> & dev_s = *stress_d; Matrix<Real> & h = *history_int; /// Compute the first invariant of strain this->template gradUToEpsilon<spatial_dimension>(grad_u, epsilon_d); Real Theta = epsilon_d.trace(); epsilon_v.eye(Theta / Real(3.)); epsilon_d -= epsilon_v; q.copy(dev_s); q -= h; q *= gamma_v; q_rate.copy(dev_s); q_rate *= gamma_v; q_rate -= q; q_rate /= tau; for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) *dis_energy += (epsilon_d(i, j) - alpha * q(i, j)) * q_rate(i, j) * dt; /// Save the deviator of stress ++stress_d; ++history_int; ++dis_energy; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialStandardLinearSolidDeviatoric<spatial_dimension>::getDissipatedEnergy() const { AKANTU_DEBUG_IN(); Real de = 0.; /// integrate the dissipated energy for each type of elements for(auto & type : this->element_filter.elementTypes(spatial_dimension, _not_ghost)) { de += this->fem.integrate(dissipated_energy(type, _not_ghost), type, _not_ghost, this->element_filter(type, _not_ghost)); } AKANTU_DEBUG_OUT(); return de; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialStandardLinearSolidDeviatoric<spatial_dimension>::getDissipatedEnergy(ElementType type, UInt index) const { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = this->fem.getNbIntegrationPoints(type); Array<Real>::const_vector_iterator it = this->dissipated_energy(type, _not_ghost).begin(nb_quadrature_points); UInt gindex = (this->element_filter(type, _not_ghost))(index); AKANTU_DEBUG_OUT(); return this->fem.integrate(it[index], type, gindex); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialStandardLinearSolidDeviatoric<spatial_dimension>::getEnergy(std::string type) { if(type == "dissipated") return getDissipatedEnergy(); else if(type == "dissipated_sls_deviatoric") return getDissipatedEnergy(); else return MaterialElastic<spatial_dimension>::getEnergy(type); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialStandardLinearSolidDeviatoric<spatial_dimension>::getEnergy(std::string energy_id, ElementType type, UInt index) { if(energy_id == "dissipated") return getDissipatedEnergy(type, index); else if(energy_id == "dissipated_sls_deviatoric") return getDissipatedEnergy(type, index); else return MaterialElastic<spatial_dimension>::getEnergy(energy_id, type, index); } /* -------------------------------------------------------------------------- */ -INSTANTIATE_MATERIAL(MaterialStandardLinearSolidDeviatoric); +INSTANTIATE_MATERIAL(sls_deviatoric, MaterialStandardLinearSolidDeviatoric); } // akantu diff --git a/src/model/solid_mechanics/materials/random_internal_field.hh b/src/model/solid_mechanics/materials/random_internal_field.hh index dcca9ecb8..c18402786 100644 --- a/src/model/solid_mechanics/materials/random_internal_field.hh +++ b/src/model/solid_mechanics/materials/random_internal_field.hh @@ -1,109 +1,109 @@ /** * @file random_internal_field.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Dec 08 2015 * * @brief Random internal material parameter * * @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_random_generator.hh" #include "internal_field.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_RANDOM_INTERNAL_FIELD_HH__ #define __AKANTU_RANDOM_INTERNAL_FIELD_HH__ namespace akantu { /** * class for the internal fields of materials with a random * distribution */ template<typename T, template<typename> class BaseField = InternalField, - template<typename> class Generator = RandGenerator> + template<typename> class Generator = RandomGenerator> class RandomInternalField : public BaseField<T> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: RandomInternalField(const ID & id, Material & material); virtual ~RandomInternalField(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ private: RandomInternalField operator=(__attribute__((unused)) const RandomInternalField & other) {}; public: AKANTU_GET_MACRO(RandomParameter, random_parameter, const RandomParameter<T>); /// initialize the field to a given number of component virtual void initialize(UInt nb_component); /// set the field to a given value void setDefaultValue(const T & value); /// set the specified random distribution to a given parameter void setRandomDistribution(const RandomParameter<T> & param); /// print the content virtual void printself(std::ostream & stream, int indent = 0) const; protected: virtual void setArrayValues(T * begin, T * end); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: inline operator Real() const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// random parameter containing the distribution and base value RandomParameter<T> random_parameter; }; /// standard output stream operator template<typename T> inline std::ostream & operator <<(std::ostream & stream, const RandomInternalField<T> & _this) { _this.printself(stream); return stream; } } // akantu #endif /* __AKANTU_RANDOM_INTERNAL_FIELD_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model.cc b/src/model/solid_mechanics/solid_mechanics_model.cc index 9a99735a5..5411d7e5c 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.cc +++ b/src/model/solid_mechanics/solid_mechanics_model.cc @@ -1,1546 +1,1260 @@ /** * @file solid_mechanics_model.cc * * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch> * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Jan 19 2016 * * @brief Implementation of the SolidMechanicsModel 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 "solid_mechanics_model.hh" -#include "aka_math.hh" -#include "element_group.hh" #include "element_synchronizer.hh" -#include "group_manager_inline_impl.cc" -#include "material_non_local.hh" #include "sparse_matrix.hh" #include "static_communicator.hh" #include "synchronizer_registry.hh" #include "dumpable_inline_impl.hh" #ifdef AKANTU_USE_IOHELPER -#include "dumper_element_partition.hh" -#include "dumper_elemental_field.hh" -#include "dumper_field.hh" -#include "dumper_homogenizing_field.hh" -#include "dumper_internal_material_field.hh" -#include "dumper_iohelper.hh" -#include "dumper_material_padders.hh" #include "dumper_paraview.hh" #endif +#include "material_non_local.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ /** * A solid mechanics model need a mesh and a dimension to be created. the model * by it self can not do a lot, the good init functions should be called in * order to configure the model depending on what we want to do. * * @param mesh mesh representing the model we want to simulate * @param dim spatial dimension of the problem, if dim = 0 (default value) the * dimension of the problem is assumed to be the on of the mesh * @param id an id to identify the model */ SolidMechanicsModel::SolidMechanicsModel(Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id) : Model(mesh, dim, id, memory_id), BoundaryCondition<SolidMechanicsModel>(), NonLocalManager(*this, id + ":non_local_manager", memory_id), f_m2a(1.0), displacement(nullptr), previous_displacement(nullptr), displacement_increment(nullptr), mass(nullptr), velocity(nullptr), acceleration(nullptr), external_force(nullptr), internal_force(nullptr), blocked_dofs(nullptr), current_position(nullptr), mass_matrix(nullptr), velocity_damping_matrix(nullptr), stiffness_matrix(nullptr), jacobian_matrix(nullptr), material_index("material index", id, memory_id), material_local_numbering("material local numbering", id, memory_id), material_selector(new DefaultMaterialSelector(material_index)), is_default_material_selector(true), increment_flag(false), are_materials_instantiated(false) { //, pbc_synch(nullptr) { AKANTU_DEBUG_IN(); this->registerFEEngineObject<MyFEEngineType>("SolidMechanicsFEEngine", mesh, Model::spatial_dimension); this->mesh.registerEventHandler(*this); #if defined(AKANTU_USE_IOHELPER) this->mesh.registerDumper<DumperParaview>("paraview_all", id, true); this->mesh.addDumpMesh(mesh, Model::spatial_dimension, _not_ghost, _ek_regular); #endif this->initDOFManager(); this->registerDataAccessor(*this); if (this->mesh.isDistributed()) { auto & synchronizer = this->mesh.getElementSynchronizer(); this->registerSynchronizer(synchronizer, _gst_material_id); this->registerSynchronizer(synchronizer, _gst_smm_mass); this->registerSynchronizer(synchronizer, _gst_smm_stress); this->registerSynchronizer(synchronizer, _gst_smm_boundary); this->registerSynchronizer(synchronizer, _gst_for_dump); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolidMechanicsModel::~SolidMechanicsModel() { AKANTU_DEBUG_IN(); if (is_default_material_selector) { delete material_selector; material_selector = nullptr; } for (auto & internal : this->registered_internals) { delete internal.second; } // delete pbc_synch; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::setTimeStep(Real time_step, const ID & solver_id) { Model::setTimeStep(time_step, solver_id); #if defined(AKANTU_USE_IOHELPER) this->mesh.getDumper().setTimeStep(time_step); #endif } /* -------------------------------------------------------------------------- */ /* Initialization */ /* -------------------------------------------------------------------------- */ /** * This function groups many of the initialization in on function. For most of * basics case the function should be enough. The functions initialize the * model, the internal vectors, set them to 0, and depending on the parameters * it also initialize the explicit or implicit solver. * * @param material_file the file containing the materials to use * @param method the analysis method wanted. See the akantu::AnalysisMethod for * the different possibilities */ void SolidMechanicsModel::initFull(const ModelOptions & options) { Model::initFull(options); const SolidMechanicsModelOptions & smm_options = dynamic_cast<const SolidMechanicsModelOptions &>(options); this->method = smm_options.analysis_method; // initialize the vectors this->initArrays(); if (!this->hasDefaultSolver()) this->initNewSolver(this->method); // initialize pbc if (this->pbc_pair.size() != 0) this->initPBC(); // initialize the materials if (this->parser->getLastParsedFile() != "") { this->instantiateMaterials(); } if (!smm_options.no_init_materials) { this->initMaterials(); } // if (increment_flag) this->initBC(*this, *displacement, *displacement_increment, *external_force); // else // this->initBC(*this, *displacement, *external_force); } /* -------------------------------------------------------------------------- */ TimeStepSolverType SolidMechanicsModel::getDefaultSolverType() const { return _tsst_dynamic_lumped; } /* -------------------------------------------------------------------------- */ ModelSolverOptions SolidMechanicsModel::getDefaultSolverOptions( const TimeStepSolverType & type) const { ModelSolverOptions options; switch (type) { case _tsst_dynamic_lumped: { options.non_linear_solver_type = _nls_lumped; options.integration_scheme_type["displacement"] = _ist_central_difference; options.solution_type["displacement"] = IntegrationScheme::_acceleration; break; } case _tsst_static: { options.non_linear_solver_type = _nls_newton_raphson; options.integration_scheme_type["displacement"] = _ist_pseudo_time; options.solution_type["displacement"] = IntegrationScheme::_not_defined; break; } case _tsst_dynamic: { if (this->method == _explicit_consistent_mass) { options.non_linear_solver_type = _nls_newton_raphson; options.integration_scheme_type["displacement"] = _ist_central_difference; options.solution_type["displacement"] = IntegrationScheme::_acceleration; } else { options.non_linear_solver_type = _nls_newton_raphson; options.integration_scheme_type["displacement"] = _ist_trapezoidal_rule_2; options.solution_type["displacement"] = IntegrationScheme::_displacement; } break; } } return options; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initNewSolver(const AnalysisMethod & method) { ID solver_name; TimeStepSolverType tss_type; this->method = method; switch (this->method) { case _explicit_lumped_mass: { solver_name = "explicit_lumped"; tss_type = _tsst_dynamic_lumped; break; } case _explicit_consistent_mass: { solver_name = "explicit"; tss_type = _tsst_dynamic; break; } case _static: { solver_name = "static"; tss_type = _tsst_static; break; } case _implicit_dynamic: { solver_name = "implicit"; tss_type = _tsst_dynamic; break; } } if (!this->hasSolver(solver_name)) { ModelSolverOptions options = this->getDefaultSolverOptions(tss_type); this->getNewSolver(solver_name, tss_type, options.non_linear_solver_type); this->setIntegrationScheme(solver_name, "displacement", options.integration_scheme_type["displacement"], options.solution_type["displacement"]); this->setDefaultSolver(solver_name); } } /* -------------------------------------------------------------------------- */ template <typename T> void SolidMechanicsModel::allocNodalField(Array<T> *& array, const ID & name) { if (array == nullptr) { UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_disp; sstr_disp << id << ":" << name; array = &(alloc<T>(sstr_disp.str(), nb_nodes, Model::spatial_dimension, T())); } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initSolver( TimeStepSolverType time_step_solver_type, __attribute__((unused)) NonLinearSolverType non_linear_solver_type) { DOFManager & dof_manager = this->getDOFManager(); /* ------------------------------------------------------------------------ */ // for alloc type of solvers this->allocNodalField(this->displacement, "displacement"); this->allocNodalField(this->previous_displacement, "previous_displacement"); this->allocNodalField(this->displacement_increment, "displacement_increment"); this->allocNodalField(this->internal_force, "internal_force"); this->allocNodalField(this->external_force, "external_force"); this->allocNodalField(this->blocked_dofs, "blocked_dofs"); this->allocNodalField(this->current_position, "current_position"); /* ------------------------------------------------------------------------ */ if (!dof_manager.hasDOFs("displacement")) { dof_manager.registerDOFs("displacement", *this->displacement, _dst_nodal); dof_manager.registerBlockedDOFs("displacement", *this->blocked_dofs); dof_manager.registerDOFsIncrement("displacement", *this->displacement_increment); dof_manager.registerDOFsPrevious("displacement", *this->previous_displacement); } /* ------------------------------------------------------------------------ */ // for dynamic if (time_step_solver_type == _tsst_dynamic || time_step_solver_type == _tsst_dynamic_lumped) { this->allocNodalField(this->velocity, "velocity"); this->allocNodalField(this->acceleration, "acceleration"); if (!dof_manager.hasDOFsDerivatives("displacement", 1)) { dof_manager.registerDOFsDerivative("displacement", 1, *this->velocity); dof_manager.registerDOFsDerivative("displacement", 2, *this->acceleration); } } if (time_step_solver_type == _tsst_dynamic || time_step_solver_type == _tsst_static) { if (!dof_manager.hasMatrix("K")) { dof_manager.getNewMatrix("K", _symmetric); } if (!dof_manager.hasMatrix("J")) { dof_manager.getNewMatrix("J", "K"); } } } /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::initParallel(MeshPartition & partition, // DataAccessor<Element> * data_accessor) // { // AKANTU_DEBUG_IN(); // if (data_accessor == nullptr) // data_accessor = this; // synch_parallel = &createParallelSynch(partition, *data_accessor); // synch_registry->registerSynchronizer(*synch_parallel, _gst_material_id); // synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_mass); // synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_stress); // synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_boundary); // synch_registry->registerSynchronizer(*synch_parallel, _gst_for_dump); // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initFEEngineBoundary() { FEEngine & fem_boundary = getFEEngineBoundary(); fem_boundary.initShapeFunctions(_not_ghost); fem_boundary.initShapeFunctions(_ghost); fem_boundary.computeNormalsOnIntegrationPoints(_not_ghost); fem_boundary.computeNormalsOnIntegrationPoints(_ghost); } /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::initArraysPreviousDisplacment() { // AKANTU_DEBUG_IN(); // this->setIncrementFlagOn(); // if (not this->previous_displacement) { // this->allocNodalField(this->previous_displacement, spatial_dimension, // "previous_displacement"); // this->getDOFManager().registerDOFsPrevious("displacement", // *this->previous_displacement); // } // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ /** * Allocate all the needed vectors. By default their are not necessarily set to * 0 */ void SolidMechanicsModel::initArrays() { AKANTU_DEBUG_IN(); for (auto ghost_type : ghost_types) { for (auto type : mesh.elementTypes(Model::spatial_dimension, ghost_type, _ek_not_defined)) { UInt nb_element = mesh.getNbElement(type, ghost_type); this->material_index.alloc(nb_element, 1, type, ghost_type); this->material_local_numbering.alloc(nb_element, 1, type, ghost_type); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Initialize the model,basically it pre-compute the shapes, shapes derivatives * and jacobian * */ void SolidMechanicsModel::initModel() { /// \todo add the current position as a parameter to initShapeFunctions for /// large deformation getFEEngine().initShapeFunctions(_not_ghost); getFEEngine().initShapeFunctions(_ghost); } /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::initPBC() { // Model::initPBC(); // registerPBCSynchronizer(); // // as long as there are ones on the diagonal of the matrix, we can put // // boudandary true for slaves // std::map<UInt, UInt>::iterator it = pbc_pair.begin(); // std::map<UInt, UInt>::iterator end = pbc_pair.end(); // UInt dim = mesh.getSpatialDimension(); // while (it != end) { // for (UInt i = 0; i < dim; ++i) // (*blocked_dofs)((*it).first, i) = true; // ++it; // } // } // /* -------------------------------------------------------------------------- // */ // void SolidMechanicsModel::registerPBCSynchronizer() { // pbc_synch = new PBCSynchronizer(pbc_pair); // synch_registry->registerSynchronizer(*pbc_synch, _gst_smm_uv); // synch_registry->registerSynchronizer(*pbc_synch, _gst_smm_mass); // synch_registry->registerSynchronizer(*pbc_synch, _gst_smm_res); // synch_registry->registerSynchronizer(*pbc_synch, _gst_for_dump); // // changeLocalEquationNumberForPBC(pbc_pair, mesh.getSpatialDimension()); // } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleResidual() { AKANTU_DEBUG_IN(); /* ------------------------------------------------------------------------ */ // computes the internal forces this->assembleInternalForces(); /* ------------------------------------------------------------------------ */ this->getDOFManager().assembleToResidual("displacement", *this->external_force, 1); this->getDOFManager().assembleToResidual("displacement", *this->internal_force, -1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleJacobian() { this->assembleStiffnessMatrix(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::predictor() { ++displacement_release; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::corrector() { ++displacement_release; } /* -------------------------------------------------------------------------- */ /** * This function computes the internal forces as F_{int} = \int_{\Omega} N * \sigma d\Omega@f$ */ void SolidMechanicsModel::assembleInternalForces() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the internal forces"); this->internal_force->clear(); // compute the stresses of local elements AKANTU_DEBUG_INFO("Compute local stresses"); for (auto & material : materials) { material->computeAllStresses(_not_ghost); } #ifdef AKANTU_DAMAGE_NON_LOCAL /* ------------------------------------------------------------------------ */ /* Computation of the non local part */ this->computeAllNonLocalStresses(); #endif // communicate the stresses AKANTU_DEBUG_INFO("Send data for residual assembly"); this->asynchronousSynchronize(_gst_smm_stress); // assemble the forces due to local stresses AKANTU_DEBUG_INFO("Assemble residual for local elements"); for (auto & material : materials) { material->assembleInternalForces(_not_ghost); } // finalize communications AKANTU_DEBUG_INFO("Wait distant stresses"); this->waitEndSynchronize(_gst_smm_stress); // assemble the stresses due to ghost elements AKANTU_DEBUG_INFO("Assemble residual for ghost elements"); for (auto & material : materials) { material->assembleInternalForces(_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleStiffnessMatrix() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the new stiffness matrix."); // Check if materials need to recompute the matrix bool need_to_reassemble = false; for (auto & material : materials) { need_to_reassemble |= material->hasStiffnessMatrixChanged(); } if (need_to_reassemble) { this->getDOFManager().getMatrix("K").clear(); // call compute stiffness matrix on each local elements for (auto & material : materials) { material->assembleStiffnessMatrix(_not_ghost); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateCurrentPosition() { if (this->current_position_release == this->displacement_release) return; this->current_position->copy(this->mesh.getNodes()); auto cpos_it = this->current_position->begin(Model::spatial_dimension); auto cpos_end = this->current_position->end(Model::spatial_dimension); auto disp_it = this->displacement->begin(Model::spatial_dimension); for (; cpos_it != cpos_end; ++cpos_it, ++disp_it) { *cpos_it += *disp_it; } this->current_position_release = this->displacement_release; } /* -------------------------------------------------------------------------- */ const Array<Real> & SolidMechanicsModel::getCurrentPosition() { this->updateCurrentPosition(); return *this->current_position; } /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::initializeUpdateResidualData() { // AKANTU_DEBUG_IN(); // UInt nb_nodes = mesh.getNbNodes(); // internal_force->resize(nb_nodes); // /// copy the forces in residual for boundary conditions // this->getDOFManager().assembleToResidual("displacement", // *this->external_force); // // start synchronization // this->asynchronousSynchronize(_gst_smm_uv); // this->waitEndSynchronize(_gst_smm_uv); // this->updateCurrentPosition(); // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ /* Explicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::computeStresses() { // if (isExplicit()) { // // start synchronization // this->asynchronousSynchronize(_gst_smm_uv); // this->waitEndSynchronize(_gst_smm_uv); // // compute stresses on all local elements for each materials // std::vector<Material *>::iterator mat_it; // for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { // Material & mat = **mat_it; // mat.computeAllStresses(_not_ghost); // } // #ifdef AKANTU_DAMAGE_NON_LOCAL // /* Computation of the non local part */ // this->non_local_manager->computeAllNonLocalStresses(); // #endif // } else { // std::vector<Material *>::iterator mat_it; // for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { // Material & mat = **mat_it; // mat.computeAllStressesFromTangentModuli(_not_ghost); // } // } // } /* -------------------------------------------------------------------------- */ /* Implicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ // /** // * Initialize the solver and create the sparse matrices needed. // * // */ // void SolidMechanicsModel::initSolver(__attribute__((unused)) // SolverOptions & options) { // UInt nb_global_nodes = mesh.getNbGlobalNodes(); // jacobian_matrix = &(this->getDOFManager().getNewMatrix("jacobian", // _symmetric)); // // jacobian_matrix->buildProfile(mesh, *dof_synchronizer, // spatial_dimension); // if (!isExplicit()) { // delete stiffness_matrix; // std::stringstream sstr_sti; // sstr_sti << id << ":stiffness_matrix"; // stiffness_matrix = &(this->getDOFManager().getNewMatrix("stiffness", // _symmetric)); // } // if (solver) solver->initialize(options); // } // /* -------------------------------------------------------------------------- // */ // void SolidMechanicsModel::initJacobianMatrix() { // // @todo make it more flexible: this is an ugly patch to treat the case of // non // // fix profile of the K matrix // delete jacobian_matrix; // jacobian_matrix = &(this->getDOFManager().getNewMatrix("jacobian", // "stiffness")); // std::stringstream sstr_solv; sstr_solv << id << ":solver"; // delete solver; // solver = new SolverMumps(*jacobian_matrix, sstr_solv.str()); // if(solver) // solver->initialize(_solver_no_options); // } /* -------------------------------------------------------------------------- */ /** * Initialize the implicit solver, either for dynamic or static cases, * * @param dynamic */ // void SolidMechanicsModel::initImplicit(bool dynamic) { // AKANTU_DEBUG_IN(); // method = dynamic ? _implicit_dynamic : _static; // if (!increment) // setIncrementFlagOn(); // initSolver(); // // if(method == _implicit_dynamic) { // // if(integrator) delete integrator; // // integrator = new TrapezoidalRule2(); // // } // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ // SparseMatrix & SolidMechanicsModel::initVelocityDampingMatrix() { // return this->getDOFManager().getNewMatrix("velocity_damping", "jacobian"); // } // /* -------------------------------------------------------------------------- // */ // void SolidMechanicsModel::implicitPred() { // AKANTU_DEBUG_IN(); // if(previous_displacement) previous_displacement->copy(*displacement); // if(method == _implicit_dynamic) // integrator->integrationSchemePred(time_step, // *displacement, // *velocity, // *acceleration, // *blocked_dofs); // AKANTU_DEBUG_OUT(); // } // /* -------------------------------------------------------------------------- // */ // void SolidMechanicsModel::implicitCorr() { // AKANTU_DEBUG_IN(); // if(method == _implicit_dynamic) { // integrator->integrationSchemeCorrDispl(time_step, // *displacement, // *velocity, // *acceleration, // *blocked_dofs, // *increment); // } else { // UInt nb_nodes = displacement->getSize(); // UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes; // Real * incr_val = increment->storage(); // Real * disp_val = displacement->storage(); // bool * boun_val = blocked_dofs->storage(); // for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++disp_val, ++incr_val, // ++boun_val){ // *incr_val *= (1. - *boun_val); // *disp_val += *incr_val; // } // } // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::updateIncrement() { // AKANTU_DEBUG_IN(); // auto incr_it = this->displacement_increment->begin(spatial_dimension); // auto incr_end = this->displacement_increment->end(spatial_dimension); // auto disp_it = this->displacement->begin(spatial_dimension); // auto prev_disp_it = this->previous_displacement->begin(spatial_dimension); // for (; incr_it != incr_end; ++incr_it) { // *incr_it = *disp_it; // *incr_it -= *prev_disp_it; // } // AKANTU_DEBUG_OUT(); // } // /* -------------------------------------------------------------------------- // */ void SolidMechanicsModel::updatePreviousDisplacement() { // AKANTU_DEBUG_IN(); // AKANTU_DEBUG_ASSERT( // previous_displacement, // "The previous displacement has to be initialized." // << " Are you working with Finite or Ineslactic deformations?"); // previous_displacement->copy(*displacement); // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateDataForNonLocalCriterion( ElementTypeMapReal & criterion) { const ID field_name = criterion.getName(); for (auto & material : materials) { if (!material->isInternal<Real>(field_name, _ek_regular)) continue; for (auto ghost_type : ghost_types) { material->flattenInternal(field_name, criterion, ghost_type, _ek_regular); } } } /* -------------------------------------------------------------------------- */ /* Information */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::synchronizeBoundaries() { // AKANTU_DEBUG_IN(); // this->synchronize(_gst_smm_boundary); // AKANTU_DEBUG_OUT(); // } // /* -------------------------------------------------------------------------- // */ void SolidMechanicsModel::synchronizeResidual() { // AKANTU_DEBUG_IN(); // this->synchronize(_gst_smm_res); // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::setIncrementFlagOn() { // AKANTU_DEBUG_IN(); // if (!displacement_increment) { // this->allocNodalField(displacement_increment, spatial_dimension, // "displacement_increment"); // this->getDOFManager().registerDOFsIncrement("displacement", // *this->displacement_increment); // } // increment_flag = true; // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getStableTimeStep() { AKANTU_DEBUG_IN(); Real min_dt = getStableTimeStep(_not_ghost); /// reduction min over all processors StaticCommunicator::getStaticCommunicator().allReduce(min_dt, _so_min); AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getStableTimeStep(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Real min_dt = std::numeric_limits<Real>::max(); this->updateCurrentPosition(); Element elem; elem.ghost_type = ghost_type; elem.kind = _ek_regular; for (auto type : mesh.elementTypes(Model::spatial_dimension, ghost_type, _ek_regular)) { elem.type = type; UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); UInt nb_element = mesh.getNbElement(type); auto mat_indexes = material_index(type, ghost_type).begin(); auto mat_loc_num = material_local_numbering(type, ghost_type).begin(); Array<Real> X(0, nb_nodes_per_element * Model::spatial_dimension); FEEngine::extractNodalToElementField(mesh, *current_position, X, type, _not_ghost); auto X_el = X.begin(Model::spatial_dimension, nb_nodes_per_element); for (UInt el = 0; el < nb_element; ++el, ++X_el, ++mat_indexes, ++mat_loc_num) { elem.element = *mat_loc_num; Real el_h = getFEEngine().getElementInradius(*X_el, type); Real el_c = this->materials[*mat_indexes]->getCelerity(elem); Real el_dt = el_h / el_c; min_dt = std::min(min_dt, el_dt); } } AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy() { AKANTU_DEBUG_IN(); Real ekin = 0.; UInt nb_nodes = mesh.getNbNodes(); if (this->getDOFManager().hasLumpedMatrix("M")) { auto m_it = this->mass->begin(Model::spatial_dimension); auto m_end = this->mass->end(Model::spatial_dimension); auto v_it = this->velocity->begin(Model::spatial_dimension); for (UInt n = 0; m_it != m_end; ++n, ++m_it, ++v_it) { const Vector<Real> & v = *v_it; const Vector<Real> & m = *m_it; Real mv2 = 0; bool is_local_node = mesh.isLocalOrMasterNode(n); // bool is_not_pbc_slave_node = !isPBCSlaveNode(n); bool count_node = is_local_node; // && is_not_pbc_slave_node; if (count_node) { for (UInt i = 0; i < Model::spatial_dimension; ++i) { if (m(i) > std::numeric_limits<Real>::epsilon()) mv2 += v(i) * v(i) * m(i); } } ekin += mv2; } } else if (this->getDOFManager().hasMatrix("M")) { Array<Real> Mv(nb_nodes, Model::spatial_dimension); this->getDOFManager().getMatrix("M").matVecMul(*this->velocity, Mv); auto mv_it = Mv.begin(Model::spatial_dimension); auto mv_end = Mv.end(Model::spatial_dimension); auto v_it = this->velocity->begin(Model::spatial_dimension); for (; mv_it != mv_end; ++mv_it, ++v_it) { ekin += v_it->dot(*mv_it); } } else { AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix."); } StaticCommunicator::getStaticCommunicator().allReduce(ekin, _so_sum); AKANTU_DEBUG_OUT(); return ekin * .5; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy(const ElementType & type, UInt index) { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = getFEEngine().getNbIntegrationPoints(type); Array<Real> vel_on_quad(nb_quadrature_points, Model::spatial_dimension); Array<UInt> filter_element(1, 1, index); getFEEngine().interpolateOnIntegrationPoints(*velocity, vel_on_quad, Model::spatial_dimension, type, _not_ghost, filter_element); Array<Real>::vector_iterator vit = vel_on_quad.begin(Model::spatial_dimension); Array<Real>::vector_iterator vend = vel_on_quad.end(Model::spatial_dimension); Vector<Real> rho_v2(nb_quadrature_points); Real rho = materials[material_index(type)(index)]->getRho(); for (UInt q = 0; vit != vend; ++vit, ++q) { rho_v2(q) = rho * vit->dot(*vit); } AKANTU_DEBUG_OUT(); return .5 * getFEEngine().integrate(rho_v2, type, index); } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getExternalWork() { AKANTU_DEBUG_IN(); auto incr_or_velo_it = this->velocity->begin(Model::spatial_dimension); if (this->method == _static) { incr_or_velo_it = this->displacement_increment->begin(Model::spatial_dimension); } auto ext_force_it = external_force->begin(Model::spatial_dimension); auto int_force_it = internal_force->begin(Model::spatial_dimension); auto boun_it = blocked_dofs->begin(Model::spatial_dimension); Real work = 0.; UInt nb_nodes = this->mesh.getNbNodes(); for (UInt n = 0; n < nb_nodes; ++n, ++ext_force_it, ++int_force_it, ++boun_it, ++incr_or_velo_it) { const auto & int_force = *int_force_it; const auto & ext_force = *ext_force_it; const auto & boun = *boun_it; const auto & incr_or_velo = *incr_or_velo_it; bool is_local_node = this->mesh.isLocalOrMasterNode(n); // bool is_not_pbc_slave_node = !this->isPBCSlaveNode(n); bool count_node = is_local_node; // && is_not_pbc_slave_node; if (count_node) { for (UInt i = 0; i < Model::spatial_dimension; ++i) { if (boun(i)) work -= int_force(i) * incr_or_velo(i); else work += ext_force(i) * incr_or_velo(i); } } } StaticCommunicator::getStaticCommunicator().allReduce(work, _so_sum); if (this->method != _static) work *= this->getTimeStep(); AKANTU_DEBUG_OUT(); return work; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getEnergy(const std::string & energy_id) { AKANTU_DEBUG_IN(); if (energy_id == "kinetic") { return getKineticEnergy(); } else if (energy_id == "external work") { return getExternalWork(); } Real energy = 0.; for (auto & material : materials) energy += material->getEnergy(energy_id); /// reduction sum over all processors StaticCommunicator::getStaticCommunicator().allReduce(energy, _so_sum); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getEnergy(const std::string & energy_id, const ElementType & type, UInt index) { AKANTU_DEBUG_IN(); if (energy_id == "kinetic") { return getKineticEnergy(type, index); } UInt mat_index = this->material_index(type, _not_ghost)(index); UInt mat_loc_num = this->material_local_numbering(type, _not_ghost)(index); Real energy = this->materials[mat_index]->getEnergy(energy_id, type, mat_loc_num); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onElementsAdded(const Array<Element> & element_list, const NewElementsEvent & event) { AKANTU_DEBUG_IN(); this->getFEEngine().initShapeFunctions(_not_ghost); this->getFEEngine().initShapeFunctions(_ghost); for (auto ghost_type : ghost_types) { for (auto type : mesh.elementTypes(Model::spatial_dimension, ghost_type, _ek_not_defined)) { UInt nb_element = this->mesh.getNbElement(type, ghost_type); if (!material_index.exists(type, ghost_type)) { this->material_index.alloc(nb_element, 1, type, ghost_type); this->material_local_numbering.alloc(nb_element, 1, type, ghost_type); } else { this->material_index(type, ghost_type).resize(nb_element); this->material_local_numbering(type, ghost_type).resize(nb_element); } } } ElementTypeMapArray<UInt> filter("new_element_filter", this->getID(), this->getMemoryID()); for (auto & elem : element_list) { if (!filter.exists(elem.type, elem.ghost_type)) filter.alloc(0, 1, elem.type, elem.ghost_type); filter(elem.type, elem.ghost_type).push_back(elem.element); } this->assignMaterialToElements(&filter); for (auto & material : materials) material->onElementsAdded(element_list, event); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onElementsRemoved( __attribute__((unused)) const Array<Element> & element_list, const ElementTypeMapArray<UInt> & new_numbering, const RemovedElementsEvent & event) { this->getFEEngine().initShapeFunctions(_not_ghost); this->getFEEngine().initShapeFunctions(_ghost); for (auto & material : materials) { material->onElementsRemoved(element_list, new_numbering, event); } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onNodesAdded(const Array<UInt> & nodes_list, __attribute__((unused)) const NewNodesEvent & event) { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); if (displacement) displacement->resize(nb_nodes, 0.); if (mass) mass->resize(nb_nodes, 0.); if (velocity) velocity->resize(nb_nodes, 0.); if (acceleration) acceleration->resize(nb_nodes, 0.); if (external_force) external_force->resize(nb_nodes, 0.); if (internal_force) internal_force->resize(nb_nodes, 0.); if (blocked_dofs) blocked_dofs->resize(nb_nodes, 0.); if (previous_displacement) previous_displacement->resize(nb_nodes, 0.); if (displacement_increment) displacement_increment->resize(nb_nodes, 0.); for (auto & material : materials) { material->onNodesAdded(nodes_list, event); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onNodesRemoved(__attribute__((unused)) const Array<UInt> & element_list, const Array<UInt> & new_numbering, __attribute__((unused)) const RemovedNodesEvent & event) { if (displacement) mesh.removeNodesFromArray(*displacement, new_numbering); if (mass) mesh.removeNodesFromArray(*mass, new_numbering); if (velocity) mesh.removeNodesFromArray(*velocity, new_numbering); if (acceleration) mesh.removeNodesFromArray(*acceleration, new_numbering); if (internal_force) mesh.removeNodesFromArray(*internal_force, new_numbering); if (external_force) mesh.removeNodesFromArray(*external_force, new_numbering); if (blocked_dofs) mesh.removeNodesFromArray(*blocked_dofs, new_numbering); // if (increment_acceleration) // mesh.removeNodesFromArray(*increment_acceleration, new_numbering); if (displacement_increment) mesh.removeNodesFromArray(*displacement_increment, new_numbering); if (previous_displacement) mesh.removeNodesFromArray(*previous_displacement, new_numbering); // if (method != _explicit_lumped_mass) { // this->initSolver(); // } } -/* -------------------------------------------------------------------------- */ -bool SolidMechanicsModel::isInternal(const std::string & field_name, - const ElementKind & element_kind) { - /// check if at least one material contains field_id as an internal - for (auto & material : materials) { - bool is_internal = material->isInternal<Real>(field_name, element_kind); - if (is_internal) - return true; - } - - return false; -} -/* -------------------------------------------------------------------------- */ -ElementTypeMap<UInt> -SolidMechanicsModel::getInternalDataPerElem(const std::string & field_name, - const ElementKind & element_kind) { - - if (!(this->isInternal(field_name, element_kind))) - AKANTU_EXCEPTION("unknown internal " << field_name); - - for (auto & material : materials) { - if (material->isInternal<Real>(field_name, element_kind)) - return material->getInternalDataPerElem<Real>(field_name, element_kind); - } - - return ElementTypeMap<UInt>(); -} - -/* -------------------------------------------------------------------------- */ -ElementTypeMapArray<Real> & -SolidMechanicsModel::flattenInternal(const std::string & field_name, - const ElementKind & kind, - const GhostType ghost_type) { - std::pair<std::string, ElementKind> key(field_name, kind); - if (this->registered_internals.count(key) == 0) { - this->registered_internals[key] = - new ElementTypeMapArray<Real>(field_name, this->id, this->memory_id); - } - - ElementTypeMapArray<Real> * internal_flat = this->registered_internals[key]; - - for (auto type : - mesh.elementTypes(Model::spatial_dimension, ghost_type, kind)) { - if (internal_flat->exists(type, ghost_type)) { - auto & internal = (*internal_flat)(type, ghost_type); - // internal.clear(); - internal.resize(0); - } - } - - for (auto & material : materials) { - if (material->isInternal<Real>(field_name, kind)) - material->flattenInternal(field_name, *internal_flat, ghost_type, kind); - } - - return *internal_flat; -} - -/* -------------------------------------------------------------------------- */ -void SolidMechanicsModel::flattenAllRegisteredInternals( - const ElementKind & kind) { - ElementKind _kind; - ID _id; - - for (auto & internal : this->registered_internals) { - std::tie(_id, _kind) = internal.first; - if (kind == _kind) - this->flattenInternal(_id, kind); - } -} - -/* -------------------------------------------------------------------------- */ -void SolidMechanicsModel::onDump() { - this->flattenAllRegisteredInternals(_ek_regular); -} - -/* -------------------------------------------------------------------------- */ -#ifdef AKANTU_USE_IOHELPER -dumper::Field * SolidMechanicsModel::createElementalField( - const std::string & field_name, const std::string & group_name, - bool padding_flag, const UInt & spatial_dimension, - const ElementKind & kind) { - - dumper::Field * field = nullptr; - - if (field_name == "partitions") - field = mesh.createElementalField<UInt, dumper::ElementPartitionField>( - mesh.getConnectivities(), group_name, spatial_dimension, kind); - else if (field_name == "material_index") - field = mesh.createElementalField<UInt, Vector, dumper::ElementalField>( - material_index, group_name, spatial_dimension, kind); - else { - // this copy of field_name is used to compute derivated data such as - // strain and von mises stress that are based on grad_u and stress - std::string field_name_copy(field_name); - - if (field_name == "strain" || field_name == "Green strain" || - field_name == "principal strain" || - field_name == "principal Green strain") - field_name_copy = "grad_u"; - else if (field_name == "Von Mises stress") - field_name_copy = "stress"; - - bool is_internal = this->isInternal(field_name_copy, kind); - - if (is_internal) { - ElementTypeMap<UInt> nb_data_per_elem = - this->getInternalDataPerElem(field_name_copy, kind); - ElementTypeMapArray<Real> & internal_flat = - this->flattenInternal(field_name_copy, kind); - field = mesh.createElementalField<Real, dumper::InternalMaterialField>( - internal_flat, group_name, spatial_dimension, kind, nb_data_per_elem); - if (field_name == "strain") { - dumper::ComputeStrain<false> * foo = - new dumper::ComputeStrain<false>(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); - } else if (field_name == "Von Mises stress") { - dumper::ComputeVonMisesStress * foo = - new dumper::ComputeVonMisesStress(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); - } else if (field_name == "Green strain") { - dumper::ComputeStrain<true> * foo = - new dumper::ComputeStrain<true>(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); - } else if (field_name == "principal strain") { - dumper::ComputePrincipalStrain<false> * foo = - new dumper::ComputePrincipalStrain<false>(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); - } else if (field_name == "principal Green strain") { - dumper::ComputePrincipalStrain<true> * foo = - new dumper::ComputePrincipalStrain<true>(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); - } - - // treat the paddings - if (padding_flag) { - if (field_name == "stress") { - if (spatial_dimension == 2) { - dumper::StressPadder<2> * foo = new dumper::StressPadder<2>(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); - } - } else if (field_name == "strain" || field_name == "Green strain") { - if (spatial_dimension == 2) { - dumper::StrainPadder<2> * foo = new dumper::StrainPadder<2>(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); - } - } - } - - // homogenize the field - dumper::ComputeFunctorInterface * foo = - dumper::HomogenizerProxy::createHomogenizer(*field); - - field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); - } - } - return field; -} - -/* -------------------------------------------------------------------------- */ -dumper::Field * -SolidMechanicsModel::createNodalFieldReal(const std::string & field_name, - const std::string & group_name, - bool padding_flag) { - - std::map<std::string, Array<Real> *> real_nodal_fields; - real_nodal_fields["displacement"] = this->displacement; - real_nodal_fields["mass"] = this->mass; - real_nodal_fields["velocity"] = this->velocity; - real_nodal_fields["acceleration"] = this->acceleration; - real_nodal_fields["external_force"] = this->external_force; - real_nodal_fields["internal_force"] = this->internal_force; - real_nodal_fields["increment"] = this->displacement_increment; - - if (field_name == "force") { - AKANTU_EXCEPTION("The 'force' field has been renamed in 'external_force'"); - } else if (field_name == "residual") { - AKANTU_EXCEPTION( - "The 'residual' field has been replaced by 'internal_force'"); - } - - dumper::Field * field = nullptr; - if (padding_flag) - field = this->mesh.createNodalField(real_nodal_fields[field_name], - group_name, 3); - else - field = - this->mesh.createNodalField(real_nodal_fields[field_name], group_name); - - return field; -} - -/* -------------------------------------------------------------------------- */ -dumper::Field * SolidMechanicsModel::createNodalFieldBool( - const std::string & field_name, const std::string & group_name, - __attribute__((unused)) bool padding_flag) { - - std::map<std::string, Array<bool> *> uint_nodal_fields; - uint_nodal_fields["blocked_dofs"] = blocked_dofs; - - dumper::Field * field = nullptr; - field = mesh.createNodalField(uint_nodal_fields[field_name], group_name); - return field; -} -/* -------------------------------------------------------------------------- */ -#else -/* -------------------------------------------------------------------------- */ -dumper::Field * SolidMechanicsModel::createElementalField(const std::string &, - const std::string &, - bool, const UInt &, - const ElementKind &) { - return nullptr; -} -/* -------------------------------------------------------------------------- - */ -dumper::Field * SolidMechanicsModel::createNodalFieldReal(const std::string &, - const std::string &, - bool) { - return nullptr; -} - -/* -------------------------------------------------------------------------- - */ -dumper::Field * SolidMechanicsModel::createNodalFieldBool(const std::string &, - const std::string &, - bool) { - return nullptr; -} - -#endif -/* -------------------------------------------------------------------------- - */ -void SolidMechanicsModel::dump(const std::string & dumper_name) { - this->onDump(); - EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); - mesh.dump(dumper_name); -} - -/* -------------------------------------------------------------------------- - */ -void SolidMechanicsModel::dump(const std::string & dumper_name, UInt step) { - this->onDump(); - EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); - mesh.dump(dumper_name, step); -} - -/* ------------------------------------------------------------------------- - */ -void SolidMechanicsModel::dump(const std::string & dumper_name, Real time, - UInt step) { - this->onDump(); - EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); - mesh.dump(dumper_name, time, step); -} - -/* -------------------------------------------------------------------------- */ -void SolidMechanicsModel::dump() { - this->onDump(); - EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); - mesh.dump(); -} - -/* -------------------------------------------------------------------------- */ -void SolidMechanicsModel::dump(UInt step) { - this->onDump(); - EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); - mesh.dump(step); -} - -/* -------------------------------------------------------------------------- */ -void SolidMechanicsModel::dump(Real time, UInt step) { - this->onDump(); - EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); - mesh.dump(time, step); -} - /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "Solid Mechanics Model [" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + spatial dimension : " << Model::spatial_dimension << std::endl; stream << space << " + fem [" << std::endl; getFEEngine().printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + nodals information [" << std::endl; displacement->printself(stream, indent + 2); mass->printself(stream, indent + 2); velocity->printself(stream, indent + 2); acceleration->printself(stream, indent + 2); external_force->printself(stream, indent + 2); internal_force->printself(stream, indent + 2); blocked_dofs->printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + material information [" << std::endl; material_index.printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + materials [" << std::endl; for (auto & material : materials) { material->printself(stream, indent + 1); } stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::insertIntegrationPointsInNeighborhoods( const GhostType & ghost_type) { for (auto & mat : materials) { try { ElementTypeMapArray<Real> quadrature_points_coordinates( "quadrature_points_coordinates_tmp_nl", this->id, this->memory_id); quadrature_points_coordinates.initialize( this->getFEEngine(), _spatial_dimension = Model::spatial_dimension, _nb_component = Model::spatial_dimension, _ghost_type = ghost_type); for (auto & type : quadrature_points_coordinates.elementTypes( Model::spatial_dimension, ghost_type)) { this->getFEEngine().computeIntegrationPointsCoordinates( quadrature_points_coordinates(type, ghost_type), type, ghost_type); } auto & mat_non_local = dynamic_cast<MaterialNonLocalInterface &>(*mat); mat_non_local.insertIntegrationPointsInNeighborhoods( ghost_type, quadrature_points_coordinates); } catch (std::bad_cast &) { } } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::computeNonLocalStresses( const GhostType & ghost_type) { for (auto & mat : materials) { try { auto & mat_non_local = dynamic_cast<MaterialNonLocalInterface &>(*mat); mat_non_local.computeNonLocalStresses(ghost_type); } catch (std::bad_cast &) { } } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateLocalInternal( ElementTypeMapReal & internal_flat, const GhostType & ghost_type, const ElementKind & kind) { const ID field_name = internal_flat.getName(); for (auto & material : materials) { if (material->isInternal<Real>(field_name, kind)) material->flattenInternal(field_name, internal_flat, ghost_type, kind); } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateNonLocalInternal( ElementTypeMapReal & internal_flat, const GhostType & ghost_type, const ElementKind & kind) { const ID field_name = internal_flat.getName(); for (auto & mat : materials) { try { auto & mat_non_local = dynamic_cast<MaterialNonLocalInterface &>(*mat); mat_non_local.updateNonLocalInternals(internal_flat, field_name, ghost_type, kind); } catch (std::bad_cast &) { } } } /* -------------------------------------------------------------------------- */ } // namespace akantu diff --git a/src/model/solid_mechanics/solid_mechanics_model.hh b/src/model/solid_mechanics/solid_mechanics_model.hh index 9e816c26c..ad7e9d873 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.hh +++ b/src/model/solid_mechanics/solid_mechanics_model.hh @@ -1,827 +1,809 @@ /** * @file solid_mechanics_model.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Jan 19 2016 * * @brief Model of Solid Mechanics * * @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_SOLID_MECHANICS_MODEL_HH__ -#define __AKANTU_SOLID_MECHANICS_MODEL_HH__ - -/* -------------------------------------------------------------------------- */ -#include <fstream> /* -------------------------------------------------------------------------- */ - -/* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "aka_named_argument.hh" -#include "aka_types.hh" #include "boundary_condition.hh" #include "data_accessor.hh" -#include "dumpable.hh" -#include "integrator_gauss.hh" -#include "material_selector.hh" -#include "mesh.hh" #include "model.hh" #include "non_local_manager.hh" -#include "shape_lagrange.hh" #include "solid_mechanics_model_event_handler.hh" /* -------------------------------------------------------------------------- */ +#include "integrator_gauss.hh" +#include "shape_lagrange.hh" +/* -------------------------------------------------------------------------- */ + +#ifndef __AKANTU_SOLID_MECHANICS_MODEL_HH__ +#define __AKANTU_SOLID_MECHANICS_MODEL_HH__ + namespace akantu { class Material; +class MaterialSelector; class DumperIOHelper; class NonLocalManager; } // namespace akantu -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ namespace akantu { struct SolidMechanicsModelOptions : public ModelOptions { SolidMechanicsModelOptions( - AnalysisMethod analysis_method = _explicit_lumped_mass, - bool no_init_materials = false) - : analysis_method(analysis_method), no_init_materials(no_init_materials) { - } + AnalysisMethod analysis_method = _explicit_lumped_mass); template <typename... pack> - SolidMechanicsModelOptions(use_named_args_t, pack &&... _pack) - : SolidMechanicsModelOptions( - OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass), - OPTIONAL_NAMED_ARG(no_init_materials, false)) {} + SolidMechanicsModelOptions(use_named_args_t, pack &&... _pack); AnalysisMethod analysis_method; bool no_init_materials; }; -extern const SolidMechanicsModelOptions default_solid_mechanics_model_options; - +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ class SolidMechanicsModel : public Model, public DataAccessor<Element>, public DataAccessor<UInt>, public BoundaryCondition<SolidMechanicsModel>, public NonLocalManager, public EventHandlerManager<SolidMechanicsModelEventHandler> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: class NewMaterialElementsEvent : public NewElementsEvent { public: AKANTU_GET_MACRO_NOT_CONST(MaterialList, material, Array<UInt> &); AKANTU_GET_MACRO(MaterialList, material, const Array<UInt> &); protected: Array<UInt> material; }; - typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange> MyFEEngineType; + using MyFEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>; protected: - typedef EventHandlerManager<SolidMechanicsModelEventHandler> EventManager; + using EventManager = EventHandlerManager<SolidMechanicsModelEventHandler>; public: SolidMechanicsModel(Mesh & mesh, UInt spatial_dimension = _all_dimensions, const ID & id = "solid_mechanics_model", const MemoryID & memory_id = 0); virtual ~SolidMechanicsModel(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: template <typename P, typename T, typename... pack> void initFull(named_argument::param_t<P, T &&> && first, pack &&... _pack) { this->initFull(SolidMechanicsModelOptions{use_named_args, first, _pack...}); } /// initialize completely the model void initFull( const ModelOptions & options = SolidMechanicsModelOptions()) override; /// initialize the fem object needed for boundary conditions void initFEEngineBoundary(); /// register the tags associated with the parallel synchronizer // virtual void initParallel(MeshPartition * partition, // DataAccessor<Element> * data_accessor = NULL); /// allocate all vectors virtual void initArrays(); /// allocate all vectors // void initArraysPreviousDisplacment(); /// initialize all internal arrays for materials virtual void initMaterials(); /// initialize the model void initModel() override; /// init PBC synchronizer // void initPBC(); /// initialize a new solver and sets it as the default one to use void initNewSolver(const AnalysisMethod & method); /// function to print the containt of the class void printself(std::ostream & stream, int indent = 0) const override; protected: /// allocate an array if needed template <typename T> void allocNodalField(Array<T> *& array, const ID & name); /* ------------------------------------------------------------------------ */ /* PBC */ /* ------------------------------------------------------------------------ */ public: /// change the equation number for proper assembly when using PBC // void changeEquationNumberforPBC(std::map <UInt, UInt> & pbc_pair); /// synchronize Residual for output // void synchronizeResidual(); protected: /// register PBC synchronizer // void registerPBCSynchronizer(); /* ------------------------------------------------------------------------ */ /* Solver interface */ /* ------------------------------------------------------------------------ */ public: /// assembles the stiffness matrix, virtual void assembleStiffnessMatrix(); /// assembles the internal forces in the array internal_forces virtual void assembleInternalForces(); protected: /// callback for the solver, this adds f_{ext} - f_{int} to the residual void assembleResidual() override; /// callback for the solver, this assembles the stiffness matrix void assembleJacobian() override; /// callback for the solver, this is called at beginning of solve void predictor() override; /// callback for the solver, this is called at end of solve void corrector() override; /// Callback for the model to instantiate the matricees when needed void initSolver(TimeStepSolverType time_step_solver_type, NonLinearSolverType non_linear_solver_type) override; protected: /* ------------------------------------------------------------------------ */ TimeStepSolverType getDefaultSolverType() const override; /* ------------------------------------------------------------------------ */ ModelSolverOptions getDefaultSolverOptions(const TimeStepSolverType & type) const override; /* ------------------------------------------------------------------------ */ /* Explicit */ /* ------------------------------------------------------------------------ */ // public: // /// initialize the stuff for the explicit scheme // void initExplicit(AnalysisMethod analysis_method = // _explicit_lumped_mass); public: bool isDefaultSolverExplicit() { return method == _explicit_lumped_mass || method == _explicit_consistent_mass; } // /// initialize the array needed by updateResidual (residual, // current_position) // void initializeUpdateResidualData(); protected: /// update the current position vector void updateCurrentPosition(); // /// assemble the residual for the explicit scheme // virtual void updateResidual(bool need_initialize = true); // /** // * \brief compute the acceleration from the residual // * this function is the explicit equivalent to solveDynamic in implicit // * In the case of lumped mass just divide the residual by the mass // * In the case of not lumped mass call // solveDynamic<_acceleration_corrector> // */ // void updateAcceleration(); /// Update the increment of displacement // void updateIncrement(); // /// Copy the actuel displacement into previous displacement // void updatePreviousDisplacement(); // /// Save stress and strain through EventManager // void saveStressAndStrainBeforeDamage(); // /// Update energies through EventManager // void updateEnergiesAfterDamage(); // /// Solve the system @f[ A x = \alpha b @f] with A a lumped matrix // void solveLumped(Array<Real> & x, const Array<Real> & A, // const Array<Real> & b, const Array<bool> & blocked_dofs, // Real alpha); // /// explicit integration predictor // void explicitPred(); // /// explicit integration corrector // void explicitCorr(); // public: // void solveStep(); // /* // ------------------------------------------------------------------------ // */ // /* Implicit */ // /* // ------------------------------------------------------------------------ // */ // public: // /// initialize the solver and the jacobian_matrix (called by // initImplicit) // void initSolver(); // /// initialize the stuff for the implicit solver // void initImplicit(bool dynamic = false); // /// solve Ma = f to get the initial acceleration // void initialAcceleration(); // /// assemble the stiffness matrix // void assembleStiffnessMatrix(); // public: // /** // * solve a step (predictor + convergence loop + corrector) using the // * the given convergence method (see akantu::SolveConvergenceMethod) // * and the given convergence criteria (see // * akantu::SolveConvergenceCriteria) // **/ // template <SolveConvergenceMethod method, SolveConvergenceCriteria // criteria> // bool solveStep(Real tolerance, UInt max_iteration = 100); // template <SolveConvergenceMethod method, SolveConvergenceCriteria // criteria> // bool solveStep(Real tolerance, Real & error, UInt max_iteration = 100, // bool do_not_factorize = false); // public: // /** // * solve Ku = f using the the given convergence method (see // * akantu::SolveConvergenceMethod) and the given convergence // * criteria (see akantu::SolveConvergenceCriteria) // **/ // template <SolveConvergenceMethod cmethod, SolveConvergenceCriteria // criteria> // bool solveStatic(Real tolerance, UInt max_iteration, // bool do_not_factorize = false); // /// create and return the velocity damping matrix // SparseMatrix & initVelocityDampingMatrix(); // /// implicit time integration predictor // void implicitPred(); // /// implicit time integration corrector // void implicitCorr(); // /// compute the Cauchy stress on user demand. // void computeCauchyStresses(); // // /// compute A and solve @f[ A\delta u = f_ext - f_int @f] // // template <NewmarkBeta::IntegrationSchemeCorrectorType type> // // void solve(Array<Real> &increment, Real block_val = 1., // // bool need_factorize = true, bool has_profile_changed = // false); // protected: // /// finish the computation of residual to solve in increment // void updateResidualInternal(); // /// compute the support reaction and store it in force // void updateSupportReaction(); // private: // /// re-initialize the J matrix (to use if the profile of K changed) // void initJacobianMatrix(); /* ------------------------------------------------------------------------ */ // public: /// Update the stresses for the computation of the residual of the Stiffness /// matrix in the case of finite deformation // void computeStresses(); /// synchronize the ghost element boundaries values // void synchronizeBoundaries(); /* ------------------------------------------------------------------------ */ /* Materials (solid_mechanics_model_material.cc) */ /* ------------------------------------------------------------------------ */ public: /// registers all the custom materials of a given type present in the input /// file - template <typename M> void registerNewCustomMaterials(const ID & mat_type); + // template <typename M> void registerNewCustomMaterials(const ID & mat_type); /// register an empty material of a given type - template <typename M> - Material & registerNewEmptyMaterial(const std::string & name); - - // /// Use a UIntData in the mesh to specify the material to use per element - // void setMaterialIDsFromIntData(const std::string & data_name); + Material & registerNewMaterial(const ID & mat_name, const ID & mat_type, + const ID & opt_param); + // /// Use a UIntData in the mesh to specify the material to use per + // element void setMaterialIDsFromIntData(const std::string & data_name); /// reassigns materials depending on the material selector virtual void reassignMaterial(); /// apply a constant eigen_grad_u on all quadrature points of a given material virtual void applyEigenGradU(const Matrix<Real> & prescribed_eigen_grad_u, const ID & material_name, const GhostType ghost_type = _not_ghost); protected: /// register a material in the dynamic database - template <typename M> Material & registerNewMaterial(const ParserSection & mat_section); /// read the material files to instantiate all the materials void instantiateMaterials(); /// set the element_id_by_material and add the elements to the good materials void assignMaterialToElements(const ElementTypeMapArray<UInt> * filter = NULL); /// reinitialize dof_synchronizer and solver (either in implicit or /// explicit) when cohesive elements are inserted - //void reinitializeSolver(); + // void reinitializeSolver(); /* ------------------------------------------------------------------------ */ /* Mass (solid_mechanics_model_mass.cc) */ /* ------------------------------------------------------------------------ */ public: /// assemble the lumped mass matrix void assembleMassLumped(); /// assemble the mass matrix for consistent mass resolutions void assembleMass(); protected: /// assemble the lumped mass matrix for local and ghost elements void assembleMassLumped(GhostType ghost_type); /// assemble the mass matrix for either _ghost or _not_ghost elements void assembleMass(GhostType ghost_type); /// fill a vector of rho void computeRho(Array<Real> & rho, ElementType type, GhostType ghost_type); /// compute the kinetic energy Real getKineticEnergy(); Real getKineticEnergy(const ElementType & type, UInt index); /// compute the external work (for impose displacement, the velocity should be /// given too) Real getExternalWork(); /* ------------------------------------------------------------------------ */ /* NonLocalManager inherited members */ /* ------------------------------------------------------------------------ */ protected: void updateDataForNonLocalCriterion(ElementTypeMapReal & criterion) override; void computeNonLocalStresses(const GhostType & ghost_type) override; void insertIntegrationPointsInNeighborhoods(const GhostType & ghost_type) override; /// update the values of the non local internal void updateLocalInternal(ElementTypeMapReal & internal_flat, const GhostType & ghost_type, const ElementKind & kind) override; /// copy the results of the averaging in the materials void updateNonLocalInternal(ElementTypeMapReal & internal_flat, const GhostType & ghost_type, const ElementKind & kind) override; /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ public: 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; inline UInt getNbData(const Array<UInt> & dofs, const SynchronizationTag & tag) const override; inline void packData(CommunicationBuffer & buffer, const Array<UInt> & dofs, const SynchronizationTag & tag) const override; inline void unpackData(CommunicationBuffer & buffer, const Array<UInt> & dofs, const SynchronizationTag & tag) override; protected: inline void splitElementByMaterial(const Array<Element> & elements, Array<Element> * elements_per_mat) const; /* ------------------------------------------------------------------------ */ /* Mesh Event Handler inherited members */ /* ------------------------------------------------------------------------ */ protected: void onNodesAdded(const Array<UInt> & nodes_list, const NewNodesEvent & event) override; void onNodesRemoved(const Array<UInt> & element_list, const Array<UInt> & new_numbering, const RemovedNodesEvent & event) override; void onElementsAdded(const Array<Element> & nodes_list, const NewElementsEvent & event) override; void onElementsRemoved(const Array<Element> & element_list, const ElementTypeMapArray<UInt> & new_numbering, const RemovedElementsEvent & event) override; void onElementsChanged(const Array<Element> &, const Array<Element> &, const ElementTypeMapArray<UInt> &, const ChangedElementsEvent &) override{}; /* ------------------------------------------------------------------------ */ /* Dumpable interface (kept for convenience) and dumper relative functions */ /* ------------------------------------------------------------------------ */ public: virtual void onDump(); //! decide wether a field is a material internal or not bool isInternal(const std::string & field_name, const ElementKind & element_kind); #ifndef SWIG //! give the amount of data per element virtual ElementTypeMap<UInt> getInternalDataPerElem(const std::string & field_name, const ElementKind & kind); //! flatten a given material internal field ElementTypeMapArray<Real> & flattenInternal(const std::string & field_name, const ElementKind & kind, const GhostType ghost_type = _not_ghost); //! flatten all the registered material internals void flattenAllRegisteredInternals(const ElementKind & kind); #endif dumper::Field * createNodalFieldReal(const std::string & field_name, const std::string & group_name, bool padding_flag) override; dumper::Field * createNodalFieldBool(const std::string & field_name, const std::string & group_name, bool padding_flag) override; dumper::Field * createElementalField(const std::string & field_name, const std::string & group_name, bool padding_flag, const UInt & spatial_dimension, const ElementKind & kind) override; virtual void dump(const std::string & dumper_name); virtual void dump(const std::string & dumper_name, UInt step); virtual void dump(const std::string & dumper_name, Real time, UInt step); void dump() override; virtual void dump(UInt step); virtual void dump(Real time, UInt step); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// return the dimension of the system space AKANTU_GET_MACRO(SpatialDimension, Model::spatial_dimension, UInt); /// get the current value of the time step // AKANTU_GET_MACRO(TimeStep, time_step, Real); /// set the value of the time step void setTimeStep(Real time_step, const ID & solver_id = "") override; /// void setTimeStep(Real time_step); /// return the of iterations done in the last solveStep // AKANTU_GET_MACRO(NumberIter, n_iter, UInt); /// get the value of the conversion from forces/ mass to acceleration AKANTU_GET_MACRO(F_M2A, f_m2a, Real); /// set the value of the conversion from forces/ mass to acceleration AKANTU_SET_MACRO(F_M2A, f_m2a, Real); /// get the SolidMechanicsModel::displacement vector AKANTU_GET_MACRO(Displacement, *displacement, Array<Real> &); /// get the SolidMechanicsModel::previous_displacement vector AKANTU_GET_MACRO(PreviousDisplacement, *previous_displacement, Array<Real> &); /// get the SolidMechanicsModel::current_position vector \warn only consistent /// after a call to SolidMechanicsModel::updateCurrentPosition const Array<Real> & getCurrentPosition(); /// get the SolidMechanicsModel::increment vector \warn only consistent if /// SolidMechanicsModel::setIncrementFlagOn has been called before AKANTU_GET_MACRO(Increment, *displacement_increment, Array<Real> &); /// get the lumped SolidMechanicsModel::mass vector AKANTU_GET_MACRO(Mass, *mass, Array<Real> &); /// get the SolidMechanicsModel::velocity vector AKANTU_GET_MACRO(Velocity, *velocity, Array<Real> &); /// get the SolidMechanicsModel::acceleration vector, updated by /// SolidMechanicsModel::updateAcceleration AKANTU_GET_MACRO(Acceleration, *acceleration, Array<Real> &); /// get the SolidMechanicsModel::force vector (external forces) AKANTU_GET_MACRO(Force, *external_force, Array<Real> &); /// get the SolidMechanicsModel::internal_force vector (internal forces) AKANTU_GET_MACRO(InternalForce, *internal_force, Array<Real> &); /// get the SolidMechanicsModel::blocked_dofs vector AKANTU_GET_MACRO(BlockedDOFs, *blocked_dofs, Array<bool> &); /// get the SolidMechnicsModel::incrementAcceleration vector // AKANTU_GET_MACRO(IncrementAcceleration, *increment_acceleration, // Array<Real> &); /// get the value of the SolidMechanicsModel::increment_flag AKANTU_GET_MACRO(IncrementFlag, increment_flag, bool); /// get a particular material (by material index) inline Material & getMaterial(UInt mat_index); /// get a particular material (by material index) inline const Material & getMaterial(UInt mat_index) const; /// get a particular material (by material name) inline Material & getMaterial(const std::string & name); /// get a particular material (by material name) inline const Material & getMaterial(const std::string & name) const; /// get a particular material id from is name inline UInt getMaterialIndex(const std::string & name) const; /// give the number of materials inline UInt getNbMaterials() const { return materials.size(); } inline void setMaterialSelector(MaterialSelector & selector); /// give the material internal index from its id Int getInternalIndexFromID(const ID & id) const; /// compute the stable time step Real getStableTimeStep(); /// get the energies Real getEnergy(const std::string & energy_id); /// compute the energy for energy Real getEnergy(const std::string & energy_id, const ElementType & type, UInt index); /** * @brief set the SolidMechanicsModel::increment_flag to on, the activate the * update of the SolidMechanicsModel::increment vector */ // void setIncrementFlagOn(); // /// get the stiffness matrix // AKANTU_GET_MACRO(StiffnessMatrix, *stiffness_matrix, SparseMatrix &); // /// get the global jacobian matrix of the system // AKANTU_GET_MACRO(GlobalJacobianMatrix, *jacobian_matrix, const SparseMatrix // &); // /// get the mass matrix // AKANTU_GET_MACRO(MassMatrix, *mass_matrix, SparseMatrix &); // /// get the velocity damping matrix // AKANTU_GET_MACRO(VelocityDampingMatrix, *velocity_damping_matrix, // SparseMatrix &); /// get the FEEngine object to integrate or interpolate on the boundary inline FEEngine & getFEEngineBoundary(const ID & name = ""); // /// get integrator // AKANTU_GET_MACRO(Integrator, *integrator, const IntegrationScheme2ndOrder // &); // /// get synchronizer // AKANTU_GET_MACRO(Synchronizer, *synch_parallel, const ElementSynchronizer // &); AKANTU_GET_MACRO(MaterialByElement, material_index, const ElementTypeMapArray<UInt> &); /// vectors containing local material element index for each global element /// index AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialByElement, material_index, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialByElement, material_index, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialLocalNumbering, material_local_numbering, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialLocalNumbering, material_local_numbering, UInt); /// Get the type of analysis method used AKANTU_GET_MACRO(AnalysisMethod, method, AnalysisMethod); protected: friend class Material; protected: /// compute the stable time step Real getStableTimeStep(const GhostType & ghost_type); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// number of iterations // UInt n_iter; /// time step // Real time_step; /// conversion coefficient form force/mass to acceleration Real f_m2a; /// displacements array Array<Real> * displacement; UInt displacement_release{0}; /// displacements array at the previous time step (used in finite deformation) Array<Real> * previous_displacement; /// increment of displacement Array<Real> * displacement_increment; /// lumped mass array Array<Real> * mass; /// velocities array Array<Real> * velocity; /// accelerations array Array<Real> * acceleration; /// accelerations array // Array<Real> * increment_acceleration; /// external forces array Array<Real> * external_force; /// internal forces array Array<Real> * internal_force; /// array specifing if a degree of freedom is blocked or not Array<bool> * blocked_dofs; /// array of current position used during update residual Array<Real> * current_position; UInt current_position_release{0}; /// mass matrix SparseMatrix * mass_matrix; /// velocity damping matrix SparseMatrix * velocity_damping_matrix; /// stiffness matrix SparseMatrix * stiffness_matrix; /// jacobian matrix @f[A = cM + dD + K@f] with @f[c = \frac{1}{\beta \Delta /// t^2}, d = \frac{\gamma}{\beta \Delta t} @f] SparseMatrix * jacobian_matrix; /// Arrays containing the material index for each element ElementTypeMapArray<UInt> material_index; /// Arrays containing the position in the element filter of the material /// (material's local numbering) ElementTypeMapArray<UInt> material_local_numbering; #ifdef SWIGPYTHON public: #endif /// list of used materials std::vector<std::unique_ptr<Material>> materials; /// mapping between material name and material internal id std::map<std::string, UInt> materials_names_to_id; #ifdef SWIGPYTHON protected: #endif /// class defining of to choose a material MaterialSelector * material_selector; /// define if it is the default selector or not bool is_default_material_selector; // /// integration scheme of second order used // IntegrationScheme2ndOrder *integrator; /// flag defining if the increment must be computed or not bool increment_flag; /// analysis method check the list in akantu::AnalysisMethod AnalysisMethod method; /// tells if the material are instantiated bool are_materials_instantiated; typedef std::map<std::pair<std::string, ElementKind>, ElementTypeMapArray<Real> *> flatten_internal_map; /// map a registered internals to be flattened for dump purposes flatten_internal_map registered_internals; /// pointer to the pbc synchronizer // PBCSynchronizer * pbc_synch; }; /* -------------------------------------------------------------------------- */ namespace BC { namespace Neumann { typedef FromHigherDim FromStress; typedef FromSameDim FromTraction; } // namespace Neumann } // namespace BC /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const SolidMechanicsModel & _this) { _this.printself(stream); return stream; } } // namespace akantu /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material.hh" #include "parser.hh" #include "solid_mechanics_model_inline_impl.cc" #include "solid_mechanics_model_tmpl.hh" #include "material_selector_tmpl.hh" #endif /* __AKANTU_SOLID_MECHANICS_MODEL_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc index 8755b8866..1ae1e3240 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc @@ -1,780 +1,779 @@ /** * @file solid_mechanics_model_cohesive.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue May 08 2012 * @date last modification: Wed Jan 13 2016 * * @brief Solid mechanics model 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 "solid_mechanics_model_cohesive.hh" #include "dumpable_inline_impl.hh" #include "material_cohesive.hh" #include "shape_cohesive.hh" #include <algorithm> #ifdef AKANTU_USE_IOHELPER #include "dumper_paraview.hh" #endif /* -------------------------------------------------------------------------- */ namespace akantu { const SolidMechanicsModelCohesiveOptions - default_solid_mechanics_model_cohesive_options(_explicit_lumped_mass, false, - false); + default_solid_mechanics_model_cohesive_options(_explicit_lumped_mass, false); /* -------------------------------------------------------------------------- */ SolidMechanicsModelCohesive::SolidMechanicsModelCohesive( Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id) : SolidMechanicsModel(mesh, dim, id, memory_id), tangents("tangents", id), facet_stress("facet_stress", id), facet_material("facet_material", id) { AKANTU_DEBUG_IN(); inserter = NULL; #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) facet_synchronizer = NULL; facet_stress_synchronizer = NULL; cohesive_element_synchronizer = NULL; global_connectivity = NULL; #endif delete material_selector; material_selector = new DefaultMaterialCohesiveSelector(*this); this->registerEventHandler(*this); #if defined(AKANTU_USE_IOHELPER) this->mesh.registerDumper<DumperParaview>("cohesive elements", id); this->mesh.addDumpMeshToDumper("cohesive elements", mesh, Model::spatial_dimension, _not_ghost, _ek_cohesive); #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolidMechanicsModelCohesive::~SolidMechanicsModelCohesive() { AKANTU_DEBUG_IN(); delete inserter; #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) delete cohesive_element_synchronizer; delete facet_synchronizer; delete facet_stress_synchronizer; #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::setTimeStep(Real time_step) { SolidMechanicsModel::setTimeStep(time_step); #if defined(AKANTU_USE_IOHELPER) this->mesh.getDumper("cohesive elements").setTimeStep(time_step); #endif } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initFull(const ModelOptions & options) { AKANTU_DEBUG_IN(); const SolidMechanicsModelCohesiveOptions & smmc_options = dynamic_cast<const SolidMechanicsModelCohesiveOptions &>(options); this->is_extrinsic = smmc_options.extrinsic; if (!inserter) inserter = new CohesiveElementInserter(mesh, is_extrinsic, id + ":cohesive_element_inserter"); SolidMechanicsModel::initFull(options); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initMaterials() { AKANTU_DEBUG_IN(); // make sure the material are instantiated if (!are_materials_instantiated) instantiateMaterials(); /// find the first cohesive material UInt cohesive_index = 0; while ((dynamic_cast<MaterialCohesive *>(materials[cohesive_index].get()) == nullptr) && cohesive_index <= materials.size()) ++cohesive_index; AKANTU_DEBUG_ASSERT(cohesive_index != materials.size(), "No cohesive materials in the material input file"); material_selector->setFallback(cohesive_index); // set the facet information in the material in case of dynamic insertion if (is_extrinsic) { const Mesh & mesh_facets = inserter->getMeshFacets(); facet_material.initialize(mesh_facets, _spatial_dimension = Model::spatial_dimension - 1); // mesh_facets.initElementTypeMapArray(facet_material, 1, // spatial_dimension - 1); Element element; for (auto ghost_type : ghost_types) { element.ghost_type = ghost_type; for (auto & type : mesh_facets.elementTypes(Model::spatial_dimension - 1, ghost_type)) { element.type = type; Array<UInt> & f_material = facet_material(type, ghost_type); UInt nb_element = mesh_facets.getNbElement(type, ghost_type); f_material.resize(nb_element); f_material.set(cohesive_index); for (UInt el = 0; el < nb_element; ++el) { element.element = el; UInt mat_index = (*material_selector)(element); f_material(el) = mat_index; MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(*materials[mat_index]); mat.addFacet(element); } } } SolidMechanicsModel::initMaterials(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_synchronizer != NULL) inserter->initParallel(facet_synchronizer, cohesive_element_synchronizer); // inserter->initParallel(facet_synchronizer, synch_parallel); #endif initAutomaticInsertion(); } else { // TODO think of something a bit mor consistant than just coding the first // thing that comes in Fabian's head.... typedef ParserSection::const_section_iterator const_section_iterator; std::pair<const_section_iterator, const_section_iterator> sub_sections = this->parser->getSubSections(_st_mesh); if (sub_sections.first != sub_sections.second) { std::string cohesive_surfaces = sub_sections.first->getParameter("cohesive_surfaces"); this->initIntrinsicCohesiveMaterials(cohesive_surfaces); } else { this->initIntrinsicCohesiveMaterials(cohesive_index); } } AKANTU_DEBUG_OUT(); } // namespace akantu /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initIntrinsicCohesiveMaterials( std::string cohesive_surfaces) { AKANTU_DEBUG_IN(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_synchronizer != NULL) inserter->initParallel(facet_synchronizer, cohesive_element_synchronizer); // inserter->initParallel(facet_synchronizer, synch_parallel); #endif std::istringstream split(cohesive_surfaces); std::string physname; while (std::getline(split, physname, ',')) { AKANTU_DEBUG_INFO( "Pre-inserting cohesive elements along facets from physical surface: " << physname); insertElementsFromMeshData(physname); } synchronizeInsertionData(); SolidMechanicsModel::initMaterials(); if (is_default_material_selector) delete material_selector; material_selector = new MeshDataMaterialCohesiveSelector(*this); //UInt nb_new_elements = inserter->insertElements(); // if (nb_new_elements > 0) { // this->reinitializeSolver(); // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::synchronizeInsertionData() { #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_synchronizer != NULL) { facet_synchronizer->asynchronousSynchronize(*inserter, _gst_ce_groups); facet_synchronizer->waitEndSynchronize(*inserter, _gst_ce_groups); } #endif } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initIntrinsicCohesiveMaterials( UInt cohesive_index) { AKANTU_DEBUG_IN(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { Mesh::type_iterator first = mesh.firstType(Model::spatial_dimension, *gt, _ek_cohesive); Mesh::type_iterator last = mesh.lastType(Model::spatial_dimension, *gt, _ek_cohesive); for (; first != last; ++first) { Array<UInt> & mat_indexes = this->material_index(*first, *gt); Array<UInt> & mat_loc_num = this->material_local_numbering(*first, *gt); mat_indexes.set(cohesive_index); mat_loc_num.clear(); } } #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_synchronizer != NULL) inserter->initParallel(facet_synchronizer, cohesive_element_synchronizer); // inserter->initParallel(facet_synchronizer, synch_parallel); #endif SolidMechanicsModel::initMaterials(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Initialize the model,basically it pre-compute the shapes, shapes derivatives * and jacobian * */ void SolidMechanicsModelCohesive::initModel() { AKANTU_DEBUG_IN(); SolidMechanicsModel::initModel(); registerFEEngineObject<MyFEEngineCohesiveType>("CohesiveFEEngine", mesh, Model::spatial_dimension); /// add cohesive type connectivity ElementType type = _not_defined; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType type_ghost = *gt; Mesh::type_iterator it = mesh.firstType(Model::spatial_dimension, type_ghost); Mesh::type_iterator last = mesh.lastType(Model::spatial_dimension, type_ghost); for (; it != last; ++it) { const Array<UInt> & connectivity = mesh.getConnectivity(*it, type_ghost); if (connectivity.getSize() != 0) { type = *it; ElementType type_facet = Mesh::getFacetType(type); ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet); mesh.addConnectivityType(type_cohesive, type_ghost); } } } AKANTU_DEBUG_ASSERT(type != _not_defined, "No elements in the mesh"); getFEEngine("CohesiveFEEngine").initShapeFunctions(_not_ghost); getFEEngine("CohesiveFEEngine").initShapeFunctions(_ghost); registerFEEngineObject<MyFEEngineFacetType>( "FacetsFEEngine", mesh.getMeshFacets(), Model::spatial_dimension - 1); if (is_extrinsic) { getFEEngine("FacetsFEEngine").initShapeFunctions(_not_ghost); getFEEngine("FacetsFEEngine").initShapeFunctions(_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::limitInsertion(BC::Axis axis, Real first_limit, Real second_limit) { AKANTU_DEBUG_IN(); inserter->setLimit(axis, first_limit, second_limit); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::insertIntrinsicElements() { AKANTU_DEBUG_IN(); //UInt nb_new_elements = inserter->insertIntrinsicElements(); // if (nb_new_elements > 0) { // this->reinitializeSolver(); // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::insertElementsFromMeshData( std::string physname) { AKANTU_DEBUG_IN(); UInt material_index = SolidMechanicsModel::getMaterialIndex(physname); inserter->insertIntrinsicElements(physname, material_index); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initAutomaticInsertion() { AKANTU_DEBUG_IN(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_stress_synchronizer != NULL) { DataAccessor * data_accessor = this; const ElementTypeMapArray<UInt> & rank_to_element = synch_parallel->getPrankToElement(); facet_stress_synchronizer->updateFacetStressSynchronizer( *inserter, rank_to_element, *data_accessor); } #endif facet_stress.initialize(inserter->getMeshFacets(), _nb_component = 2 * Model::spatial_dimension * Model::spatial_dimension, _spatial_dimension = Model::spatial_dimension - 1); // inserter->getMeshFacets().initElementTypeMapArray( // facet_stress, 2 * spatial_dimension * spatial_dimension, // spatial_dimension - 1); resizeFacetStress(); /// compute normals on facets computeNormals(); initStressInterpolation(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::updateAutomaticInsertion() { AKANTU_DEBUG_IN(); inserter->limitCheckFacets(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_stress_synchronizer != NULL) { DataAccessor * data_accessor = this; const ElementTypeMapArray<UInt> & rank_to_element = synch_parallel->getPrankToElement(); facet_stress_synchronizer->updateFacetStressSynchronizer( *inserter, rank_to_element, *data_accessor); } #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initStressInterpolation() { Mesh & mesh_facets = inserter->getMeshFacets(); /// compute quadrature points coordinates on facets Array<Real> & position = mesh.getNodes(); ElementTypeMapArray<Real> quad_facets("quad_facets", id); quad_facets.initialize(mesh_facets, _nb_component = Model::spatial_dimension, _spatial_dimension = Model::spatial_dimension - 1); // mesh_facets.initElementTypeMapArray(quad_facets, Model::spatial_dimension, // Model::spatial_dimension - 1); getFEEngine("FacetsFEEngine") .interpolateOnIntegrationPoints(position, quad_facets); /// compute elements quadrature point positions and build /// element-facet quadrature points data structure ElementTypeMapArray<Real> elements_quad_facets("elements_quad_facets", id); elements_quad_facets.initialize(mesh, _nb_component = Model::spatial_dimension, _spatial_dimension = Model::spatial_dimension); // mesh.initElementTypeMapArray(elements_quad_facets, Model::spatial_dimension, // Model::spatial_dimension); for (auto elem_gt : ghost_types) { for(auto & type : mesh.elementTypes(Model::spatial_dimension, elem_gt)) { UInt nb_element = mesh.getNbElement(type, elem_gt); if (nb_element == 0) continue; /// compute elements' quadrature points and list of facet /// quadrature points positions by element Array<Element> & facet_to_element = mesh_facets.getSubelementToElement(type, elem_gt); UInt nb_facet_per_elem = facet_to_element.getNbComponent(); Array<Real> & el_q_facet = elements_quad_facets(type, elem_gt); ElementType facet_type = Mesh::getFacetType(type); UInt nb_quad_per_facet = getFEEngine("FacetsFEEngine").getNbIntegrationPoints(facet_type); el_q_facet.resize(nb_element * nb_facet_per_elem * nb_quad_per_facet); for (UInt el = 0; el < nb_element; ++el) { for (UInt f = 0; f < nb_facet_per_elem; ++f) { Element global_facet_elem = facet_to_element(el, f); UInt global_facet = global_facet_elem.element; GhostType facet_gt = global_facet_elem.ghost_type; const Array<Real> & quad_f = quad_facets(facet_type, facet_gt); for (UInt q = 0; q < nb_quad_per_facet; ++q) { for (UInt s = 0; s < Model::spatial_dimension; ++s) { el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, s) = quad_f(global_facet * nb_quad_per_facet + q, s); } } } } } } /// loop over non cohesive materials for (UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat __attribute__((unused)) = dynamic_cast<MaterialCohesive &>(*materials[m]); } catch (std::bad_cast &) { /// initialize the interpolation function materials[m]->initElementalFieldInterpolation(elements_quad_facets); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::assembleInternalForces() { AKANTU_DEBUG_IN(); // f_int += f_int_cohe for (auto & material : this->materials) { try { MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(*material); mat.computeTraction(_not_ghost); } catch (std::bad_cast & bce) { } } SolidMechanicsModel::assembleInternalForces(); if (isDefaultSolverExplicit()) { for (auto & material : materials) { try { MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(*material); mat.computeEnergies(); } catch (std::bad_cast & bce) { } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::computeNormals() { AKANTU_DEBUG_IN(); Mesh & mesh_facets = this->inserter->getMeshFacets(); this->getFEEngine("FacetsFEEngine") .computeNormalsOnIntegrationPoints(_not_ghost); /** * @todo store tangents while computing normals instead of * recomputing them as follows: */ /* ------------------------------------------------------------------------ */ UInt tangent_components = Model::spatial_dimension * (Model::spatial_dimension - 1); tangents.initialize(mesh_facets, _nb_component = tangent_components, _spatial_dimension = Model::spatial_dimension - 1); // mesh_facets.initElementTypeMapArray(tangents, tangent_components, // Model::spatial_dimension - 1); for (auto facet_type : mesh_facets.elementTypes(Model::spatial_dimension - 1)) { const Array<Real> & normals = this->getFEEngine("FacetsFEEngine") .getNormalsOnIntegrationPoints(facet_type); Array<Real> & tangents = this->tangents(facet_type); Math::compute_tangents(normals, tangents); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::interpolateStress() { ElementTypeMapArray<Real> by_elem_result("temporary_stress_by_facets", id); for (auto & material : materials) { try { MaterialCohesive & mat __attribute__((unused)) = dynamic_cast<MaterialCohesive &>(*material); } catch (std::bad_cast &) { /// interpolate stress on facet quadrature points positions material->interpolateStressOnFacets(facet_stress, by_elem_result); } } #if defined(AKANTU_DEBUG_TOOLS) debug::element_manager.printData( debug::_dm_model_cohesive, "Interpolated stresses before", facet_stress); #endif this->synchronize(_gst_smmc_facets_stress); #if defined(AKANTU_DEBUG_TOOLS) debug::element_manager.printData(debug::_dm_model_cohesive, "Interpolated stresses", facet_stress); #endif } /* -------------------------------------------------------------------------- */ UInt SolidMechanicsModelCohesive::checkCohesiveStress() { interpolateStress(); for (auto & mat : materials) { try { MaterialCohesive & mat_cohesive = dynamic_cast<MaterialCohesive &>(*mat); /// check which not ghost cohesive elements are to be created mat_cohesive.checkInsertion(); } catch (std::bad_cast &) { } } /// communicate data among processors this->synchronize(_gst_smmc_facets); /// insert cohesive elements UInt nb_new_elements = inserter->insertElements(); // if (nb_new_elements > 0) { // this->reinitializeSolver(); // } return nb_new_elements; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onElementsAdded( const Array<Element> & element_list, const NewElementsEvent & event) { AKANTU_DEBUG_IN(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) updateCohesiveSynchronizers(); #endif SolidMechanicsModel::onElementsAdded(element_list, event); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (cohesive_element_synchronizer != NULL) cohesive_element_synchronizer->computeAllBufferSizes(*this); #endif /// update shape functions getFEEngine("CohesiveFEEngine").initShapeFunctions(_not_ghost); getFEEngine("CohesiveFEEngine").initShapeFunctions(_ghost); if (is_extrinsic) resizeFacetStress(); /// if (method != _explicit_lumped_mass) { /// this->initSolver(); /// } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onNodesAdded( const Array<UInt> & doubled_nodes, const NewNodesEvent & event) { AKANTU_DEBUG_IN(); UInt nb_new_nodes = doubled_nodes.getSize(); Array<UInt> nodes_list(nb_new_nodes); for (UInt n = 0; n < nb_new_nodes; ++n) nodes_list(n) = doubled_nodes(n, 1); SolidMechanicsModel::onNodesAdded(nodes_list, event); for (UInt n = 0; n < nb_new_nodes; ++n) { UInt old_node = doubled_nodes(n, 0); UInt new_node = doubled_nodes(n, 1); for (UInt dim = 0; dim < Model::spatial_dimension; ++dim) { (*displacement)(new_node, dim) = (*displacement)(old_node, dim); (*velocity)(new_node, dim) = (*velocity)(old_node, dim); (*acceleration)(new_node, dim) = (*acceleration)(old_node, dim); (*blocked_dofs)(new_node, dim) = (*blocked_dofs)(old_node, dim); if (current_position) (*current_position)(new_node, dim) = (*current_position)(old_node, dim); // if (increment_acceleration) // (*increment_acceleration)(new_node, dim) = // (*increment_acceleration)(old_node, dim); // if (increment) // (*increment)(new_node, dim) = (*increment)(old_node, dim); if (previous_displacement) (*previous_displacement)(new_node, dim) = (*previous_displacement)(old_node, dim); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onEndSolveStep(const AnalysisMethod &) { AKANTU_DEBUG_IN(); /* * This is required because the Cauchy stress is the stress measure that * is used to check the insertion of cohesive elements */ for (auto & mat : materials) { if (mat->isFiniteDeformation()) mat->computeAllCauchyStresses(_not_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::printself(std::ostream & stream, int indent) const { std::string space; for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) ; stream << space << "SolidMechanicsModelCohesive [" << std::endl; SolidMechanicsModel::printself(stream, indent + 1); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::resizeFacetStress() { AKANTU_DEBUG_IN(); Mesh & mesh_facets = inserter->getMeshFacets(); 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(Model::spatial_dimension - 1, ghost_type); Mesh::type_iterator end = mesh_facets.lastType(Model::spatial_dimension - 1, ghost_type); for (; it != end; ++it) { ElementType type = *it; UInt nb_facet = mesh_facets.getNbElement(type, ghost_type); UInt nb_quadrature_points = getFEEngine("FacetsFEEngine") .getNbIntegrationPoints(type, ghost_type); UInt new_size = nb_facet * nb_quadrature_points; facet_stress(type, ghost_type).resize(new_size); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::addDumpGroupFieldToDumper( const std::string & dumper_name, const std::string & field_id, const std::string & group_name, const ElementKind & element_kind, bool padding_flag) { AKANTU_DEBUG_IN(); UInt spatial_dimension = Model::spatial_dimension; ElementKind _element_kind = element_kind; if (dumper_name == "cohesive elements") { _element_kind = _ek_cohesive; } else if (dumper_name == "facets") { spatial_dimension = Model::spatial_dimension - 1; } SolidMechanicsModel::addDumpGroupFieldToDumper( dumper_name, field_id, group_name, spatial_dimension, _element_kind, padding_flag); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onDump() { this->flattenAllRegisteredInternals(_ek_cohesive); SolidMechanicsModel::onDump(); } /* -------------------------------------------------------------------------- */ } // namespace akantu diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh index ffde2e79a..dbd59372a 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh @@ -1,296 +1,297 @@ /** * @file solid_mechanics_model_cohesive.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue May 08 2012 * @date last modification: Mon Dec 14 2015 * * @brief Solid mechanics model 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/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ #define __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ #include "cohesive_element_inserter.hh" #include "material_selector_cohesive.hh" #include "solid_mechanics_model.hh" #include "solid_mechanics_model_event_handler.hh" #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) #include "facet_stress_synchronizer.hh" #include "facet_synchronizer.hh" #endif /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ struct FacetsCohesiveIntegrationOrderFunctor { template <ElementType type, ElementType cohesive_type = CohesiveFacetProperty<type>::cohesive_type> struct _helper { static constexpr int get() { return ElementClassProperty<cohesive_type>::polynomial_degree; } }; template <ElementType type> struct _helper<type, _not_defined> { static constexpr int get() { return ElementClassProperty<type>::polynomial_degree; } }; template <ElementType type> static inline constexpr int getOrder() { return _helper<type>::get(); } }; /* -------------------------------------------------------------------------- */ struct SolidMechanicsModelCohesiveOptions : public SolidMechanicsModelOptions { SolidMechanicsModelCohesiveOptions( AnalysisMethod analysis_method = _explicit_lumped_mass, - bool extrinsic = false, bool no_init_materials = false) - : SolidMechanicsModelOptions(analysis_method, no_init_materials), - extrinsic(extrinsic) {} + bool extrinsic = false) + : SolidMechanicsModelOptions(analysis_method), extrinsic(extrinsic) {} template <typename... pack> SolidMechanicsModelCohesiveOptions(use_named_args_t, pack &&... _pack) : SolidMechanicsModelOptions( OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass), - OPTIONAL_NAMED_ARG(is_extrinsic, false), - OPTIONAL_NAMED_ARG(no_init_materials, false)) {} + OPTIONAL_NAMED_ARG(is_extrinsic, false)) {} - bool extrinsic; + bool extrinsic{false}; }; /* -------------------------------------------------------------------------- */ /* Solid Mechanics Model for Cohesive elements */ /* -------------------------------------------------------------------------- */ class SolidMechanicsModelCohesive : public SolidMechanicsModel, public SolidMechanicsModelEventHandler { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: class NewCohesiveNodesEvent : public NewNodesEvent { public: AKANTU_GET_MACRO_NOT_CONST(OldNodesList, old_nodes, Array<UInt> &); AKANTU_GET_MACRO(OldNodesList, old_nodes, const Array<UInt> &); protected: Array<UInt> old_nodes; }; typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive> MyFEEngineCohesiveType; typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular, FacetsCohesiveIntegrationOrderFunctor> MyFEEngineFacetType; SolidMechanicsModelCohesive(Mesh & mesh, UInt spatial_dimension = _all_dimensions, const ID & id = "solid_mechanics_model_cohesive", const MemoryID & memory_id = 0); virtual ~SolidMechanicsModelCohesive(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// set the value of the time step void setTimeStep(Real time_step); /// assemble the residual for the explicit scheme virtual void assembleInternalForces(); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /// function to perform a stress check on each facet and insert /// cohesive elements if needed (returns the number of new cohesive /// elements) UInt checkCohesiveStress(); /// interpolate stress on facets void interpolateStress(); /// initialize the cohesive model - void initFull(const ModelOptions & options = SolidMechanicsModelCohesiveOptions()); + void + initFull(const ModelOptions & options = SolidMechanicsModelCohesiveOptions()); template <typename P, typename T, typename... pack> void initFull(named_argument::param_t<P, T &&> && first, pack &&... _pack) { - this->initFull(SolidMechanicsModelCohesiveOptions{use_named_args, first, _pack...}); + this->initFull( + SolidMechanicsModelCohesiveOptions{use_named_args, first, _pack...}); } /// initialize the model void initModel(); /// initialize cohesive material void initMaterials(); /// init facet filters for cohesive materials void initFacetFilter(); /// limit the cohesive element insertion to a given area void limitInsertion(BC::Axis axis, Real first_limit, Real second_limit); /// update automatic insertion after a change in the element inserter void updateAutomaticInsertion(); /// insert intrinsic cohesive elements void insertIntrinsicElements(); // synchronize facets physical data before insertion along physical surfaces void synchronizeInsertionData(); - // template <SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria> - // bool solveStepCohesive(Real tolerance, Real & error, UInt max_iteration = 100, + // template <SolveConvergenceMethod cmethod, SolveConvergenceCriteria + // criteria> bool solveStepCohesive(Real tolerance, Real & error, UInt + // max_iteration = 100, // bool load_reduction = false, // Real tol_increase_factor = 1.0, // bool do_not_factorize = false); /// initialize stress interpolation void initStressInterpolation(); private: /// initialize cohesive material with intrinsic insertion (by default) void initIntrinsicCohesiveMaterials(UInt cohesive_index); /// initialize cohesive material with intrinsic insertion (if physical /// surfaces are precised) void initIntrinsicCohesiveMaterials(std::string cohesive_surfaces); /// insert cohesive elements along a given physical surface of the mesh void insertElementsFromMeshData(std::string physical_name); /// initialize completely the model for extrinsic elements void initAutomaticInsertion(); /// compute facets' normals void computeNormals(); /// resize facet stress void resizeFacetStress(); /// init facets_check array void initFacetsCheck(); /* ------------------------------------------------------------------------ */ /* Mesh Event Handler inherited members */ /* ------------------------------------------------------------------------ */ protected: virtual void onNodesAdded(const Array<UInt> & nodes_list, const NewNodesEvent & event); virtual void onElementsAdded(const Array<Element> & nodes_list, const NewElementsEvent & event); /* ------------------------------------------------------------------------ */ /* SolidMechanicsModelEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: virtual void onEndSolveStep(const AnalysisMethod & method); /* ------------------------------------------------------------------------ */ /* Dumpable interface */ /* ------------------------------------------------------------------------ */ public: virtual void onDump(); virtual void addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name, const ElementKind & element_kind, bool padding_flag); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get facet mesh AKANTU_GET_MACRO(MeshFacets, mesh.getMeshFacets(), const Mesh &); /// get stress on facets vector AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(StressOnFacets, facet_stress, Real); /// get facet material AKANTU_GET_MACRO_BY_ELEMENT_TYPE(FacetMaterial, facet_material, UInt); /// get facet material AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(FacetMaterial, facet_material, UInt); /// get facet material AKANTU_GET_MACRO(FacetMaterial, facet_material, const ElementTypeMapArray<UInt> &); /// @todo THIS HAS TO BE CHANGED AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Tangents, tangents, Real); /// get element inserter AKANTU_GET_MACRO_NOT_CONST(ElementInserter, *inserter, CohesiveElementInserter &); /// get is_extrinsic boolean AKANTU_GET_MACRO(IsExtrinsic, is_extrinsic, bool); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// @todo store tangents when normals are computed: ElementTypeMapArray<Real> tangents; /// stress on facets on the two sides by quadrature point ElementTypeMapArray<Real> facet_stress; /// material to use if a cohesive element is created on a facet ElementTypeMapArray<UInt> facet_material; bool is_extrinsic; /// cohesive element inserter CohesiveElementInserter * inserter; #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) #include "solid_mechanics_model_cohesive_parallel.hh" #endif }; /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const SolidMechanicsModelCohesive & _this) { _this.printself(stream); return stream; } -} // akantu +} // namespace akantu #include "solid_mechanics_model_cohesive_inline_impl.cc" #endif /* __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc b/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc index beba5e53b..4e25fafbd 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc @@ -1,397 +1,426 @@ /** * @file solid_mechanics_model_inline_impl.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Aug 04 2010 * @date last modification: Wed Nov 18 2015 * - * @brief Implementation of the inline functions of the SolidMechanicsModel class + * @brief Implementation of the inline functions of the SolidMechanicsModel + * 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_named_argument.hh" +#include "material_selector.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLID_MECHANICS_MODEL_INLINE_IMPL_CC__ #define __AKANTU_SOLID_MECHANICS_MODEL_INLINE_IMPL_CC__ namespace akantu { +/* -------------------------------------------------------------------------- */ +inline SolidMechanicsModelOptions::SolidMechanicsModelOptions( + AnalysisMethod analysis_method) + : analysis_method(analysis_method) {} + +/* -------------------------------------------------------------------------- */ +template <typename... pack> +SolidMechanicsModelOptions::SolidMechanicsModelOptions(use_named_args_t, + pack &&... _pack) + : SolidMechanicsModelOptions( + OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass)) {} + /* -------------------------------------------------------------------------- */ inline Material & SolidMechanicsModel::getMaterial(UInt mat_index) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(mat_index < materials.size(), - "The model " << id << " has no material no "<< mat_index); + "The model " << id << " has no material no " + << mat_index); AKANTU_DEBUG_OUT(); return *materials[mat_index]; } /* -------------------------------------------------------------------------- */ inline const Material & SolidMechanicsModel::getMaterial(UInt mat_index) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(mat_index < materials.size(), - "The model " << id << " has no material no "<< mat_index); + "The model " << id << " has no material no " + << mat_index); AKANTU_DEBUG_OUT(); return *materials[mat_index]; } /* -------------------------------------------------------------------------- */ inline Material & SolidMechanicsModel::getMaterial(const std::string & name) { AKANTU_DEBUG_IN(); - std::map<std::string, UInt>::const_iterator it = materials_names_to_id.find(name); + std::map<std::string, UInt>::const_iterator it = + materials_names_to_id.find(name); AKANTU_DEBUG_ASSERT(it != materials_names_to_id.end(), - "The model " << id << " has no material named "<< name); + "The model " << id << " has no material named " << name); AKANTU_DEBUG_OUT(); return *materials[it->second]; } /* -------------------------------------------------------------------------- */ -inline UInt SolidMechanicsModel::getMaterialIndex(const std::string & name) const { +inline UInt +SolidMechanicsModel::getMaterialIndex(const std::string & name) const { AKANTU_DEBUG_IN(); - std::map<std::string, UInt>::const_iterator it = materials_names_to_id.find(name); + std::map<std::string, UInt>::const_iterator it = + materials_names_to_id.find(name); AKANTU_DEBUG_ASSERT(it != materials_names_to_id.end(), - "The model " << id << " has no material named "<< name); + "The model " << id << " has no material named " << name); AKANTU_DEBUG_OUT(); return it->second; } /* -------------------------------------------------------------------------- */ -inline const Material & SolidMechanicsModel::getMaterial(const std::string & name) const { +inline const Material & +SolidMechanicsModel::getMaterial(const std::string & name) const { AKANTU_DEBUG_IN(); - std::map<std::string, UInt>::const_iterator it = materials_names_to_id.find(name); + std::map<std::string, UInt>::const_iterator it = + materials_names_to_id.find(name); AKANTU_DEBUG_ASSERT(it != materials_names_to_id.end(), - "The model " << id << " has no material named "<< name); + "The model " << id << " has no material named " << name); AKANTU_DEBUG_OUT(); return *materials[it->second]; } /* -------------------------------------------------------------------------- */ -inline void SolidMechanicsModel::setMaterialSelector(MaterialSelector & selector) { - if(is_default_material_selector) delete material_selector; +inline void +SolidMechanicsModel::setMaterialSelector(MaterialSelector & selector) { + if (is_default_material_selector) + delete material_selector; material_selector = &selector; is_default_material_selector = false; } /* -------------------------------------------------------------------------- */ inline FEEngine & SolidMechanicsModel::getFEEngineBoundary(const ID & name) { - return dynamic_cast<FEEngine &>(getFEEngineClassBoundary<MyFEEngineType>(name)); + return dynamic_cast<FEEngine &>( + getFEEngineClassBoundary<MyFEEngineType>(name)); } /* -------------------------------------------------------------------------- */ -inline void SolidMechanicsModel::splitElementByMaterial(const Array<Element> & elements, - Array<Element> * elements_per_mat) const { +inline void SolidMechanicsModel::splitElementByMaterial( + const Array<Element> & elements, Array<Element> * elements_per_mat) const { ElementType current_element_type = _not_defined; GhostType current_ghost_type = _casper; const Array<UInt> * mat_indexes = NULL; const Array<UInt> * mat_loc_num = NULL; - Array<Element>::const_iterator<Element> it = elements.begin(); + Array<Element>::const_iterator<Element> it = elements.begin(); Array<Element>::const_iterator<Element> end = elements.end(); for (; it != end; ++it) { Element el = *it; - if(el.type != current_element_type || el.ghost_type != current_ghost_type) { + if (el.type != current_element_type || + el.ghost_type != current_ghost_type) { current_element_type = el.type; - current_ghost_type = el.ghost_type; + current_ghost_type = el.ghost_type; mat_indexes = &(this->material_index(el.type, el.ghost_type)); mat_loc_num = &(this->material_local_numbering(el.type, el.ghost_type)); } UInt old_id = el.element; el.element = (*mat_loc_num)(old_id); elements_per_mat[(*mat_indexes)(old_id)].push_back(el); } } /* -------------------------------------------------------------------------- */ -inline UInt SolidMechanicsModel::getNbData(const Array<Element> & elements, - const SynchronizationTag & tag) const { +inline UInt +SolidMechanicsModel::getNbData(const Array<Element> & elements, + const SynchronizationTag & tag) const { AKANTU_DEBUG_IN(); UInt size = 0; UInt nb_nodes_per_element = 0; - Array<Element>::const_iterator<Element> it = elements.begin(); + Array<Element>::const_iterator<Element> it = elements.begin(); Array<Element>::const_iterator<Element> end = elements.end(); for (; it != end; ++it) { const Element & el = *it; nb_nodes_per_element += Mesh::getNbNodesPerElement(el.type); } - switch(tag) { + switch (tag) { case _gst_material_id: { size += elements.getSize() * sizeof(UInt); break; } case _gst_smm_mass: { - size += nb_nodes_per_element * sizeof(Real) * Model::spatial_dimension; // mass vector + size += nb_nodes_per_element * sizeof(Real) * + Model::spatial_dimension; // mass vector break; } case _gst_smm_for_gradu: { - size += nb_nodes_per_element * Model::spatial_dimension * sizeof(Real); // displacement - break; + size += nb_nodes_per_element * Model::spatial_dimension * + sizeof(Real); // displacement + break; } case _gst_smm_boundary: { // force, displacement, boundary - size += nb_nodes_per_element * Model::spatial_dimension * (2 * sizeof(Real) + sizeof(bool)); + size += nb_nodes_per_element * Model::spatial_dimension * + (2 * sizeof(Real) + sizeof(bool)); break; } case _gst_for_dump: { // displacement, velocity, acceleration, residual, force size += nb_nodes_per_element * Model::spatial_dimension * sizeof(Real) * 5; break; } - default: { } + default: {} } - if(tag != _gst_material_id) { + if (tag != _gst_material_id) { Array<Element> * elements_per_mat = new Array<Element>[materials.size()]; this->splitElementByMaterial(elements, elements_per_mat); for (UInt i = 0; i < materials.size(); ++i) { size += materials[i]->getNbData(elements_per_mat[i], tag); } - delete [] elements_per_mat; + delete[] elements_per_mat; } AKANTU_DEBUG_OUT(); return size; } /* -------------------------------------------------------------------------- */ -inline void SolidMechanicsModel::packData(CommunicationBuffer & buffer, - const Array<Element> & elements, - const SynchronizationTag & tag) const { +inline void +SolidMechanicsModel::packData(CommunicationBuffer & buffer, + const Array<Element> & elements, + const SynchronizationTag & tag) const { AKANTU_DEBUG_IN(); - switch(tag) { + switch (tag) { case _gst_material_id: { - this->packElementalDataHelper(material_index, buffer, elements, false, getFEEngine()); + this->packElementalDataHelper(material_index, buffer, elements, false, + getFEEngine()); break; } case _gst_smm_mass: { packNodalDataHelper(*mass, buffer, elements, mesh); break; } case _gst_smm_for_gradu: { packNodalDataHelper(*displacement, buffer, elements, mesh); break; } case _gst_for_dump: { packNodalDataHelper(*displacement, buffer, elements, mesh); packNodalDataHelper(*velocity, buffer, elements, mesh); packNodalDataHelper(*acceleration, buffer, elements, mesh); packNodalDataHelper(*internal_force, buffer, elements, mesh); packNodalDataHelper(*external_force, buffer, elements, mesh); break; } case _gst_smm_boundary: { packNodalDataHelper(*external_force, buffer, elements, mesh); packNodalDataHelper(*velocity, buffer, elements, mesh); packNodalDataHelper(*blocked_dofs, buffer, elements, mesh); break; } - default: { - } + default: {} } - if(tag != _gst_material_id) { + if (tag != _gst_material_id) { Array<Element> * elements_per_mat = new Array<Element>[materials.size()]; splitElementByMaterial(elements, elements_per_mat); for (UInt i = 0; i < materials.size(); ++i) { materials[i]->packData(buffer, elements_per_mat[i], tag); } - delete [] elements_per_mat; + delete[] elements_per_mat; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::unpackData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) { AKANTU_DEBUG_IN(); - switch(tag) { + switch (tag) { case _gst_material_id: { - unpackElementalDataHelper(material_index, buffer, elements, - false, getFEEngine()); + unpackElementalDataHelper(material_index, buffer, elements, false, + getFEEngine()); break; } case _gst_smm_mass: { unpackNodalDataHelper(*mass, buffer, elements, mesh); break; } case _gst_smm_for_gradu: { unpackNodalDataHelper(*displacement, buffer, elements, mesh); break; } case _gst_for_dump: { unpackNodalDataHelper(*displacement, buffer, elements, mesh); unpackNodalDataHelper(*velocity, buffer, elements, mesh); unpackNodalDataHelper(*acceleration, buffer, elements, mesh); unpackNodalDataHelper(*internal_force, buffer, elements, mesh); unpackNodalDataHelper(*external_force, buffer, elements, mesh); break; } case _gst_smm_boundary: { unpackNodalDataHelper(*external_force, buffer, elements, mesh); unpackNodalDataHelper(*velocity, buffer, elements, mesh); unpackNodalDataHelper(*blocked_dofs, buffer, elements, mesh); break; } - default: { - } + default: {} } - if(tag != _gst_material_id) { + if (tag != _gst_material_id) { Array<Element> * elements_per_mat = new Array<Element>[materials.size()]; splitElementByMaterial(elements, elements_per_mat); for (UInt i = 0; i < materials.size(); ++i) { materials[i]->unpackData(buffer, elements_per_mat[i], tag); } - delete [] elements_per_mat; + delete[] elements_per_mat; } AKANTU_DEBUG_OUT(); } - /* -------------------------------------------------------------------------- */ -inline UInt SolidMechanicsModel::getNbData(const Array<UInt> & dofs, - const SynchronizationTag & tag) const { +inline UInt +SolidMechanicsModel::getNbData(const Array<UInt> & dofs, + const SynchronizationTag & tag) const { AKANTU_DEBUG_IN(); UInt size = 0; // UInt nb_nodes = mesh.getNbNodes(); - switch(tag) { + switch (tag) { case _gst_smm_uv: { size += sizeof(Real) * Model::spatial_dimension * 2; break; } case _gst_smm_res: { size += sizeof(Real) * Model::spatial_dimension; break; } case _gst_smm_mass: { size += sizeof(Real) * Model::spatial_dimension; break; } case _gst_for_dump: { size += sizeof(Real) * Model::spatial_dimension * 5; break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); return size * dofs.getSize(); } - /* -------------------------------------------------------------------------- */ -inline void SolidMechanicsModel::packData(CommunicationBuffer & buffer, - const Array<UInt> & dofs, - const SynchronizationTag & tag) const { +inline void +SolidMechanicsModel::packData(CommunicationBuffer & buffer, + const Array<UInt> & dofs, + const SynchronizationTag & tag) const { AKANTU_DEBUG_IN(); - switch(tag) { + switch (tag) { case _gst_smm_uv: { packDOFDataHelper(*displacement, buffer, dofs); - packDOFDataHelper(*velocity , buffer, dofs); + packDOFDataHelper(*velocity, buffer, dofs); break; } case _gst_smm_res: { packDOFDataHelper(*internal_force, buffer, dofs); break; } case _gst_smm_mass: { packDOFDataHelper(*mass, buffer, dofs); break; } case _gst_for_dump: { - packDOFDataHelper(*displacement , buffer, dofs); - packDOFDataHelper(*velocity , buffer, dofs); - packDOFDataHelper(*acceleration , buffer, dofs); + packDOFDataHelper(*displacement, buffer, dofs); + packDOFDataHelper(*velocity, buffer, dofs); + packDOFDataHelper(*acceleration, buffer, dofs); packDOFDataHelper(*internal_force, buffer, dofs); packDOFDataHelper(*external_force, buffer, dofs); break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::unpackData(CommunicationBuffer & buffer, const Array<UInt> & dofs, const SynchronizationTag & tag) { AKANTU_DEBUG_IN(); - - switch(tag) { + switch (tag) { case _gst_smm_uv: { unpackDOFDataHelper(*displacement, buffer, dofs); - unpackDOFDataHelper(*velocity , buffer, dofs); + unpackDOFDataHelper(*velocity, buffer, dofs); break; } case _gst_smm_res: { unpackDOFDataHelper(*internal_force, buffer, dofs); break; } case _gst_smm_mass: { unpackDOFDataHelper(*mass, buffer, dofs); break; } case _gst_for_dump: { - unpackDOFDataHelper(*displacement , buffer, dofs); - unpackDOFDataHelper(*velocity , buffer, dofs); - unpackDOFDataHelper(*acceleration , buffer, dofs); + unpackDOFDataHelper(*displacement, buffer, dofs); + unpackDOFDataHelper(*velocity, buffer, dofs); + unpackDOFDataHelper(*acceleration, buffer, dofs); unpackDOFDataHelper(*internal_force, buffer, dofs); unpackDOFDataHelper(*external_force, buffer, dofs); break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -} // akantu +} // namespace akantu #endif /* __AKANTU_SOLID_MECHANICS_MODEL_INLINE_IMPL_CC__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_io.cc b/src/model/solid_mechanics/solid_mechanics_model_io.cc new file mode 100644 index 000000000..f1534d53c --- /dev/null +++ b/src/model/solid_mechanics/solid_mechanics_model_io.cc @@ -0,0 +1,329 @@ +/** + * @file solid_mechanics_model_io.cc + * + * @author Nicolas Richart <nicolas.richart@epfl.ch> + * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> + * @author David Simon Kammer <david.kammer@epfl.ch> + * + * @date creation Fri Jul 07 2017 + * + * @brief Dumpable part of the SolidMechnicsModel + * + * @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 "solid_mechanics_model.hh" + +#include "group_manager_inline_impl.cc" + +#include "dumpable_inline_impl.hh" +#ifdef AKANTU_USE_IOHELPER +#include "dumper_element_partition.hh" +#include "dumper_elemental_field.hh" +#include "dumper_field.hh" +#include "dumper_homogenizing_field.hh" +#include "dumper_internal_material_field.hh" +#include "dumper_iohelper.hh" +#include "dumper_material_padders.hh" +#include "dumper_paraview.hh" +#endif + +namespace akantu { + +/* -------------------------------------------------------------------------- */ +bool SolidMechanicsModel::isInternal(const std::string & field_name, + const ElementKind & element_kind) { + /// check if at least one material contains field_id as an internal + for (auto & material : materials) { + bool is_internal = material->isInternal<Real>(field_name, element_kind); + if (is_internal) + return true; + } + + return false; +} + +/* -------------------------------------------------------------------------- */ +ElementTypeMap<UInt> +SolidMechanicsModel::getInternalDataPerElem(const std::string & field_name, + const ElementKind & element_kind) { + + if (!(this->isInternal(field_name, element_kind))) + AKANTU_EXCEPTION("unknown internal " << field_name); + + for (auto & material : materials) { + if (material->isInternal<Real>(field_name, element_kind)) + return material->getInternalDataPerElem<Real>(field_name, element_kind); + } + + return ElementTypeMap<UInt>(); +} + +/* -------------------------------------------------------------------------- */ +ElementTypeMapArray<Real> & +SolidMechanicsModel::flattenInternal(const std::string & field_name, + const ElementKind & kind, + const GhostType ghost_type) { + std::pair<std::string, ElementKind> key(field_name, kind); + if (this->registered_internals.count(key) == 0) { + this->registered_internals[key] = + new ElementTypeMapArray<Real>(field_name, this->id, this->memory_id); + } + + ElementTypeMapArray<Real> * internal_flat = this->registered_internals[key]; + + for (auto type : + mesh.elementTypes(Model::spatial_dimension, ghost_type, kind)) { + if (internal_flat->exists(type, ghost_type)) { + auto & internal = (*internal_flat)(type, ghost_type); + // internal.clear(); + internal.resize(0); + } + } + + for (auto & material : materials) { + if (material->isInternal<Real>(field_name, kind)) + material->flattenInternal(field_name, *internal_flat, ghost_type, kind); + } + + return *internal_flat; +} + +/* -------------------------------------------------------------------------- */ +void SolidMechanicsModel::flattenAllRegisteredInternals( + const ElementKind & kind) { + ElementKind _kind; + ID _id; + + for (auto & internal : this->registered_internals) { + std::tie(_id, _kind) = internal.first; + if (kind == _kind) + this->flattenInternal(_id, kind); + } +} + +/* -------------------------------------------------------------------------- */ +void SolidMechanicsModel::onDump() { + this->flattenAllRegisteredInternals(_ek_regular); +} + +/* -------------------------------------------------------------------------- */ +#ifdef AKANTU_USE_IOHELPER +dumper::Field * SolidMechanicsModel::createElementalField( + const std::string & field_name, const std::string & group_name, + bool padding_flag, const UInt & spatial_dimension, + const ElementKind & kind) { + + dumper::Field * field = nullptr; + + if (field_name == "partitions") + field = mesh.createElementalField<UInt, dumper::ElementPartitionField>( + mesh.getConnectivities(), group_name, spatial_dimension, kind); + else if (field_name == "material_index") + field = mesh.createElementalField<UInt, Vector, dumper::ElementalField>( + material_index, group_name, spatial_dimension, kind); + else { + // this copy of field_name is used to compute derivated data such as + // strain and von mises stress that are based on grad_u and stress + std::string field_name_copy(field_name); + + if (field_name == "strain" || field_name == "Green strain" || + field_name == "principal strain" || + field_name == "principal Green strain") + field_name_copy = "grad_u"; + else if (field_name == "Von Mises stress") + field_name_copy = "stress"; + + bool is_internal = this->isInternal(field_name_copy, kind); + + if (is_internal) { + ElementTypeMap<UInt> nb_data_per_elem = + this->getInternalDataPerElem(field_name_copy, kind); + ElementTypeMapArray<Real> & internal_flat = + this->flattenInternal(field_name_copy, kind); + field = mesh.createElementalField<Real, dumper::InternalMaterialField>( + internal_flat, group_name, spatial_dimension, kind, nb_data_per_elem); + if (field_name == "strain") { + dumper::ComputeStrain<false> * foo = + new dumper::ComputeStrain<false>(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); + } else if (field_name == "Von Mises stress") { + dumper::ComputeVonMisesStress * foo = + new dumper::ComputeVonMisesStress(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); + } else if (field_name == "Green strain") { + dumper::ComputeStrain<true> * foo = + new dumper::ComputeStrain<true>(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); + } else if (field_name == "principal strain") { + dumper::ComputePrincipalStrain<false> * foo = + new dumper::ComputePrincipalStrain<false>(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); + } else if (field_name == "principal Green strain") { + dumper::ComputePrincipalStrain<true> * foo = + new dumper::ComputePrincipalStrain<true>(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); + } + + // treat the paddings + if (padding_flag) { + if (field_name == "stress") { + if (spatial_dimension == 2) { + dumper::StressPadder<2> * foo = new dumper::StressPadder<2>(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); + } + } else if (field_name == "strain" || field_name == "Green strain") { + if (spatial_dimension == 2) { + dumper::StrainPadder<2> * foo = new dumper::StrainPadder<2>(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); + } + } + } + + // homogenize the field + dumper::ComputeFunctorInterface * foo = + dumper::HomogenizerProxy::createHomogenizer(*field); + + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); + } + } + return field; +} + +/* -------------------------------------------------------------------------- */ +dumper::Field * +SolidMechanicsModel::createNodalFieldReal(const std::string & field_name, + const std::string & group_name, + bool padding_flag) { + + std::map<std::string, Array<Real> *> real_nodal_fields; + real_nodal_fields["displacement"] = this->displacement; + real_nodal_fields["mass"] = this->mass; + real_nodal_fields["velocity"] = this->velocity; + real_nodal_fields["acceleration"] = this->acceleration; + real_nodal_fields["external_force"] = this->external_force; + real_nodal_fields["internal_force"] = this->internal_force; + real_nodal_fields["increment"] = this->displacement_increment; + + if (field_name == "force") { + AKANTU_EXCEPTION("The 'force' field has been renamed in 'external_force'"); + } else if (field_name == "residual") { + AKANTU_EXCEPTION( + "The 'residual' field has been replaced by 'internal_force'"); + } + + dumper::Field * field = nullptr; + if (padding_flag) + field = this->mesh.createNodalField(real_nodal_fields[field_name], + group_name, 3); + else + field = + this->mesh.createNodalField(real_nodal_fields[field_name], group_name); + + return field; +} + +/* -------------------------------------------------------------------------- */ +dumper::Field * SolidMechanicsModel::createNodalFieldBool( + const std::string & field_name, const std::string & group_name, + __attribute__((unused)) bool padding_flag) { + + std::map<std::string, Array<bool> *> uint_nodal_fields; + uint_nodal_fields["blocked_dofs"] = blocked_dofs; + + dumper::Field * field = nullptr; + field = mesh.createNodalField(uint_nodal_fields[field_name], group_name); + return field; +} +/* -------------------------------------------------------------------------- */ +#else +/* -------------------------------------------------------------------------- */ +dumper::Field * SolidMechanicsModel::createElementalField(const std::string &, + const std::string &, + bool, const UInt &, + const ElementKind &) { + return nullptr; +} +/* -------------------------------------------------------------------------- + */ +dumper::Field * SolidMechanicsModel::createNodalFieldReal(const std::string &, + const std::string &, + bool) { + return nullptr; +} + +/* -------------------------------------------------------------------------- + */ +dumper::Field * SolidMechanicsModel::createNodalFieldBool(const std::string &, + const std::string &, + bool) { + return nullptr; +} + +#endif +/* -------------------------------------------------------------------------- + */ +void SolidMechanicsModel::dump(const std::string & dumper_name) { + this->onDump(); + EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); + mesh.dump(dumper_name); +} + +/* -------------------------------------------------------------------------- + */ +void SolidMechanicsModel::dump(const std::string & dumper_name, UInt step) { + this->onDump(); + EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); + mesh.dump(dumper_name, step); +} + +/* ------------------------------------------------------------------------- + */ +void SolidMechanicsModel::dump(const std::string & dumper_name, Real time, + UInt step) { + this->onDump(); + EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); + mesh.dump(dumper_name, time, step); +} + +/* -------------------------------------------------------------------------- */ +void SolidMechanicsModel::dump() { + this->onDump(); + EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); + mesh.dump(); +} + +/* -------------------------------------------------------------------------- */ +void SolidMechanicsModel::dump(UInt step) { + this->onDump(); + EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); + mesh.dump(step); +} + +/* -------------------------------------------------------------------------- */ +void SolidMechanicsModel::dump(Real time, UInt step) { + this->onDump(); + EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); + mesh.dump(time, step); +} + +} // namespace akantu diff --git a/src/model/solid_mechanics/solid_mechanics_model_material.cc b/src/model/solid_mechanics/solid_mechanics_model_material.cc index fde420a9c..211e8f560 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_material.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_material.cc @@ -1,334 +1,315 @@ /** * @file solid_mechanics_model_material.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Nov 26 2010 * @date last modification: Mon Nov 16 2015 * * @brief instatiation of materials * * @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_factory.hh" #include "aka_math.hh" -#include "material_list.hh" +//#include "material_list.hh" #include "solid_mechanics_model.hh" #ifdef AKANTU_DAMAGE_NON_LOCAL #include "non_local_manager.hh" #endif /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ -#define AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL(dim, elem) \ - registerNewMaterial<BOOST_PP_ARRAY_ELEM(1, elem) < dim>> (section) - -#define AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL_EACH(r, data, i, elem) \ - BOOST_PP_EXPR_IF(BOOST_PP_NOT_EQUAL(0, i), else) \ - if (opt_param == BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, elem))) { \ - registerNewMaterial<BOOST_PP_ARRAY_ELEM(1, data) < \ - BOOST_PP_ARRAY_ELEM(0, data), \ - BOOST_PP_SEQ_ENUM(BOOST_PP_TUPLE_ELEM(2, 1, elem))>> \ - (section); \ +Material & +SolidMechanicsModel::registerNewMaterial(const ParserSection & section) { + std::string mat_name; + std::string mat_type = section.getName(); + std::string opt_param = section.getOption(); + + try { + std::string tmp = section.getParameter("name"); + mat_name = tmp; /** this can seam weird, but there is an ambiguous operator + * overload that i couldn't solve. @todo remove the + * weirdness of this code + */ + } catch (debug::Exception &) { + AKANTU_DEBUG_ERROR( + "A material of type \'" + << mat_type << "\' in the input file has been defined without a name!"); } + Material & mat = this->registerNewMaterial(mat_name, mat_type, opt_param); -#define AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL(dim, elem) \ - BOOST_PP_SEQ_FOR_EACH_I(AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL_EACH, \ - (2, (dim, BOOST_PP_ARRAY_ELEM(1, elem))), \ - BOOST_PP_ARRAY_ELEM(2, elem)) \ - else { \ - AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL(dim, elem); \ - } + mat.parseSection(section); -#define AKANTU_INTANTIATE_MATERIAL_BY_DIM(dim, elem) \ - BOOST_PP_IF(BOOST_PP_EQUAL(3, BOOST_PP_ARRAY_SIZE(elem)), \ - AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL, \ - AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL) \ - (dim, elem) - -#define AKANTU_INTANTIATE_MATERIAL(elem) \ - switch (Model::spatial_dimension) { \ - case 1: { \ - AKANTU_INTANTIATE_MATERIAL_BY_DIM(1, elem); \ - break; \ - } \ - case 2: { \ - AKANTU_INTANTIATE_MATERIAL_BY_DIM(2, elem); \ - break; \ - } \ - case 3: { \ - AKANTU_INTANTIATE_MATERIAL_BY_DIM(3, elem); \ - break; \ - } \ - } + return mat; +} -#define AKANTU_INTANTIATE_MATERIAL_IF(elem) \ - if (mat_type == BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(0, elem))) { \ - AKANTU_INTANTIATE_MATERIAL(elem); \ - } +/* -------------------------------------------------------------------------- */ +Material & SolidMechanicsModel::registerNewMaterial(const ID & mat_name, + const ID & mat_type, + const ID & opt_param) { + AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_name) == + materials_names_to_id.end(), + "A material with this name '" + << mat_name << "' has already been registered. " + << "Please use unique names for materials"); -#define AKANTU_INTANTIATE_OTHER_MATERIAL(r, data, elem) \ - else AKANTU_INTANTIATE_MATERIAL_IF(elem) - -#define AKANTU_INSTANTIATE_MATERIALS() \ - do { \ - AKANTU_INTANTIATE_MATERIAL_IF(BOOST_PP_SEQ_HEAD(AKANTU_MATERIAL_LIST)) \ - BOOST_PP_SEQ_FOR_EACH(AKANTU_INTANTIATE_OTHER_MATERIAL, _, \ - BOOST_PP_SEQ_TAIL(AKANTU_MATERIAL_LIST)) \ - else { \ - if (getStaticParser().isPermissive()) \ - AKANTU_DEBUG_INFO("Malformed material file " \ - << ": unknown material type '" << mat_type << "'"); \ - else \ - AKANTU_DEBUG_WARNING("Malformed material file " \ - << ": unknown material type " << mat_type \ - << ". This is perhaps a user" \ - << " defined material ?"); \ - } \ - } while (0) + UInt mat_count = materials.size(); + materials_names_to_id[mat_name] = mat_count; + + std::stringstream sstr_mat; + sstr_mat << this->id << ":" << mat_count << ":" << mat_type; + ID mat_id = sstr_mat.str(); + + std::unique_ptr<Material> material = MaterialFactory::getInstance().allocate( + mat_type, Model::spatial_dimension, opt_param, *this, mat_id); + + materials.push_back(std::move(material)); + + return *(materials.back()); +} /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::instantiateMaterials() { std::pair<Parser::const_section_iterator, Parser::const_section_iterator> sub_sect = this->parser->getSubSections(_st_material); Parser::const_section_iterator it = sub_sect.first; for (; it != sub_sect.second; ++it) { const ParserSection & section = *it; - std::string mat_type = section.getName(); - std::string opt_param = section.getOption(); - AKANTU_INSTANTIATE_MATERIALS(); + registerNewMaterial(section); } are_materials_instantiated = true; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assignMaterialToElements( const ElementTypeMapArray<UInt> * filter) { Element element; element.ghost_type = _not_ghost; auto element_types = mesh.elementTypes(Model::spatial_dimension, _not_ghost, _ek_not_defined); if (filter != NULL) { element_types = filter->elementTypes(Model::spatial_dimension, _not_ghost, _ek_not_defined); } // Fill the element material array from the material selector for (auto type : element_types) { UInt nb_element = mesh.getNbElement(type, _not_ghost); const Array<UInt> * filter_array = NULL; if (filter != NULL) { filter_array = &((*filter)(type, _not_ghost)); nb_element = filter_array->getSize(); } element.type = type; element.kind = mesh.getKind(element.type); Array<UInt> & mat_indexes = material_index(type, _not_ghost); for (UInt el = 0; el < nb_element; ++el) { if (filter != NULL) element.element = (*filter_array)(el); else element.element = el; UInt mat_index = (*material_selector)(element); AKANTU_DEBUG_ASSERT( mat_index < materials.size(), "The material selector returned an index that does not exists"); mat_indexes(element.element) = mat_index; } } // synchronize the element material arrays this->synchronize(_gst_material_id); /// fill the element filters of the materials using the element_material /// arrays for (auto ghost_type : ghost_types) { element_types = mesh.elementTypes(Model::spatial_dimension, ghost_type, _ek_not_defined); if (filter != NULL) { element_types = filter->elementTypes(Model::spatial_dimension, ghost_type, _ek_not_defined); } for (auto type : element_types) { UInt nb_element = mesh.getNbElement(type, ghost_type); const Array<UInt> * filter_array = NULL; if (filter != NULL) { filter_array = &((*filter)(type, ghost_type)); nb_element = filter_array->getSize(); } Array<UInt> & mat_indexes = material_index(type, ghost_type); Array<UInt> & mat_local_num = material_local_numbering(type, ghost_type); for (UInt el = 0; el < nb_element; ++el) { UInt element; if (filter != NULL) element = (*filter_array)(el); else element = el; UInt mat_index = mat_indexes(element); UInt index = materials[mat_index]->addElement(type, element, ghost_type); mat_local_num(element) = index; } } } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initMaterials() { AKANTU_DEBUG_ASSERT(materials.size() != 0, "No material to initialize !"); if (!are_materials_instantiated) instantiateMaterials(); this->assignMaterialToElements(); for (auto & material : materials) { /// init internals properties material->initMaterial(); } this->synchronize(_gst_smm_init_mat); // initialize mass switch (method) { case _explicit_lumped_mass: assembleMassLumped(); break; case _explicit_consistent_mass: case _implicit_dynamic: assembleMass(); break; case _static: break; default: AKANTU_EXCEPTION("analysis method not recognised by SolidMechanicsModel"); break; } // initialize the previous displacement array if at least on material needs it // for (auto & material : materials) { // if (material->isFiniteDeformation() || material->isInelasticDeformation()) // { // initArraysPreviousDisplacment(); // break; // } // } #ifdef AKANTU_DAMAGE_NON_LOCAL /// initialize the non-local manager for non-local computations this->initializeNonLocal(); #endif } /* -------------------------------------------------------------------------- */ Int SolidMechanicsModel::getInternalIndexFromID(const ID & id) const { AKANTU_DEBUG_IN(); auto it = materials.begin(); auto end = materials.end(); for (; it != end; ++it) if ((*it)->getID() == id) { AKANTU_DEBUG_OUT(); return (it - materials.begin()); } AKANTU_DEBUG_OUT(); return -1; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::reassignMaterial() { AKANTU_DEBUG_IN(); std::vector<Array<Element>> element_to_add(materials.size()); std::vector<Array<Element>> element_to_remove(materials.size()); Element element; for (auto ghost_type : ghost_types) { element.ghost_type = ghost_type; for (auto type : mesh.elementTypes(Model::spatial_dimension, ghost_type, _ek_not_defined)) { element.type = type; element.kind = Mesh::getKind(type); UInt nb_element = mesh.getNbElement(type, ghost_type); Array<UInt> & mat_indexes = material_index(type, ghost_type); for (UInt el = 0; el < nb_element; ++el) { element.element = el; UInt old_material = mat_indexes(el); UInt new_material = (*material_selector)(element); if (old_material != new_material) { element_to_add[new_material].push_back(element); element_to_remove[old_material].push_back(element); } } } } UInt mat_index = 0; for (auto mat_it = materials.begin(); mat_it != materials.end(); ++mat_it, ++mat_index) { (*mat_it)->removeElements(element_to_remove[mat_index]); (*mat_it)->addElements(element_to_add[mat_index]); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::applyEigenGradU( const Matrix<Real> & prescribed_eigen_grad_u, const ID & material_name, const GhostType ghost_type) { AKANTU_DEBUG_ASSERT(prescribed_eigen_grad_u.size() == Model::spatial_dimension * Model::spatial_dimension, "The prescribed grad_u is not of the good size"); for (auto & material : materials) { if (material->getName() == material_name) material->applyEigenGradU(prescribed_eigen_grad_u, ghost_type); } } /* -------------------------------------------------------------------------- */ -} // akantu +} // namespace akantu diff --git a/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh b/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh index 96dc5bcc9..adfd3d86a 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh +++ b/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh @@ -1,120 +1,120 @@ /** * @file solid_mechanics_model_tmpl.hh * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Dana Christen <dana.christen@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Nov 13 2015 * * @brief template part of 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" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLID_MECHANICS_MODEL_TMPL_HH__ #define __AKANTU_SOLID_MECHANICS_MODEL_TMPL_HH__ namespace akantu { /* -------------------------------------------------------------------------- */ -template <typename M> -Material & -SolidMechanicsModel::registerNewMaterial(const ParserSection & section) { - std::string mat_name; - std::string mat_type = section.getName(); - try { - std::string tmp = section.getParameter("name"); - mat_name = tmp; /** this can seam weird, but there is an ambiguous operator - * overload that i couldn't solve. @todo remove the - * weirdness of this code - */ - } catch (debug::Exception &) { - AKANTU_DEBUG_ERROR( - "A material of type \'" - << mat_type << "\' in the input file has been defined without a name!"); - } - AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_name) == - materials_names_to_id.end(), - "A material with this name '" - << mat_name << "' has already been registered. " - << "Please use unique names for materials"); - - UInt mat_count = materials.size(); - materials_names_to_id[mat_name] = mat_count; - - std::stringstream sstr_mat; - sstr_mat << this->id << ":" << mat_count << ":" << mat_type; - ID mat_id = sstr_mat.str(); - - std::unique_ptr<Material> material(new M(*this, mat_id)); - material->parseSection(section); - - materials.push_back(std::move(material)); - - return *(materials.back()); -} +// template <typename M> +// Material & +// SolidMechanicsModel::registerNewMaterial(const ParserSection & section) { +// std::string mat_name; +// std::string mat_type = section.getName(); +// try { +// std::string tmp = section.getParameter("name"); +// mat_name = tmp; /** this can seam weird, but there is an ambiguous operator +// * overload that i couldn't solve. @todo remove the +// * weirdness of this code +// */ +// } catch (debug::Exception &) { +// AKANTU_DEBUG_ERROR( +// "A material of type \'" +// << mat_type << "\' in the input file has been defined without a name!"); +// } +// AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_name) == +// materials_names_to_id.end(), +// "A material with this name '" +// << mat_name << "' has already been registered. " +// << "Please use unique names for materials"); + +// UInt mat_count = materials.size(); +// materials_names_to_id[mat_name] = mat_count; + +// std::stringstream sstr_mat; +// sstr_mat << this->id << ":" << mat_count << ":" << mat_type; +// ID mat_id = sstr_mat.str(); + +// std::unique_ptr<Material> material(new M(*this, mat_id)); +// material->parseSection(section); + +// materials.push_back(std::move(material)); + +// return *(materials.back()); +// } /* -------------------------------------------------------------------------- */ -template <typename M> -Material & -SolidMechanicsModel::registerNewEmptyMaterial(const std::string & mat_name) { +// template <typename M> +// Material & +// SolidMechanicsModel::registerNewEmptyMaterial(const std::string & mat_name) { - AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_name) == - materials_names_to_id.end(), - "A material with this name '" - << mat_name << "' has already been registered. " - << "Please use unique names for materials"); +// AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_name) == +// materials_names_to_id.end(), +// "A material with this name '" +// << mat_name << "' has already been registered. " +// << "Please use unique names for materials"); - UInt mat_count = materials.size(); - materials_names_to_id[mat_name] = mat_count; +// UInt mat_count = materials.size(); +// materials_names_to_id[mat_name] = mat_count; - std::stringstream sstr_mat; - sstr_mat << id << ":" << mat_count << ":" << mat_name; - ID mat_id = sstr_mat.str(); +// std::stringstream sstr_mat; +// sstr_mat << id << ":" << mat_count << ":" << mat_name; +// ID mat_id = sstr_mat.str(); - std::unique_ptr<Material> material(new M(*this, mat_id)); - materials.push_back(std::move(material)); - return *(materials.back()); -} +// std::unique_ptr<Material> material(new M(*this, mat_id)); +// materials.push_back(std::move(material)); +// return *(materials.back()); +// } /* -------------------------------------------------------------------------- */ -template <typename M> -void SolidMechanicsModel::registerNewCustomMaterials(const ID & mat_type) { - std::pair<Parser::const_section_iterator, Parser::const_section_iterator> - sub_sect = getStaticParser().getSubSections(_st_material); - - Parser::const_section_iterator it = sub_sect.first; - for (; it != sub_sect.second; ++it) { - if (it->getName() == mat_type) { - registerNewMaterial<M>(*it); - } - } -} +// template <typename M> +// void SolidMechanicsModel::registerNewCustomMaterials(const ID & mat_type) { +// std::pair<Parser::const_section_iterator, Parser::const_section_iterator> +// sub_sect = getStaticParser().getSubSections(_st_material); + +// Parser::const_section_iterator it = sub_sect.first; +// for (; it != sub_sect.second; ++it) { +// if (it->getName() == mat_type) { +// registerNewMaterial<M>(*it); +// } +// } +// } /* -------------------------------------------------------------------------- */ } // akantu #endif /* __AKANTU_SOLID_MECHANICS_MODEL_TMPL_HH__ */ diff --git a/test/test_io/test_parser/test_parser.cc b/test/test_io/test_parser/test_parser.cc index d847058b9..8bede7ca3 100644 --- a/test/test_io/test_parser/test_parser.cc +++ b/test/test_io/test_parser/test_parser.cc @@ -1,76 +1,76 @@ /** * @file test_parser.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Sun Oct 19 2014 * * @brief test the input file parser * * @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 "parser.hh" #include "aka_random_generator.hh" #include <iostream> using namespace akantu; int main(int argc, char *argv[]) { initialize("input_file.dat", argc, argv); const Parser & p = getStaticParser(); - std::cout << RandGenerator<Real>::seed() <<"==123456" << std::endl; + std::cout << RandomGenerator<UInt>::seed() <<"==123456" << std::endl; std::cout << p << std::endl; Real toto = p.getParameter("toto"); std::cout << toto; Real ref = 2*M_PI + std::max(2., 50.); if(std::abs(toto - ref) > std::numeric_limits<Real>::epsilon()) { std::cout << "!=" << ref << std::endl; return 1; } std::cout << "==" << ref << std::endl; Vector<Real> vect = p.getParameter("vect"); std::cout << vect << std::endl; Matrix<Real> mat = p.getParameter("mat"); std::cout << mat << std::endl; RandomParameter<Real> rand1 = p.getParameter("rand1"); std::cout << rand1 << std::endl; RandomParameter<Real> rand2 = p.getParameter("rand2"); std::cout << rand2 << std::endl; RandomParameter<Real> rand3 = p.getParameter("rand3"); std::cout << rand3 << std::endl; finalize(); return 0; } diff --git a/test/test_model/test_model_solver/test_model_solver.cc b/test/test_model/test_model_solver/test_model_solver.cc index f0d9a3f81..f8702519e 100644 --- a/test/test_model/test_model_solver/test_model_solver.cc +++ b/test/test_model/test_model_solver/test_model_solver.cc @@ -1,155 +1,155 @@ /** * @file test_dof_manager_default.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date Wed Feb 24 12:28:44 2016 * * @brief Test default dof manager * * @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_random_generator.hh" #include "dof_manager.hh" #include "dof_synchronizer.hh" #include "mesh.hh" #include "mesh_accessor.hh" #include "model_solver.hh" #include "non_linear_solver_newton_raphson.hh" #include "sparse_matrix.hh" #include "sparse_solver_mumps.hh" /* -------------------------------------------------------------------------- */ #include "test_model_solver_my_model.hh" /* -------------------------------------------------------------------------- */ #include <cmath> /* -------------------------------------------------------------------------- */ using namespace akantu; static void genMesh(Mesh & mesh, UInt nb_nodes); static void printResults(MyModel & model, UInt nb_nodes); Real F = -10; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize(argc, argv); UInt prank = StaticCommunicator::getStaticCommunicator().whoAmI(); std::cout << std::setprecision(7); UInt global_nb_nodes = 100; Mesh mesh(1); - RandGenerator<Real>::seed(1); + RandomGenerator<UInt>::seed(1); if (prank == 0) { genMesh(mesh, global_nb_nodes); } //std::cout << prank << RandGenerator<Real>::seed() << std::endl; mesh.distribute(); MyModel model(F, mesh, false); model.getNewSolver("static", _tsst_static, _nls_newton_raphson); model.setIntegrationScheme("static", "disp", _ist_pseudo_time); NonLinearSolver & solver = model.getDOFManager().getNonLinearSolver("static"); solver.set("max_iterations", 2); model.solveStep(); dynamic_cast<NonLinearSolverNewtonRaphson &>( model.getDOFManager().getNonLinearSolver("static")) .getSolver() .analysis(); printResults(model, global_nb_nodes); finalize(); return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ void genMesh(Mesh & mesh, UInt nb_nodes) { MeshAccessor mesh_accessor(mesh); Array<Real> & nodes = mesh_accessor.getNodes(); Array<UInt> & conn = mesh_accessor.getConnectivity(_segment_2); nodes.resize(nb_nodes); for (UInt n = 0; n < nb_nodes; ++n) { nodes(n, _x) = n * (1. / (nb_nodes - 1)); } conn.resize(nb_nodes - 1); for (UInt n = 0; n < nb_nodes - 1; ++n) { conn(n, 0) = n; conn(n, 1) = n + 1; } } /* -------------------------------------------------------------------------- */ void printResults(MyModel & model, UInt nb_nodes) { UInt prank = StaticCommunicator::getStaticCommunicator().whoAmI(); auto & sync = dynamic_cast<DOFManagerDefault &>(model.getDOFManager()) .getSynchronizer(); if (prank == 0) { Array<Real> global_displacement(nb_nodes); Array<Real> global_forces(nb_nodes); Array<bool> global_blocked(nb_nodes); sync.gather(model.forces, global_forces); sync.gather(model.displacement, global_displacement); sync.gather(model.blocked, global_blocked); auto force_it = global_forces.begin(); auto disp_it = global_displacement.begin(); auto blocked_it = global_blocked.begin(); std::cout << "node" << ", " << std::setw(8) << "disp" << ", " << std::setw(8) << "force" << ", " << std::setw(8) << "blocked" << std::endl; UInt node = 0; for (; disp_it != global_displacement.end(); ++disp_it, ++force_it, ++blocked_it, ++node) { std::cout << node << ", " << std::setw(8) << *disp_it << ", " << std::setw(8) << *force_it << ", " << std::setw(8) << *blocked_it << std::endl; std::cout << std::flush; } } else { sync.gather(model.forces); sync.gather(model.displacement); sync.gather(model.blocked); } } diff --git a/test/test_model/test_non_local_toolbox/test_build_neighborhood_parallel.cc b/test/test_model/test_non_local_toolbox/test_build_neighborhood_parallel.cc index 08d0d5e54..08cb77e51 100644 --- a/test/test_model/test_non_local_toolbox/test_build_neighborhood_parallel.cc +++ b/test/test_model/test_non_local_toolbox/test_build_neighborhood_parallel.cc @@ -1,188 +1,195 @@ /** * @file test_build_neighborhood_parallel.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Wed Nov 25 2015 * * @brief test in parallel for the class NonLocalNeighborhood * * @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 "dumper_paraview.hh" +#include "non_local_neighborhood_base.hh" #include "solid_mechanics_model.hh" #include "test_material.hh" -#include "non_local_neighborhood_base.hh" -#include "dumper_paraview.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ -int main(int argc, char *argv[]) { +int main(int argc, char * argv[]) { akantu::initialize("material_parallel_test.dat", argc, argv); - StaticCommunicator & comm = akantu::StaticCommunicator::getStaticCommunicator(); + StaticCommunicator & comm = + akantu::StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); // some configuration variables const UInt spatial_dimension = 2; // mesh creation and read Mesh mesh(spatial_dimension); - akantu::MeshPartition * partition = NULL; - if(prank == 0) { - + if (prank == 0) { mesh.read("parallel_test.msh"); - - - /// partition the mesh - partition = new MeshPartitionScotch(mesh, spatial_dimension); - - partition->partitionate(psize); } - /// model creation - SolidMechanicsModel model(mesh); - model.initParallel(partition); - delete partition; + mesh.distribute(); + /// model creation + SolidMechanicsModel model(mesh); /// dump the ghost elements before the non-local part is intialized DumperParaview dumper_ghost("ghost_elements"); dumper_ghost.registerMesh(mesh, spatial_dimension, _ghost); - if(psize > 1) { + if (psize > 1) { dumper_ghost.dump(); } /// creation of material selector MeshDataMaterialSelector<std::string> * mat_selector; - mat_selector = new MeshDataMaterialSelector<std::string>("physical_names", model); + mat_selector = + new MeshDataMaterialSelector<std::string>("physical_names", model); model.setMaterialSelector(*mat_selector); /// dump material index in paraview model.addDumpField("partitions"); model.dump(); /// model initialization changed to use our material - model.initFull(_no_init_materials = true); - - model.registerNewCustomMaterials< TestMaterial<spatial_dimension> >("test_material"); - model.initMaterials(); + model.initFull(); + /// dump the ghost elements after ghosts for non-local have been added - if(psize > 1) + if (psize > 1) dumper_ghost.dump(); model.addDumpField("grad_u"); model.addDumpField("grad_u non local"); model.addDumpField("material_index"); - /// apply constant strain field everywhere in the plate + /// apply constant strain field everywhere in the plate Matrix<Real> applied_strain(spatial_dimension, spatial_dimension); applied_strain.clear(); for (UInt i = 0; i < spatial_dimension; ++i) - applied_strain(i,i) = 2.; + applied_strain(i, i) = 2.; ElementType element_type = _triangle_3; GhostType ghost_type = _not_ghost; /// apply constant grad_u field in all elements for (UInt m = 0; m < model.getNbMaterials(); ++m) { Material & mat = model.getMaterial(m); - Array<Real> & grad_u = const_cast<Array<Real> &> (mat.getInternal<Real>("grad_u")(element_type, ghost_type)); - Array<Real>::iterator< Matrix<Real> > grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension); - Array<Real>::iterator< Matrix<Real> > grad_u_end = grad_u.end(spatial_dimension, spatial_dimension); - for (; grad_u_it != grad_u_end; ++grad_u_it) + Array<Real> & grad_u = const_cast<Array<Real> &>( + mat.getInternal<Real>("grad_u")(element_type, ghost_type)); + Array<Real>::iterator<Matrix<Real>> grad_u_it = + grad_u.begin(spatial_dimension, spatial_dimension); + Array<Real>::iterator<Matrix<Real>> grad_u_end = + grad_u.end(spatial_dimension, spatial_dimension); + for (; grad_u_it != grad_u_end; ++grad_u_it) (*grad_u_it) += applied_strain; } - /// double the strain in the center: find the closed gauss point to the center + /// double the strain in the center: find the closed gauss point to the center /// compute the quadrature points ElementTypeMapReal quad_coords("quad_coords"); - mesh.initElementTypeMapArray(quad_coords, spatial_dimension, spatial_dimension, false, _ek_regular, true); + quad_coords.initialize(mesh, _nb_component = spatial_dimension, + _spatial_dimension = spatial_dimension, _with_nb_element = true); model.getFEEngine().computeIntegrationPointsCoordinates(quad_coords); Vector<Real> center(spatial_dimension, 0.); - Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost, _ek_regular); - Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _not_ghost, _ek_regular); + Mesh::type_iterator it = + mesh.firstType(spatial_dimension, _not_ghost, _ek_regular); + Mesh::type_iterator last_type = + mesh.lastType(spatial_dimension, _not_ghost, _ek_regular); Real min_distance = 2; IntegrationPoint q_min; - for(; it != last_type ; ++it) { + for (; it != last_type; ++it) { ElementType type = *it; UInt nb_elements = mesh.getNbElement(type, _not_ghost); UInt nb_quads = model.getFEEngine().getNbIntegrationPoints(type); Array<Real> & coords = quad_coords(type, _not_ghost); - Array<Real>::const_vector_iterator coord_it = coords.begin(spatial_dimension); + Array<Real>::const_vector_iterator coord_it = + coords.begin(spatial_dimension); for (UInt e = 0; e < nb_elements; ++e) { for (UInt q = 0; q < nb_quads; ++q, ++coord_it) { - Real dist = center.distance(*coord_it); - if (dist < min_distance) { - min_distance = dist; - q_min.element = e; - q_min.num_point = q; - q_min.global_num = nb_elements * nb_quads + q; - q_min.type = type; - } + Real dist = center.distance(*coord_it); + if (dist < min_distance) { + min_distance = dist; + q_min.element = e; + q_min.num_point = q; + q_min.global_num = nb_elements * nb_quads + q; + q_min.type = type; + } } } } Real global_min = min_distance; - comm.allReduce(&global_min, 1, _so_min); + comm.allReduce(global_min, _so_min); - if(Math::are_float_equal(global_min, min_distance)) { - UInt mat_index = model.getMaterialByElement(q_min.type, _not_ghost).begin()[q_min.element]; + if (Math::are_float_equal(global_min, min_distance)) { + UInt mat_index = model.getMaterialByElement(q_min.type, _not_ghost) + .begin()[q_min.element]; Material & mat = model.getMaterial(mat_index); UInt nb_quads = model.getFEEngine().getNbIntegrationPoints(q_min.type); - UInt local_el_index = model.getMaterialLocalNumbering(q_min.type, _not_ghost).begin()[q_min.element]; + UInt local_el_index = + model.getMaterialLocalNumbering(q_min.type, _not_ghost) + .begin()[q_min.element]; UInt local_num = (local_el_index * nb_quads) + q_min.num_point; - Array<Real> & grad_u = const_cast<Array<Real> &> (mat.getInternal<Real>("grad_u")(q_min.type, _not_ghost)); - Array<Real>::iterator< Matrix<Real> > grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension); + Array<Real> & grad_u = const_cast<Array<Real> &>( + mat.getInternal<Real>("grad_u")(q_min.type, _not_ghost)); + Array<Real>::iterator<Matrix<Real>> grad_u_it = + grad_u.begin(spatial_dimension, spatial_dimension); grad_u_it += local_num; Matrix<Real> & g_u = *grad_u_it; - g_u += applied_strain; + g_u += applied_strain; } /// compute the non-local strains - model.getNonLocalManager().computeAllNonLocalStresses(); - model.dump(); + model.assembleInternalForces(); + model.dump(); /// damage the element with higher grad_u completely, so that it is /// not taken into account for the averaging - if(Math::are_float_equal(global_min, min_distance)) { - UInt mat_index = model.getMaterialByElement(q_min.type, _not_ghost).begin()[q_min.element]; + if (Math::are_float_equal(global_min, min_distance)) { + UInt mat_index = model.getMaterialByElement(q_min.type, _not_ghost) + .begin()[q_min.element]; Material & mat = model.getMaterial(mat_index); UInt nb_quads = model.getFEEngine().getNbIntegrationPoints(q_min.type); - UInt local_el_index = model.getMaterialLocalNumbering(q_min.type, _not_ghost).begin()[q_min.element]; + UInt local_el_index = + model.getMaterialLocalNumbering(q_min.type, _not_ghost) + .begin()[q_min.element]; UInt local_num = (local_el_index * nb_quads) + q_min.num_point; - Array<Real> & damage = const_cast<Array<Real> &> (mat.getInternal<Real>("damage")(q_min.type, _not_ghost)); + Array<Real> & damage = const_cast<Array<Real> &>( + mat.getInternal<Real>("damage")(q_min.type, _not_ghost)); Real * dam_ptr = damage.storage(); dam_ptr += local_num; *dam_ptr = 0.9; } /// compute the non-local strains - model.getNonLocalManager().computeAllNonLocalStresses(); - model.dump(); + model.assembleInternalForces(); + model.dump(); finalize(); - + return EXIT_SUCCESS; } diff --git a/test/test_model/test_non_local_toolbox/test_material.cc b/test/test_model/test_non_local_toolbox/test_material.cc index df021a8a2..2e3b88433 100644 --- a/test/test_model/test_non_local_toolbox/test_material.cc +++ b/test/test_model/test_non_local_toolbox/test_material.cc @@ -1,125 +1,61 @@ /** * @file test_material.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Wed Nov 25 2015 * - * @brief Implementation of test material for the non-local neighborhood base test + * @brief Implementation of test material for the non-local neighborhood base + * test * * @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 "test_material.hh" -__BEGIN_AKANTU__ - /* -------------------------------------------------------------------------- */ -template<UInt dim> -TestMaterial<dim>::TestMaterial(SolidMechanicsModel & model, const ID & id) : - Material(model, id), - MyLocalParent(model, id), - MyNonLocalParent(model, id), - grad_u_nl("grad_u non local", *this) { +template <UInt dim> +TestMaterial<dim>::TestMaterial(SolidMechanicsModel & model, const ID & id) + : Parent(model, id), grad_u_nl("grad_u non local", *this) { this->is_non_local = true; - this->grad_u_nl.initialize(dim*dim); - this->model->getNonLocalManager().registerNonLocalVariable(this->gradu.getName(), grad_u_nl.getName(), dim*dim); - - } + this->grad_u_nl.initialize(dim * dim); + this->model.registerNonLocalVariable( + this->gradu.getName(), grad_u_nl.getName(), dim * dim); +} /* -------------------------------------------------------------------------- */ -template<UInt spatial_dimension> +template <UInt spatial_dimension> void TestMaterial<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); - this->registerNeighborhood(); - - MyLocalParent::initMaterial(); - MyNonLocalParent::initMaterial(); + Parent::initMaterial(); - this->model->getNonLocalManager().nonLocalVariableToNeighborhood(grad_u_nl.getName(), "test_region"); + this->model.getNeighborhood("test_region") + .registerNonLocalVariable(grad_u_nl.getName()); AKANTU_DEBUG_OUT(); } -/* -------------------------------------------------------------------------- */ -template<UInt spatial_dimension> -void TestMaterial<spatial_dimension>::insertQuadsInNeighborhoods(GhostType ghost_type) { - - /// this function will add all the quadrature points to the same - /// default neighborhood instead of using one neighborhood per - /// material - NonLocalManager & manager = this->model->getNonLocalManager(); - InternalField<Real> quadrature_points_coordinates("quadrature_points_coordinates_tmp_nl", *this); - quadrature_points_coordinates.initialize(spatial_dimension); - - /// intialize quadrature point object - IntegrationPoint q; - q.ghost_type = ghost_type; - q.kind = _ek_regular; - - Mesh::type_iterator it = this->element_filter.firstType(spatial_dimension, ghost_type, _ek_regular); - Mesh::type_iterator last_type = this->element_filter.lastType(spatial_dimension, ghost_type, _ek_regular); - for(; it != last_type; ++it) { - q.type = *it; - const Array<UInt> & elem_filter = this->element_filter(*it, ghost_type); - UInt nb_element = elem_filter.getSize(); - if(nb_element) { - UInt nb_quad = this->fem->getNbIntegrationPoints(*it, ghost_type); - UInt nb_tot_quad = nb_quad * nb_element; - - Array<Real> & quads = quadrature_points_coordinates(*it, ghost_type); - quads.resize(nb_tot_quad); - - this->model->getFEEngine().computeIntegrationPointsCoordinates(quads, *it, ghost_type, elem_filter); - - Array<Real>::const_vector_iterator quad = quads.begin(spatial_dimension); - UInt * elem = elem_filter.storage(); - - for (UInt e = 0; e < nb_element; ++e) { - q.element = *elem; - for (UInt nq = 0; nq < nb_quad; ++nq) { - q.num_point = nq; - q.global_num = q.element * nb_quad + nq; - manager.insertQuad(q, *quad, "test_region"); - ++quad; - } - ++elem; - } - } - } -} - -/* -------------------------------------------------------------------------- */ -template<UInt spatial_dimension> -void TestMaterial<spatial_dimension>::registerNeighborhood() { - this->model->getNonLocalManager().registerNeighborhood("test_region", "test_region"); -} - /* -------------------------------------------------------------------------- */ // Instantiate the material for the 3 dimensions -INSTANTIATE_MATERIAL(TestMaterial); +INSTANTIATE_MATERIAL(test_material, TestMaterial); /* -------------------------------------------------------------------------- */ - -__END_AKANTU__ - - diff --git a/test/test_model/test_non_local_toolbox/test_material.hh b/test/test_model/test_non_local_toolbox/test_material.hh index e0c262d4f..a1cdd484a 100644 --- a/test/test_model/test_non_local_toolbox/test_material.hh +++ b/test/test_model/test_non_local_toolbox/test_material.hh @@ -1,72 +1,70 @@ /** * @file test_material.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Wed Nov 25 2015 * * @brief test material for the non-local neighborhood base test * * @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 "material_damage.hh" #include "material_damage_non_local.hh" #ifndef __TEST_MATERIAL_HH__ #define __TEST_MATERIAL_HH__ -namespace akantu { +using namespace akantu; template <UInt dim> -class TestMaterial : public MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>> { +class TestMaterial + : public MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>> { /* ------------------------------------------------------------------------ */ /* Constructor/Destructor */ /* ------------------------------------------------------------------------ */ public: - using Parent = MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>>; + using Parent = + MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>>; TestMaterial(SolidMechanicsModel & model, const ID & id); virtual ~TestMaterial(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: - void initMaterial(); + void initMaterial() final; - void computeNonLocalStresses(GhostType){}; + void computeNonLocalStress(ElementType, GhostType) final{}; - void insertQuadsInNeighborhoods(GhostType ghost_type); - - virtual void registerNeighborhood(); + void computeNonLocalStresses(GhostType) final{}; /* ------------------------------------------------------------------------ */ /* Members */ /* ------------------------------------------------------------------------ */ private: InternalField<Real> grad_u_nl; }; -} // namespace akantu - #endif /* __TEST_MATERIAL_HH__ */ diff --git a/test/test_model/test_non_local_toolbox/test_material_damage.cc b/test/test_model/test_non_local_toolbox/test_material_damage.cc index b61c974c8..89c7cfdd9 100644 --- a/test/test_model/test_non_local_toolbox/test_material_damage.cc +++ b/test/test_model/test_non_local_toolbox/test_material_damage.cc @@ -1,116 +1,60 @@ /** * @file test_material_damage.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Thu Oct 15 2015 * * @brief Implementation of test material damage * * @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 "test_material_damage.hh" - -__BEGIN_AKANTU__ +/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -template<UInt dim> -TestMaterialDamage<dim>::TestMaterialDamage(SolidMechanicsModel & model, const ID & id) : - Material(model, id), - MaterialDamage<dim>(model, id), - MyNonLocalParent(model, id), - grad_u_nl("grad_u non local", *this) { +template <UInt dim> +TestMaterialDamage<dim>::TestMaterialDamage(SolidMechanicsModel & model, + const ID & id) + : Parent(model, id), grad_u_nl("grad_u non local", *this) { this->is_non_local = true; - this->grad_u_nl.initialize(dim*dim); - this->model->getNonLocalManager().registerNonLocalVariable(this->gradu.getName(), grad_u_nl.getName(), dim*dim); - - } + this->grad_u_nl.initialize(dim * dim); + this->model.registerNonLocalVariable(this->gradu.getName(), + grad_u_nl.getName(), dim * dim); +} /* -------------------------------------------------------------------------- */ -template<UInt spatial_dimension> +template <UInt spatial_dimension> void TestMaterialDamage<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialDamage<spatial_dimension>::initMaterial(); - MyNonLocalParent::initMaterial(); - this->model->getNonLocalManager().nonLocalVariableToNeighborhood(grad_u_nl.getName(), this->name); + Parent::initMaterial(); + this->model.getNeighborhood(this->name) + .registerNonLocalVariable(grad_u_nl.getName()); AKANTU_DEBUG_OUT(); } -/* -------------------------------------------------------------------------- */ -template<UInt spatial_dimension> -void TestMaterialDamage<spatial_dimension>::insertQuadsInNeighborhoods(GhostType ghost_type) { - - /// this function will add all the quadrature points to the same - /// default neighborhood instead of using one neighborhood per - /// material - NonLocalManager & manager = this->model->getNonLocalManager(); - InternalField<Real> quadrature_points_coordinates("quadrature_points_coordinates_tmp_nl", *this); - quadrature_points_coordinates.initialize(spatial_dimension); - - /// intialize quadrature point object - IntegrationPoint q; - q.ghost_type = ghost_type; - q.kind = _ek_regular; - - Mesh::type_iterator it = this->element_filter.firstType(spatial_dimension, ghost_type, _ek_regular); - Mesh::type_iterator last_type = this->element_filter.lastType(spatial_dimension, ghost_type, _ek_regular); - for(; it != last_type; ++it) { - q.type = *it; - const Array<UInt> & elem_filter = this->element_filter(*it, ghost_type); - UInt nb_element = elem_filter.getSize(); - if(nb_element) { - UInt nb_quad = this->fem->getNbIntegrationPoints(*it, ghost_type); - UInt nb_tot_quad = nb_quad * nb_element; - - Array<Real> & quads = quadrature_points_coordinates(*it, ghost_type); - quads.resize(nb_tot_quad); - - this->model->getFEEngine().computeIntegrationPointsCoordinates(quads, *it, ghost_type, elem_filter); - - Array<Real>::const_vector_iterator quad = quads.begin(spatial_dimension); - UInt * elem = elem_filter.storage(); - - for (UInt e = 0; e < nb_element; ++e) { - q.element = *elem; - for (UInt nq = 0; nq < nb_quad; ++nq) { - q.num_point = nq; - q.global_num = q.element * nb_quad + nq; - manager.insertQuad(q, *quad, this->name); - ++quad; - } - ++elem; - } - } - } -} - - /* -------------------------------------------------------------------------- */ // Instantiate the material for the 3 dimensions -INSTANTIATE_MATERIAL(TestMaterialDamage); +INSTANTIATE_MATERIAL(test_material, TestMaterialDamage); /* -------------------------------------------------------------------------- */ - -__END_AKANTU__ - - diff --git a/test/test_model/test_non_local_toolbox/test_material_damage.hh b/test/test_model/test_non_local_toolbox/test_material_damage.hh index 01d51bdf3..9afe91fc1 100644 --- a/test/test_model/test_non_local_toolbox/test_material_damage.hh +++ b/test/test_model/test_non_local_toolbox/test_material_damage.hh @@ -1,72 +1,70 @@ /** * @file test_material_damage.hh * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * * @date creation: Thu Feb 21 2013 * @date last modification: Thu Oct 15 2015 * * @brief test material damage for the non-local remove damage test * * @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 "material_damage.hh" -#include "material_non_local.hh" +#include "material_damage_non_local.hh" +/* -------------------------------------------------------------------------- */ #ifndef __TEST_MATERIAL_DAMAGE_HH__ #define __TEST_MATERIAL_DAMAGE_HH__ -__BEGIN_AKANTU__ +using namespace akantu; template <UInt dim> -class TestMaterialDamage : public MaterialDamage<dim, MaterialElastic>, - public MaterialNonLocal<dim> { +class TestMaterialDamage + : public MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>> { /* ------------------------------------------------------------------------ */ /* Constructor/Destructor */ /* ------------------------------------------------------------------------ */ public: TestMaterialDamage(SolidMechanicsModel & model, const ID & id); virtual ~TestMaterialDamage(){}; - typedef MaterialNonLocal<dim> MyNonLocalParent; + using Parent = MaterialDamageNonLocal<dim, MaterialDamage<dim, MaterialElastic>>; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); - // void computeNonLocalStress(ElementType type, GhostType ghost_type = - // _not_ghost); + void computeNonLocalStress(ElementType, GhostType) final{}; - void computeNonLocalStresses(__attribute__((unused)) GhostType ghost_type){}; + void computeNonLocalStresses(GhostType) final{}; void insertQuadsInNeighborhoods(GhostType ghost_type); /* ------------------------------------------------------------------------ */ /* Members */ /* ------------------------------------------------------------------------ */ private: InternalField<Real> grad_u_nl; }; -__END_AKANTU__ - #endif /* __TEST_MATERIAL_DAMAGE_HH__ */ diff --git a/test/test_model/test_non_local_toolbox/test_non_local_averaging.cc b/test/test_model/test_non_local_toolbox/test_non_local_averaging.cc index 5e8094186..36e5c6647 100644 --- a/test/test_model/test_non_local_toolbox/test_non_local_averaging.cc +++ b/test/test_model/test_non_local_toolbox/test_non_local_averaging.cc @@ -1,112 +1,111 @@ /** * @file test_non_local_averaging.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Wed Oct 07 2015 * * @brief test for non-local averaging of strain * * @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 "solid_mechanics_model.hh" #include "test_material.hh" #include "non_local_manager.hh" #include "non_local_neighborhood.hh" #include "dumper_paraview.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::initialize("material.dat", argc, argv); // some configuration variables const UInt spatial_dimension = 2; ElementType element_type = _quadrangle_4; GhostType ghost_type = _not_ghost; // mesh creation and read Mesh mesh(spatial_dimension); mesh.read("plate.msh"); /// model creation SolidMechanicsModel model(mesh); /// creation of material selector MeshDataMaterialSelector<std::string> * mat_selector; mat_selector = new MeshDataMaterialSelector<std::string>("physical_names", model); model.setMaterialSelector(*mat_selector); /// model initialization changed to use our material - model.initFull(_no_init_materials = true); - model.registerNewCustomMaterials< TestMaterial<spatial_dimension> >("test_material"); - model.initMaterials(); + model.initFull(); + /// dump material index in paraview model.addDumpField("material_index"); model.addDumpField("grad_u"); model.addDumpField("grad_u non local"); model.dump(); /// apply constant strain field everywhere in the plate Matrix<Real> applied_strain(spatial_dimension, spatial_dimension); applied_strain.clear(); for (UInt i = 0; i < spatial_dimension; ++i) applied_strain(i,i) = 2.; /// apply constant grad_u field in all elements for (UInt m = 0; m < model.getNbMaterials(); ++m) { Material & mat = model.getMaterial(m); Array<Real> & grad_u = const_cast<Array<Real> &> (mat.getInternal<Real>("grad_u")(element_type, ghost_type)); Array<Real>::iterator< Matrix<Real> > grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension); Array<Real>::iterator< Matrix<Real> > grad_u_end = grad_u.end(spatial_dimension, spatial_dimension); for (; grad_u_it != grad_u_end; ++grad_u_it) (*grad_u_it) += applied_strain; } /// compute the non-local strains - model.getNonLocalManager().computeAllNonLocalStresses(); + model.assembleInternalForces(); model.dump(); /// verify the result: non-local averaging over constant field must /// yield same constant field Real test_result = 0.; Matrix<Real> difference(spatial_dimension, spatial_dimension, 0.); for (UInt m = 0; m < model.getNbMaterials(); ++m) { - MaterialNonLocal<spatial_dimension> & mat = dynamic_cast<MaterialNonLocal<spatial_dimension> & >(model.getMaterial(m)); - Array<Real> & grad_u_nl = const_cast<Array<Real> &> (mat.getInternal<Real>("grad_u non local")(element_type, ghost_type)); + auto & mat = model.getMaterial(m); + Array<Real> & grad_u_nl = mat.getInternal<Real>("grad_u non local")(element_type, ghost_type); - Array<Real>::iterator< Matrix<Real> > grad_u_nl_it = grad_u_nl.begin(spatial_dimension, spatial_dimension); - Array<Real>::iterator< Matrix<Real> > grad_u_nl_end = grad_u_nl.end(spatial_dimension, spatial_dimension); + auto grad_u_nl_it = grad_u_nl.begin(spatial_dimension, spatial_dimension); + auto grad_u_nl_end = grad_u_nl.end(spatial_dimension, spatial_dimension); for (; grad_u_nl_it != grad_u_nl_end; ++grad_u_nl_it) { difference = (*grad_u_nl_it) - applied_strain; test_result += difference.norm<L_2>(); } } if (test_result > 10.e-13) { std::cout << "the total norm is: " << test_result << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; } diff --git a/test/test_model/test_non_local_toolbox/test_non_local_neighborhood_base.cc b/test/test_model/test_non_local_toolbox/test_non_local_neighborhood_base.cc index d307b9366..2fadd32a3 100644 --- a/test/test_model/test_non_local_toolbox/test_non_local_neighborhood_base.cc +++ b/test/test_model/test_non_local_toolbox/test_non_local_neighborhood_base.cc @@ -1,89 +1,88 @@ /** * @file test_non_local_neighborhood_base.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Wed Oct 07 2015 * * @brief test for the class NonLocalNeighborhoodBase * * @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 "solid_mechanics_model.hh" #include "test_material.hh" #include "non_local_neighborhood_base.hh" #include "dumper_paraview.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::initialize("material.dat", argc, argv); // some configuration variables const UInt spatial_dimension = 2; // mesh creation and read Mesh mesh(spatial_dimension); mesh.read("plate.msh"); /// model creation SolidMechanicsModel model(mesh); /// creation of material selector MeshDataMaterialSelector<std::string> * mat_selector; mat_selector = new MeshDataMaterialSelector<std::string>("physical_names", model); model.setMaterialSelector(*mat_selector); /// model initialization changed to use our material - model.initFull(_no_init_materials = true); - model.registerNewCustomMaterials< TestMaterial<spatial_dimension> >("test_material"); - model.initMaterials(); + model.initFull(); + /// dump material index in paraview model.addDumpField("material_index"); model.dump(); NonLocalNeighborhoodBase & neighborhood = model.getNeighborhood("test_region"); /// save the pair of quadrature points and the coords of all neighbors std::string output_1 = "quadrature_pairs"; std::string output_2 = "neighborhoods"; neighborhood.savePairs(output_1); neighborhood.saveNeighborCoords(output_2); /// print results to screen for validation std::ifstream quad_pairs; quad_pairs.open("quadrature_pairs.0"); std::string current_line; while(getline(quad_pairs, current_line)) std::cout << current_line << std::endl; quad_pairs.close(); std::ifstream neighborhoods; neighborhoods.open("neighborhoods.0"); while(getline(neighborhoods, current_line)) std::cout << current_line << std::endl; neighborhoods.close(); finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_non_local_toolbox/test_pair_computation.cc b/test/test_model/test_non_local_toolbox/test_pair_computation.cc index 5d463925b..26d98969d 100644 --- a/test/test_model/test_non_local_toolbox/test_pair_computation.cc +++ b/test/test_model/test_non_local_toolbox/test_pair_computation.cc @@ -1,243 +1,233 @@ /** * @file test_pair_computation.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * * @date creation: Wed Nov 25 2015 * * @brief test the weight computation with and without grid * * @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 "dumper_paraview.hh" #include "non_local_manager.hh" #include "non_local_neighborhood.hh" #include "solid_mechanics_model.hh" #include "test_material_damage.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; -typedef std::vector<std::pair<IntegrationPoint, IntegrationPoint> > PairList; +typedef std::vector<std::pair<IntegrationPoint, IntegrationPoint>> PairList; /* -------------------------------------------------------------------------- */ void computePairs(SolidMechanicsModel & model, PairList * pair_list); int main(int argc, char * argv[]) { akantu::initialize("material_remove_damage.dat", argc, argv); // some configuration variables const UInt spatial_dimension = 2; StaticCommunicator & comm = - akantu::StaticCommunicator::getStaticCommunicator(); - Int psize = comm.getNbProc(); + akantu::StaticCommunicator::getStaticCommunicator(); Int prank = comm.whoAmI(); // mesh creation and read Mesh mesh(spatial_dimension); - akantu::MeshPartition * partition = NULL; if (prank == 0) { mesh.read("pair_test.msh"); - /// partition the mesh - partition = new MeshPartitionScotch(mesh, spatial_dimension); - partition->partitionate(psize); } + mesh.distribute(); /// model creation SolidMechanicsModel model(mesh); - model.initParallel(partition); - delete partition; /// creation of material selector MeshDataMaterialSelector<std::string> * mat_selector; mat_selector = new MeshDataMaterialSelector<std::string>("physical_names", model); model.setMaterialSelector(*mat_selector); /// model initialization changed to use our material - model.initFull(_no_init_materials = true); - model.registerNewCustomMaterials<TestMaterialDamage<spatial_dimension> >( - "test_material"); - model.initMaterials(); + model.initFull(); + /// dump material index in paraview model.addDumpField("material_index"); model.dump(); /// compute the pairs by looping over all the quadrature points PairList pair_list[2]; computePairs(model, pair_list); - NonLocalManager & manager = model.getNonLocalManager(); - const PairList * pairs_mat_1 = - manager.getNeighborhood("mat_1").getPairLists(); - const PairList * pairs_mat_2 = - manager.getNeighborhood("mat_2").getPairLists(); + const PairList * pairs_mat_1 = model.getNeighborhood("mat_1").getPairLists(); + const PairList * pairs_mat_2 = model.getNeighborhood("mat_2").getPairLists(); /// compare the number of pairs UInt nb_not_ghost_pairs_grid = pairs_mat_1[0].size() + pairs_mat_2[0].size(); UInt nb_ghost_pairs_grid = pairs_mat_1[1].size() + pairs_mat_2[1].size(); UInt nb_not_ghost_pairs_no_grid = pair_list[0].size(); UInt nb_ghost_pairs_no_grid = pair_list[1].size(); if ((nb_not_ghost_pairs_grid != nb_not_ghost_pairs_no_grid) || (nb_ghost_pairs_grid != nb_ghost_pairs_no_grid)) { std::cout << "The number of pairs is not correct: TEST FAILED!!!" << std::endl; finalize(); return EXIT_FAILURE; } for (UInt i = 0; i < pairs_mat_1[0].size(); ++i) { std::pair<IntegrationPoint, IntegrationPoint> p = (pairs_mat_1[0])[i]; PairList::const_iterator it = std::find( pair_list[0].begin(), pair_list[0].end(), (pairs_mat_1[0])[i]); if (it == pair_list[0].end()) { std::cout << "The pairs are not correct" << std::endl; finalize(); return EXIT_FAILURE; } } for (UInt i = 0; i < pairs_mat_2[0].size(); ++i) { std::pair<IntegrationPoint, IntegrationPoint> p = (pairs_mat_2[0])[i]; PairList::const_iterator it = std::find( pair_list[0].begin(), pair_list[0].end(), (pairs_mat_2[0])[i]); if (it == pair_list[0].end()) { std::cout << "The pairs are not correct" << std::endl; finalize(); return EXIT_FAILURE; } } for (UInt i = 0; i < pairs_mat_1[1].size(); ++i) { std::pair<IntegrationPoint, IntegrationPoint> p = (pairs_mat_1[1])[i]; PairList::const_iterator it = std::find( pair_list[1].begin(), pair_list[1].end(), (pairs_mat_1[1])[i]); if (it == pair_list[1].end()) { std::cout << "The pairs are not correct" << std::endl; finalize(); return EXIT_FAILURE; } } for (UInt i = 0; i < pairs_mat_2[1].size(); ++i) { std::pair<IntegrationPoint, IntegrationPoint> p = (pairs_mat_2[1])[i]; PairList::const_iterator it = std::find( pair_list[1].begin(), pair_list[1].end(), (pairs_mat_2[1])[i]); if (it == pair_list[1].end()) { std::cout << "The pairs are not correct" << std::endl; finalize(); return EXIT_FAILURE; } } finalize(); return 0; } /* -------------------------------------------------------------------------- */ void computePairs(SolidMechanicsModel & model, PairList * pair_list) { ElementKind kind = _ek_regular; Mesh & mesh = model.getMesh(); UInt spatial_dimension = model.getSpatialDimension(); /// compute the quadrature points ElementTypeMapReal quad_coords("quad_coords"); - mesh.initElementTypeMapArray(quad_coords, spatial_dimension, - spatial_dimension, false, _ek_regular, true); + quad_coords.initialize(mesh, _nb_component = spatial_dimension, + _spatial_dimension = spatial_dimension, + _with_nb_element = true); model.getFEEngine().computeIntegrationPointsCoordinates(quad_coords); /// loop in a n^2 way over all the quads to generate the pairs Real neighborhood_radius = 0.5; Mesh::type_iterator it_1 = mesh.firstType(spatial_dimension, _not_ghost, kind); Mesh::type_iterator last_type_1 = mesh.lastType(spatial_dimension, _not_ghost, kind); IntegrationPoint q1; IntegrationPoint q2; q1.kind = kind; q2.kind = kind; GhostType ghost_type_1 = _not_ghost; q1.ghost_type = ghost_type_1; Vector<Real> q1_coords(spatial_dimension); Vector<Real> q2_coords(spatial_dimension); for (; it_1 != last_type_1; ++it_1) { ElementType type_1 = *it_1; q1.type = type_1; UInt nb_elements_1 = mesh.getNbElement(type_1, ghost_type_1); UInt nb_quads_1 = model.getFEEngine().getNbIntegrationPoints(type_1); Array<Real> & quad_coords_1 = quad_coords(q1.type, q1.ghost_type); Array<Real>::const_vector_iterator coord_it_1 = quad_coords_1.begin(spatial_dimension); for (UInt e_1 = 0; e_1 < nb_elements_1; ++e_1) { q1.element = e_1; UInt mat_index_1 = model.getMaterialByElement(q1.type, q1.ghost_type) .begin()[q1.element]; for (UInt q_1 = 0; q_1 < nb_quads_1; ++q_1) { q1.global_num = nb_quads_1 * e_1 + q_1; q1.num_point = q_1; q1_coords = coord_it_1[q1.global_num]; /// loop over all other quads and create pairs for this given quad for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type_2 = *gt; q2.ghost_type = ghost_type_2; Mesh::type_iterator it_2 = mesh.firstType(spatial_dimension, ghost_type_2, kind); Mesh::type_iterator last_type_2 = mesh.lastType(spatial_dimension, ghost_type_2, kind); for (; it_2 != last_type_2; ++it_2) { ElementType type_2 = *it_2; q2.type = type_2; UInt nb_elements_2 = mesh.getNbElement(type_2, ghost_type_2); UInt nb_quads_2 = model.getFEEngine().getNbIntegrationPoints(type_2); Array<Real> & quad_coords_2 = quad_coords(q2.type, q2.ghost_type); Array<Real>::const_vector_iterator coord_it_2 = quad_coords_2.begin(spatial_dimension); for (UInt e_2 = 0; e_2 < nb_elements_2; ++e_2) { q2.element = e_2; UInt mat_index_2 = model.getMaterialByElement(q2.type, q2.ghost_type) .begin()[q2.element]; for (UInt q_2 = 0; q_2 < nb_quads_2; ++q_2) { q2.global_num = nb_quads_2 * e_2 + q_2; q2.num_point = q_2; q2_coords = coord_it_2[q2.global_num]; Real distance = q1_coords.distance(q2_coords); if (mat_index_1 != mat_index_2) continue; else if (distance <= neighborhood_radius + Math::getTolerance() && (q2.ghost_type == _ghost || (q2.ghost_type == _not_ghost && q1.global_num <= q2.global_num))) { // storing only half lists pair_list[q2.ghost_type].push_back(std::make_pair(q1, q2)); } } } } } } } } } diff --git a/test/test_model/test_non_local_toolbox/test_remove_damage_weight_function.cc b/test/test_model/test_non_local_toolbox/test_remove_damage_weight_function.cc index fe070b933..961d9a9fa 100644 --- a/test/test_model/test_non_local_toolbox/test_remove_damage_weight_function.cc +++ b/test/test_model/test_non_local_toolbox/test_remove_damage_weight_function.cc @@ -1,202 +1,198 @@ /** * @file test_remove_damage_weight_function.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * * @date creation: Wed Oct 07 2015 * * @brief Test the damage weight funcion for non local computations * * @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 "dumper_paraview.hh" #include "non_local_manager.hh" #include "non_local_neighborhood.hh" #include "solid_mechanics_model.hh" #include "test_material_damage.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { akantu::initialize("material_remove_damage.dat", argc, argv); // some configuration variables const UInt spatial_dimension = 2; ElementType element_type = _quadrangle_4; GhostType ghost_type = _not_ghost; // mesh creation and read Mesh mesh(spatial_dimension); mesh.read("plate.msh"); /// model creation SolidMechanicsModel model(mesh); /// creation of material selector MeshDataMaterialSelector<std::string> * mat_selector; mat_selector = new MeshDataMaterialSelector<std::string>("physical_names", model); model.setMaterialSelector(*mat_selector); /// model initialization changed to use our material - model.initFull(_no_init_materials = true); - model.registerNewCustomMaterials<TestMaterialDamage<spatial_dimension> >( - "test_material"); - model.initMaterials(); + model.initFull(); /// dump material index in paraview model.addDumpField("material_index"); model.addDumpField("grad_u"); model.addDumpField("grad_u non local"); model.addDumpField("damage"); model.dump(); /// apply constant strain field in all elements except element 3 and 15 Matrix<Real> applied_strain(spatial_dimension, spatial_dimension); applied_strain.clear(); for (UInt i = 0; i < spatial_dimension; ++i) applied_strain(i, i) = 2.; /// apply different strain in element 3 and 15 Matrix<Real> modified_strain(spatial_dimension, spatial_dimension); modified_strain.clear(); for (UInt i = 0; i < spatial_dimension; ++i) modified_strain(i, i) = 1.; /// apply constant grad_u field in all elements for (UInt m = 0; m < model.getNbMaterials(); ++m) { Material & mat = model.getMaterial(m); Array<Real> & grad_u = const_cast<Array<Real> &>( mat.getInternal<Real>("grad_u")(element_type, ghost_type)); Array<Real>::iterator<Matrix<Real> > grad_u_it = grad_u.begin(spatial_dimension, spatial_dimension); Array<Real>::iterator<Matrix<Real> > grad_u_end = grad_u.end(spatial_dimension, spatial_dimension); UInt element_counter = 0; for (; grad_u_it != grad_u_end; ++grad_u_it, ++element_counter) if (element_counter == 12 || element_counter == 13 || element_counter == 14 || element_counter == 15) (*grad_u_it) += modified_strain; else (*grad_u_it) += applied_strain; } /// compute the non-local strains - model.getNonLocalManager().computeAllNonLocalStresses(); + model.assembleInternalForces(); model.dump(); /// save the weights in a file NonLocalNeighborhood<RemoveDamagedWeightFunction> & neighborhood_1 = dynamic_cast<NonLocalNeighborhood<RemoveDamagedWeightFunction> &>( - model.getNonLocalManager().getNeighborhood("mat_1")); + model.getNeighborhood("mat_1")); NonLocalNeighborhood<RemoveDamagedWeightFunction> & neighborhood_2 = dynamic_cast<NonLocalNeighborhood<RemoveDamagedWeightFunction> &>( - model.getNonLocalManager().getNeighborhood("mat_2")); + model.getNeighborhood("mat_2")); neighborhood_1.saveWeights("before_0"); neighborhood_2.saveWeights("before_1"); for (UInt n = 0; n < 2; ++n) { /// print results to screen for validation std::stringstream sstr; sstr << "before_" << n << ".0"; std::ifstream weights; weights.open(sstr.str()); std::string current_line; while (getline(weights, current_line)) std::cout << current_line << std::endl; weights.close(); } /// apply damage to not have the elements with lower strain impact the /// averaging for (UInt m = 0; m < model.getNbMaterials(); ++m) { MaterialDamage<spatial_dimension> & mat = dynamic_cast<MaterialDamage<spatial_dimension> &>(model.getMaterial(m)); Array<Real> & damage = const_cast<Array<Real> &>( mat.getInternal<Real>("damage")(element_type, ghost_type)); Array<Real>::scalar_iterator dam_it = damage.begin(); Array<Real>::scalar_iterator dam_end = damage.end(); UInt element_counter = 0; for (; dam_it != dam_end; ++dam_it, ++element_counter) if (element_counter == 12 || element_counter == 13 || element_counter == 14 || element_counter == 15) *dam_it = 0.9; } /// compute the non-local strains - model.getNonLocalManager().computeAllNonLocalStresses(); + model.assembleInternalForces(); neighborhood_1.saveWeights("after_0"); neighborhood_2.saveWeights("after_1"); for (UInt n = 0; n < 2; ++n) { /// print results to screen for validation std::stringstream sstr; sstr << "after_" << n << ".0"; std::ifstream weights; weights.open(sstr.str()); std::string current_line; while (getline(weights, current_line)) std::cout << current_line << std::endl; weights.close(); } model.dump(); /// verify the result: non-local averaging over constant field must /// yield same constant field Real test_result = 0.; Matrix<Real> difference(spatial_dimension, spatial_dimension, 0.); Matrix<Real> difference_in_damaged_elements(spatial_dimension, spatial_dimension, 0.); for (UInt m = 0; m < model.getNbMaterials(); ++m) { difference_in_damaged_elements.clear(); - MaterialNonLocal<spatial_dimension> & mat = - dynamic_cast<MaterialNonLocal<spatial_dimension> &>( - model.getMaterial(m)); + auto & mat = + model.getMaterial(m); Array<Real> & grad_u_nl = const_cast<Array<Real> &>( mat.getInternal<Real>("grad_u non local")(element_type, ghost_type)); Array<Real>::iterator<Matrix<Real> > grad_u_nl_it = grad_u_nl.begin(spatial_dimension, spatial_dimension); Array<Real>::iterator<Matrix<Real> > grad_u_nl_end = grad_u_nl.end(spatial_dimension, spatial_dimension); UInt element_counter = 0; for (; grad_u_nl_it != grad_u_nl_end; ++grad_u_nl_it, ++element_counter) { if (element_counter == 12 || element_counter == 13 || element_counter == 14 || element_counter == 15) difference_in_damaged_elements += (*grad_u_nl_it); else difference = (*grad_u_nl_it) - applied_strain; test_result += difference.norm<L_2>(); } difference_in_damaged_elements *= (1 / 4.); difference_in_damaged_elements -= (1.41142 * modified_strain); test_result += difference_in_damaged_elements.norm<L_2>(); } if (test_result > 10.e-5) { std::cout << "the total norm is: " << test_result << std::endl; return EXIT_FAILURE; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_non_local_toolbox/test_weight_computation.cc b/test/test_model/test_non_local_toolbox/test_weight_computation.cc index 6ca55d14f..54ec60c78 100644 --- a/test/test_model/test_non_local_toolbox/test_weight_computation.cc +++ b/test/test_model/test_non_local_toolbox/test_weight_computation.cc @@ -1,78 +1,76 @@ /** * @file test_weight_computation.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * * @date creation: Sat Sep 26 2015 * @date last modification: Wed Oct 07 2015 * * @brief test for the weight computation with base weight function * * @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 "dumper_paraview.hh" #include "non_local_manager.hh" #include "non_local_neighborhood.hh" #include "solid_mechanics_model.hh" #include "test_material.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { akantu::initialize("material_weight_computation.dat", argc, argv); // some configuration variables const UInt spatial_dimension = 2; // mesh creation and read Mesh mesh(spatial_dimension); mesh.read("plate.msh"); /// model creation SolidMechanicsModel model(mesh); /// model initialization changed to use our material - model.initFull(_no_init_materials = true); - model.registerNewCustomMaterials<TestMaterial<spatial_dimension> >( - "test_material"); - model.initMaterials(); + model.initFull(); + /// dump material index in paraview model.addDumpField("material_index"); model.dump(); /// save the weights in a file NonLocalNeighborhood<BaseWeightFunction> & neighborhood = dynamic_cast<NonLocalNeighborhood<BaseWeightFunction> &>( - model.getNonLocalManager().getNeighborhood("test_region")); + model.getNeighborhood("test_region")); neighborhood.saveWeights("weights"); /// print results to screen for validation std::ifstream weights; weights.open("weights.0"); std::string current_line; while (getline(weights, current_line)) std::cout << current_line << std::endl; weights.close(); finalize(); return EXIT_SUCCESS; } 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 dfa76b23f..1e199d191 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,312 +1,313 @@ /** * @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 <iostream> - #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 (UInt i = 0; i < dim; ++i) boundary(*nodes_it, 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 26751dd04..fde87d4e0 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,312 +1,314 @@ /** * @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 <iostream> - #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 (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/test_materials/test_local_material.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc index 1a035ea5b..62c37d21e 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc @@ -1,121 +1,126 @@ /** * @file test_local_material.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Marion Estelle Chambart <marion.chambart@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Clement Roux <clement.roux@epfl.ch> * * @date creation: Wed Aug 04 2010 * @date last modification: Thu Oct 15 2015 * * @brief test of the class SolidMechanicsModel with custom local damage on a * notched plate * * @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 "local_material_damage.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char * argv[]) { akantu::initialize("material.dat", argc, argv); UInt max_steps = 1100; const UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); mesh.read("mesh_section_gap.msh"); - + SolidMechanicsModel model(mesh); /// model initialization - model.initFull(_no_init_materials = true); - model.registerNewCustomMaterials<LocalMaterialDamage>("local_damage"); - model.initMaterials(); + MaterialFactory::getInstance().registerAllocator( + "local_damage", + [](UInt, const ID &, SolidMechanicsModel & model, + const ID & id) -> std::unique_ptr<Material> { + return std::make_unique<LocalMaterialDamage>(model, id); + }); + + model.initFull(); Real time_step = model.getStableTimeStep(); model.setTimeStep(time_step / 2.5); model.assembleMassLumped(); std::cout << model << std::endl; /// Dirichlet boundary conditions model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "Fixed"); // model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "Fixed"); // Boundary condition (Neumann) Matrix<Real> stress(2, 2); stress.eye(7e5); model.applyBC(BC::Neumann::FromHigherDim(stress), "Traction"); for (UInt s = 0; s < max_steps; ++s) { if (s < 100) { // Boundary condition (Neumann) stress.eye(7e5); model.applyBC(BC::Neumann::FromHigherDim(stress), "Traction"); } model.solveStep(); } const Vector<Real> & lower_bounds = mesh.getLowerBounds(); const Vector<Real> & upper_bounds = mesh.getUpperBounds(); Real L = upper_bounds(0) - lower_bounds(0); const ElementTypeMapArray<UInt> & filter = model.getMaterial(0).getElementFilter(); ElementTypeMapArray<UInt>::type_iterator it = filter.firstType(spatial_dimension); ElementTypeMapArray<UInt>::type_iterator end = filter.lastType(spatial_dimension); Vector<Real> barycenter(spatial_dimension); bool is_fully_damaged = false; for (; it != end; ++it) { UInt nb_elem = mesh.getNbElement(*it); const UInt nb_gp = model.getFEEngine().getNbIntegrationPoints(*it); Array<Real> & material_damage_array = model.getMaterial(0).getArray<Real>("damage", *it); UInt cpt = 0; for (UInt nel = 0; nel < nb_elem; ++nel) { if (material_damage_array(cpt, 0) > 0.9) { is_fully_damaged = true; mesh.getBarycenter(nel, *it, barycenter.storage()); if ((std::abs(barycenter(0) - (L / 2)) < (L / 10))) { return EXIT_FAILURE; } } cpt += nb_gp; } } if (!is_fully_damaged) return EXIT_FAILURE; akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_mazars.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_mazars.cc index ab43b67d9..327c764f7 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_mazars.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_mazars.cc @@ -1,294 +1,290 @@ /** * @file test_material_mazars.cc * * @author Clement Roux <clement.roux@epfl.ch> * * @date creation: Thu Oct 08 2015 * @date last modification: Tue Dec 08 2015 * * @brief test for material mazars, dissymmetric * * @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 "aka_common.hh" -#include "material.hh" -#include "mesh.hh" -#include "mesh_io.hh" #include "solid_mechanics_model.hh" -//#include "io_helper_tools.hh" - /* -------------------------------------------------------------------------- */ +#include <fstream> +/* -------------------------------------------------------------------------- */ + using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { debug::setDebugLevel(akantu::dblWarning); akantu::initialize("material_mazars.dat", argc, argv); const UInt spatial_dimension = 3; // ElementType type = _quadrangle_4; ElementType type = _hexahedron_8; // UInt compression_steps = 5e5; // Real max_compression = 0.01; // UInt traction_steps = 1e4; // Real max_traction = 0.001; Mesh mesh(spatial_dimension); mesh.addConnectivityType(type); Array<Real> & nodes = const_cast<Array<Real> &>(mesh.getNodes()); Array<UInt> & connectivity = const_cast<Array<UInt> &>(mesh.getConnectivity(type)); const Real width = 1; UInt nb_dof = 0; connectivity.resize(1); if (type == _hexahedron_8) { nb_dof = 8; nodes.resize(nb_dof); nodes(0, 0) = 0.; nodes(0, 1) = 0.; nodes(0, 2) = 0.; nodes(1, 0) = width; nodes(1, 1) = 0.; nodes(1, 2) = 0.; nodes(2, 0) = width; nodes(2, 1) = width; nodes(2, 2) = 0; nodes(3, 0) = 0; nodes(3, 1) = width; nodes(3, 2) = 0; nodes(4, 0) = 0.; nodes(4, 1) = 0.; nodes(4, 2) = width; nodes(5, 0) = width; nodes(5, 1) = 0.; nodes(5, 2) = width; nodes(6, 0) = width; nodes(6, 1) = width; nodes(6, 2) = width; nodes(7, 0) = 0; nodes(7, 1) = width; nodes(7, 2) = width; connectivity(0, 0) = 0; connectivity(0, 1) = 1; connectivity(0, 2) = 2; connectivity(0, 3) = 3; connectivity(0, 4) = 4; connectivity(0, 5) = 5; connectivity(0, 6) = 6; connectivity(0, 7) = 7; } else if (type == _quadrangle_4) { nb_dof = 4; nodes.resize(nb_dof); nodes(0, 0) = 0.; nodes(0, 1) = 0.; nodes(1, 0) = width; nodes(1, 1) = 0; nodes(2, 0) = width; nodes(2, 1) = width; nodes(3, 0) = 0.; nodes(3, 1) = width; connectivity(0, 0) = 0; connectivity(0, 1) = 1; connectivity(0, 2) = 2; connectivity(0, 3) = 3; } SolidMechanicsModel model(mesh); model.initFull(); Material & mat = model.getMaterial(0); std::cout << mat << std::endl; /// boundary conditions Array<Real> & disp = model.getDisplacement(); Array<Real> & velo = model.getVelocity(); Array<bool> & boun = model.getBlockedDOFs(); for (UInt i = 0; i < nb_dof; ++i) { boun(i, 0) = true; } Real time_step = model.getStableTimeStep() * .5; // Real time_step = 1e-5; std::cout << "Time Step = " << time_step << "s - nb elements : " << mesh.getNbElement(type) << std::endl; model.setTimeStep(time_step); std::ofstream energy; energy.open("energies_and_scalar_mazars.csv"); energy << "id,rtime,epot,ekin,u,wext,kin+pot,D,strain_xx,strain_yy,stress_xx," "stress_yy,edis,tot" << std::endl; /// Set dumper model.setBaseName("uniaxial_comp-trac_mazars"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity"); model.addDumpField("acceleration"); model.addDumpField("damage"); model.addDumpField("strain"); model.addDumpField("stress"); model.addDumpField("partitions"); model.dump(); const Array<Real> & strain = mat.getGradU(type); const Array<Real> & stress = mat.getStress(type); const Array<Real> & damage = mat.getArray<Real>("damage", type); /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ Real wext = 0.; Real sigma_max = 0, sigma_min = 0; Real max_disp; Real stress_xx_compression_1; UInt nb_steps = 7e5 / 150; Real adisp = 0; for (UInt s = 0; s < nb_steps; ++s) { if (s == 0) { max_disp = 0.003; adisp = -(max_disp * 8. / nb_steps) / 2.; std::cout << "Step " << s << " compression: " << max_disp << std::endl; } if (s == (2 * nb_steps / 8)) { stress_xx_compression_1 = stress(0, 0); max_disp = 0 + max_disp; adisp = max_disp * 8. / nb_steps; std::cout << "Step " << s << " discharge" << std::endl; } if (s == (3 * nb_steps / 8)) { max_disp = 0.004; adisp = -max_disp * 8. / nb_steps; std::cout << "Step " << s << " compression: " << max_disp << std::endl; } if (s == (4 * nb_steps / 8)) { if (stress(0, 0) < stress_xx_compression_1) { std::cout << "after this second compression step softening should have " "started" << std::endl; return EXIT_FAILURE; } max_disp = 0.0015 + max_disp; adisp = max_disp * 8. / nb_steps; std::cout << "Step " << s << " discharge tension: " << max_disp << std::endl; } if (s == (5 * nb_steps / 8)) { max_disp = 0. + 0.0005; adisp = -max_disp * 8. / nb_steps; std::cout << "Step " << s << " discharge" << std::endl; } if (s == (6 * nb_steps / 8)) { max_disp = 0.0035 - 0.001; adisp = max_disp * 8. / nb_steps; std::cout << "Step " << s << " tension: " << max_disp << std::endl; } if (s == (7 * nb_steps / 8)) { // max_disp = max_disp; adisp = -max_disp * 8. / nb_steps; std::cout << "Step " << s << " discharge" << std::endl; } for (UInt i = 0; i < nb_dof; ++i) { if (std::abs(nodes(i, 0) - width) < std::numeric_limits<Real>::epsilon()) { disp(i, 0) += adisp; velo(i, 0) = adisp / time_step; } } std::cout << "S: " << s << "/" << nb_steps << " inc disp: " << adisp << " disp: " << std::setw(5) << disp(2, 0) << "\r" << std::flush; model.solveStep(); Real epot = model.getEnergy("potential"); Real ekin = model.getEnergy("kinetic"); Real edis = model.getEnergy("dissipated"); wext += model.getEnergy("external work"); sigma_max = std::max(sigma_max, stress(0, 0)); sigma_min = std::min(sigma_min, stress(0, 0)); if (s % 10 == 0) energy << s << "," // 1 << s * time_step << "," // 2 << epot << "," // 3 << ekin << "," // 4 << disp(2, 0) << "," // 5 << wext << "," // 6 << epot + ekin << "," // 7 << damage(0) << "," // 8 << strain(0, 0) << "," // 9 << strain(0, 3) << "," // 11 << stress(0, 0) << "," // 10 << stress(0, 3) << "," // 10 << edis << "," // 12 << epot + ekin + edis // 13 << std::endl; if (s % 100 == 0) model.dump(); } std::cout << std::endl << "sigma_max = " << sigma_max << ", sigma_min = " << sigma_min << std::endl; /// Verif the maximal/minimal stress values if ((std::abs(sigma_max) > std::abs(sigma_min)) || (std::abs(sigma_max - 6.24e6) > 1e5) || (std::abs(sigma_min + 2.943e7) > 1e6)) return EXIT_FAILURE; energy.close(); akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.cc index 1ae75be0b..935159b21 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/custom_non_local_test_material.cc @@ -1,86 +1,86 @@ /** * @file custom_non_local_test_material.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sun Mar 01 2015 * @date last modification: Thu Oct 15 2015 * * @brief Custom material to test the non local implementation * * @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 "custom_non_local_test_material.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template <UInt dim> CustomNonLocalTestMaterial<dim>::CustomNonLocalTestMaterial( SolidMechanicsModel & model, const ID & id) : MyNonLocalParent(model, id), local_damage("local_damage", *this), damage("damage", *this) { // Initialize the internal field by specifying the number of components this->local_damage.initialize(1); this->damage.initialize(1); /// register the non-local variable in the manager this->model.registerNonLocalVariable(this->local_damage.getName(), this->damage.getName(), 1); } /* -------------------------------------------------------------------------- */ template <UInt dim> void CustomNonLocalTestMaterial<dim>::initMaterial() { MyNonLocalParent::initMaterial(); this->model.getNeighborhood(this->name).registerNonLocalVariable(damage.getName()); } /* -------------------------------------------------------------------------- */ template <UInt dim> void CustomNonLocalTestMaterial<dim>::computeStress(ElementType el_type, GhostType ghost_type) { MyNonLocalParent::computeStress(el_type, ghost_type); } /* -------------------------------------------------------------------------- */ template <UInt dim> void CustomNonLocalTestMaterial<dim>::computeNonLocalStress( ElementType el_type, GhostType ghost_type) { Array<Real>::const_scalar_iterator dam = this->damage(el_type, ghost_type).begin(); Array<Real>::matrix_iterator stress = this->stress(el_type, ghost_type).begin(dim, dim); Array<Real>::matrix_iterator stress_end = this->stress(el_type, ghost_type).end(dim, dim); // compute the damage and update the stresses for (; stress != stress_end; ++stress, ++dam) { *stress *= (1. - *dam); } } /* -------------------------------------------------------------------------- */ // Instantiate the material for the 3 dimensions -INSTANTIATE_MATERIAL(CustomNonLocalTestMaterial); +INSTANTIATE_MATERIAL(custom_non_local_test_material, CustomNonLocalTestMaterial); /* -------------------------------------------------------------------------- */ } // namespace akantu diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_non_local.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_non_local.cc index 409d04898..90cc88bf2 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_non_local.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_non_local.cc @@ -1,104 +1,101 @@ /** * @file test_material_non_local.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Aug 31 2011 * @date last modification: Thu Oct 15 2015 * * @brief test of the main part of the non local materials * * @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 "custom_non_local_test_material.hh" /* -------------------------------------------------------------------------- */ #include <iostream> /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::initialize("material.dat", argc, argv); // some configuration variables const UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); StaticCommunicator & comm = akantu::StaticCommunicator::getStaticCommunicator(); Int prank = comm.whoAmI(); // mesh creation and read if(prank == 0) { mesh.read("mesh.msh"); } mesh.distribute(); /// model creation SolidMechanicsModel model(mesh); /// model initialization changed to use our material - model.initFull(_no_init_materials = true); - - model.registerNewCustomMaterials< CustomNonLocalTestMaterial<spatial_dimension> >("custom_non_local_test_material"); - model.initMaterials(); + model.initFull(); CustomNonLocalTestMaterial<spatial_dimension> & mat = dynamic_cast<CustomNonLocalTestMaterial<spatial_dimension> &>(model.getMaterial("test")); if(prank == 0) std::cout << mat << std::endl; // Setting up the dumpers + first dump model.setBaseName("non_local_material"); model.addDumpFieldVector("displacement"); model.addDumpFieldVector("external_force"); model.addDumpFieldVector("internal_force"); model.addDumpField("partitions" ); model.addDumpField("stress" ); model.addDumpField("stress" ); model.addDumpField("local_damage"); model.addDumpField("damage" ); model.assembleInternalForces(); model.dump(); //Array<Real> & damage = mat.getArray("local_damage", _quadrangle_4); Array<Real> & damage = mat.getArray<Real>("local_damage", _triangle_3); - RandGenerator<UInt> gen; + RandomGenerator<UInt> gen; for (UInt i = 0; i < 1; ++i) { - UInt g = (gen() / Real(RandGenerator<UInt>::max() - RandGenerator<UInt>::min())) * damage.getSize(); + UInt g = (gen() / Real(RandomGenerator<UInt>::max() - RandomGenerator<UInt>::min())) * damage.getSize(); std::cout << prank << " -> " << g << std::endl; damage(g) = 1.; } model.assembleInternalForces(); model.dump(); akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_orthotropic.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_orthotropic.cc index e6e632dc8..8353c4b9b 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_orthotropic.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_orthotropic.cc @@ -1,100 +1,99 @@ /** * @file test_material_orthotropic.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Aug 04 2010 * @date last modification: Tue Sep 01 2015 * * @brief test of the class SolidMechanicsModel * * @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 "solid_mechanics_model.hh" +/* -------------------------------------------------------------------------- */ +#include <fstream> +/* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { // akantu::initialize("orthotropic.dat", argc, argv); akantu::initialize("orthotropic.dat", argc, argv); UInt max_steps = 1000; Real epot, ekin; Mesh mesh(2); mesh.read("square.msh"); mesh.createBoundaryGroupFromGeometry(); SolidMechanicsModel model(mesh); /// model initialization model.initFull(); Real time_step = model.getStableTimeStep(); model.setTimeStep(time_step/10.); model.assembleMassLumped(); std::cout << model << std::endl; // Boundary condition (Neumann) Matrix<Real> stress(2,2); stress.eye(Real(1e3)); model.applyBC(BC::Neumann::FromHigherDim(stress), "boundary_0"); model.setBaseName ("square-orthotrope" ); model.addDumpFieldVector("displacement"); model.addDumpField ("mass" ); model.addDumpField ("velocity" ); model.addDumpField ("acceleration"); model.addDumpFieldVector("external_force"); model.addDumpFieldVector("internal_force"); model.addDumpField ("stress" ); model.addDumpField ("grad_u" ); model.dump(); std::ofstream energy; energy.open("energy.csv"); energy << "id,epot,ekin,tot" << std::endl; for(UInt s = 0; s < max_steps; ++s) { model.solveStep(); epot = model.getEnergy("potential"); ekin = model.getEnergy("kinetic"); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; if(s % 100 == 0) model.dump(); } energy.close(); finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d.cc index a265c2bd2..348076bd1 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d.cc @@ -1,108 +1,106 @@ /** * @file test_solid_mechanics_model_cube3d.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * * @date creation: Wed Aug 04 2010 * @date last modification: Thu Aug 06 2015 * * @brief test of the class SolidMechanicsModel on the 3d 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 <iostream> - /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" - +/* -------------------------------------------------------------------------- */ +#include <fstream> /* -------------------------------------------------------------------------- */ -int main(int argc, char *argv[]) -{ +int main(int argc, char * argv[]) { akantu::initialize("material.dat", argc, argv); akantu::UInt max_steps = 10000; akantu::Real epot, ekin; akantu::Mesh mesh(3); mesh.read("cube1.msh"); akantu::SolidMechanicsModel model(mesh); model.initFull(); akantu::Real time_step = model.getStableTimeStep(); - model.setTimeStep(time_step/10.); + model.setTimeStep(time_step / 10.); model.assembleMassLumped(); std::cout << model << std::endl; - /// boundary conditions akantu::UInt nb_nodes = mesh.getNbNodes(); akantu::Real eps = 1e-16; for (akantu::UInt i = 0; i < nb_nodes; ++i) { - model.getDisplacement().storage()[3*i] = model.getFEEngine().getMesh().getNodes().storage()[3*i] / 100.; + model.getDisplacement().storage()[3 * i] = + model.getFEEngine().getMesh().getNodes().storage()[3 * i] / 100.; - if(model.getFEEngine().getMesh().getNodes().storage()[3*i] <= eps) { - model.getBlockedDOFs().storage()[3*i ] = true; + if (model.getFEEngine().getMesh().getNodes().storage()[3 * i] <= eps) { + model.getBlockedDOFs().storage()[3 * i] = true; } - if(model.getFEEngine().getMesh().getNodes().storage()[3*i + 1] <= eps) { - model.getBlockedDOFs().storage()[3*i + 1] = true; + if (model.getFEEngine().getMesh().getNodes().storage()[3 * i + 1] <= eps) { + model.getBlockedDOFs().storage()[3 * i + 1] = true; } } model.setBaseName("cube3d"); model.addDumpField("displacement"); - model.addDumpField("mass" ); - model.addDumpField("velocity" ); + model.addDumpField("mass"); + model.addDumpField("velocity"); model.addDumpField("acceleration"); model.addDumpField("external_force"); model.addDumpField("internal_force"); - model.addDumpField("stress" ); - model.addDumpField("grad_u" ); + model.addDumpField("stress"); + model.addDumpField("grad_u"); model.addDumpField("element_index_by_material"); model.dump(); std::ofstream energy; energy.open("energy.csv"); energy << "id,epot,ekin,tot" << std::endl; - for(akantu::UInt s = 0; s < max_steps; ++s) { + for (akantu::UInt s = 0; s < max_steps; ++s) { model.solveStep(); epot = model.getEnergy("potential"); ekin = model.getEnergy("kinetic"); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin - << std::endl; + << std::endl; - if(s % 10 == 0) model.dump(); + if (s % 10 == 0) + model.dump(); } energy.close(); akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_tetra10.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_tetra10.cc index 8a2ea7205..35d67e1ad 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_tetra10.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_tetra10.cc @@ -1,110 +1,107 @@ /** * @file test_solid_mechanics_model_cube3d_tetra10.cc * * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @author Peter Spijker <peter.spijker@epfl.ch> * * @date creation: Wed Aug 04 2010 * @date last modification: Thu Aug 06 2015 * * @brief test of the class SolidMechanicsModel on the 3d 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 <iostream> - /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" - +/* -------------------------------------------------------------------------- */ +#include <fstream> /* -------------------------------------------------------------------------- */ -int main(int argc, char *argv[]) -{ +int main(int argc, char * argv[]) { akantu::initialize("material.dat", argc, argv); akantu::UInt max_steps = 1000; akantu::Real epot, ekin; akantu::Mesh mesh(3); mesh.read("cube2.msh"); akantu::SolidMechanicsModel model(mesh); /// model initialization model.initFull(); akantu::Real time_step = model.getStableTimeStep(); - model.setTimeStep(time_step/10.); + model.setTimeStep(time_step / 10.); model.assembleMassLumped(); std::cout << model << std::endl; - /// boundary conditions akantu::Real eps = 1e-2; akantu::UInt nb_nodes = model.getFEEngine().getMesh().getNbNodes(); for (akantu::UInt i = 0; i < nb_nodes; ++i) { - model.getDisplacement().storage()[3*i] = model.getFEEngine().getMesh().getNodes().storage()[3*i] / 100.; + model.getDisplacement().storage()[3 * i] = + model.getFEEngine().getMesh().getNodes().storage()[3 * i] / 100.; - if(model.getFEEngine().getMesh().getNodes().storage()[3*i] <= eps) { - model.getBlockedDOFs().storage()[3*i ] = true; + if (model.getFEEngine().getMesh().getNodes().storage()[3 * i] <= eps) { + model.getBlockedDOFs().storage()[3 * i] = true; } - if(model.getFEEngine().getMesh().getNodes().storage()[3*i + 1] <= eps) { - model.getBlockedDOFs().storage()[3*i + 1] = true; + if (model.getFEEngine().getMesh().getNodes().storage()[3 * i + 1] <= eps) { + model.getBlockedDOFs().storage()[3 * i + 1] = true; } } // model.getDisplacement().storage()[1] = 0.1; model.setBaseName("cube3d_t10"); model.addDumpField("displacement"); - model.addDumpField("mass" ); - model.addDumpField("velocity" ); + model.addDumpField("mass"); + model.addDumpField("velocity"); model.addDumpField("acceleration"); model.addDumpField("external_force"); model.addDumpField("internal_force"); - model.addDumpField("stress" ); - model.addDumpField("strain" ); + model.addDumpField("stress"); + model.addDumpField("strain"); model.dump(); std::ofstream energy; energy.open("energy.csv"); energy << "id,epot,ekin,tot" << std::endl; - for(akantu::UInt s = 0; s < max_steps; ++s) { + for (akantu::UInt s = 0; s < max_steps; ++s) { model.solveStep(); epot = model.getEnergy("potential"); ekin = model.getEnergy("kinetic"); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin - << std::endl; + << std::endl; - if(s % 10 == 0) model.dump(); + if (s % 10 == 0) + model.dump(); } energy.close(); akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_square.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_square.cc index 0a7ef5b3b..1a4d909fc 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_square.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_square.cc @@ -1,99 +1,101 @@ /** * @file test_solid_mechanics_model_square.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Aug 04 2010 * @date last modification: Thu Aug 06 2015 * * @brief test of the class SolidMechanicsModel * * @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 "solid_mechanics_model.hh" +/* -------------------------------------------------------------------------- */ +#include <fstream> +/* -------------------------------------------------------------------------- */ + using namespace akantu; -int main(int argc, char *argv[]) { +int main(int argc, char * argv[]) { akantu::initialize("material.dat", argc, argv); UInt max_steps = 1000; Real epot, ekin; Mesh mesh(2); mesh.read("square.msh"); mesh.createBoundaryGroupFromGeometry(); SolidMechanicsModel model(mesh); /// model initialization model.initFull(); Real time_step = model.getStableTimeStep(); - model.setTimeStep(time_step/10.); + model.setTimeStep(time_step / 10.); model.assembleMassLumped(); std::cout << model << std::endl; // Boundary condition (Neumann) - Matrix<Real> stress(2,2); + Matrix<Real> stress(2, 2); stress.eye(Real(1e3)); model.applyBC(BC::Neumann::FromHigherDim(stress), "boundary_0"); - model.setBaseName ("square" ); + model.setBaseName("square"); model.addDumpFieldVector("displacement"); - model.addDumpField ("mass" ); - model.addDumpField ("velocity" ); - model.addDumpField ("acceleration"); + model.addDumpField("mass"); + model.addDumpField("velocity"); + model.addDumpField("acceleration"); model.addDumpFieldVector("external_force"); model.addDumpFieldVector("internal_force"); - model.addDumpField ("stress" ); - model.addDumpField ("strain" ); + model.addDumpField("stress"); + model.addDumpField("strain"); model.dump(); std::ofstream energy; energy.open("energy.csv"); energy << "id,epot,ekin,tot" << std::endl; - for(UInt s = 0; s < max_steps; ++s) { + for (UInt s = 0; s < max_steps; ++s) { model.solveStep(); epot = model.getEnergy("potential"); ekin = model.getEnergy("kinetic"); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin - << std::endl; + << std::endl; - if(s % 100 == 0) model.dump(); + if (s % 100 == 0) + model.dump(); } energy.close(); finalize(); return EXIT_SUCCESS; } diff --git a/test/test_synchronizer/test_data_accessor.hh b/test/test_synchronizer/test_data_accessor.hh index c1859bd31..3791f52a6 100644 --- a/test/test_synchronizer/test_data_accessor.hh +++ b/test/test_synchronizer/test_data_accessor.hh @@ -1,135 +1,132 @@ /** * @file test_data_accessor.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Thu Apr 11 2013 * @date last modification: Sun Oct 19 2014 * * @brief Data Accessor class for testing * * @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 "data_accessor.hh" #include "mesh.hh" +using namespace akantu; /* -------------------------------------------------------------------------- */ -__BEGIN_AKANTU__ - class TestAccessor : public DataAccessor<Element> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: inline TestAccessor(const Mesh & mesh, const ElementTypeMapArray<Real> & barycenters); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Barycenter, barycenters, Real); /* ------------------------------------------------------------------------ */ /* Ghost Synchronizer inherited members */ /* ------------------------------------------------------------------------ */ protected: inline UInt getNbData(const Array<Element> & elements, const SynchronizationTag & tag) const; inline void packData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) const; inline void unpackData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: const ElementTypeMapArray<Real> & barycenters; const Mesh & mesh; }; /* -------------------------------------------------------------------------- */ /* TestSynchronizer implementation */ /* -------------------------------------------------------------------------- */ inline TestAccessor::TestAccessor(const Mesh & mesh, const ElementTypeMapArray<Real> & barycenters) : barycenters(barycenters), mesh(mesh) {} inline UInt TestAccessor::getNbData(const Array<Element> & elements, const SynchronizationTag &) const { if (elements.getSize()) // return Mesh::getSpatialDimension(elements(0).type) * sizeof(Real) * // elements.getSize(); return mesh.getSpatialDimension() * sizeof(Real) * elements.getSize(); else return 0; } inline void TestAccessor::packData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag &) const { UInt spatial_dimension = mesh.getSpatialDimension(); Array<Element>::const_iterator<Element> bit = elements.begin(); Array<Element>::const_iterator<Element> bend = elements.end(); for (; bit != bend; ++bit) { const Element & element = *bit; Vector<Real> bary( this->barycenters(element.type, element.ghost_type).storage() + element.element * spatial_dimension, spatial_dimension); buffer << bary; } } inline void TestAccessor::unpackData(CommunicationBuffer & buffer, const Array<Element> & elements, const SynchronizationTag & tag) { UInt spatial_dimension = mesh.getSpatialDimension(); Array<Element>::const_iterator<Element> bit = elements.begin(); Array<Element>::const_iterator<Element> bend = elements.end(); for (; bit != bend; ++bit) { const Element & element = *bit; Vector<Real> barycenter_loc( this->barycenters(element.type, element.ghost_type).storage() + element.element * spatial_dimension, spatial_dimension); Vector<Real> bary(spatial_dimension); buffer >> bary; std::cout << element << barycenter_loc << std::endl; Real tolerance = 1e-15; for (UInt i = 0; i < spatial_dimension; ++i) { if (!(std::abs(bary(i) - barycenter_loc(i)) <= tolerance)) AKANTU_DEBUG_ERROR("Unpacking an unknown value for the element: " << element << "(barycenter[" << i << "] = " << barycenter_loc(i) << " and buffer[" << i << "] = " << bary(i) << ") - tag: " << tag); } } } - -__END_AKANTU__ diff --git a/test/test_synchronizer/test_synchronizer_communication.cc b/test/test_synchronizer/test_synchronizer_communication.cc index 78fc98cbe..390b4616e 100644 --- a/test/test_synchronizer/test_synchronizer_communication.cc +++ b/test/test_synchronizer/test_synchronizer_communication.cc @@ -1,161 +1,160 @@ /** * @file test_synchronizer_communication.cc * * @author Dana Christen <dana.christen@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Sep 01 2010 * @date last modification: Sun Oct 19 2014 * * @brief test to synchronize barycenters * * @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_random_generator.hh" #include "element_synchronizer.hh" #include "mesh.hh" #include "mesh_partition_scotch.hh" #include "synchronizer_registry.hh" /* -------------------------------------------------------------------------- */ //#define DUMP #if defined(AKANTU_USE_IOHELPER) && defined(DUMP) #include "dumper_paraview.hh" #endif // AKANTU_USE_IOHELPER #include "test_data_accessor.hh" using namespace akantu; /* -------------------------------------------------------------------------- */ /* Main */ /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize(argc, argv); UInt spatial_dimension = 3; Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int prank = comm.whoAmI(); bool wait = true; if (argc > 1) { if (prank == 0) while (wait) ; } if (prank == 0) mesh.read("cube.msh"); mesh.distribute(); /// compute barycenter for each facet ElementTypeMapArray<Real> barycenters("barycenters", "", 0); - mesh.initElementTypeMapArray(barycenters, spatial_dimension, - spatial_dimension); + barycenters.initialize(mesh, _nb_component = 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.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type); for (; it != last_type; ++it) { UInt nb_element = mesh.getNbElement(*it, ghost_type); Array<Real> & barycenter = barycenters(*it, ghost_type); barycenter.resize(nb_element); Array<Real>::iterator<Vector<Real>> bary_it = barycenter.begin(spatial_dimension); for (UInt elem = 0; elem < nb_element; ++elem, ++bary_it) mesh.getBarycenter(elem, *it, bary_it->storage(), ghost_type); } } AKANTU_DEBUG_INFO("Creating TestAccessor"); TestAccessor test_accessor(mesh, barycenters); SynchronizerRegistry synch_registry; synch_registry.registerDataAccessor(test_accessor); synch_registry.registerSynchronizer(mesh.getElementSynchronizer(), _gst_test); AKANTU_DEBUG_INFO("Synchronizing tag"); synch_registry.synchronize(_gst_test); // Checking the tags in MeshData (not a very good test because they're all // identical, // but still...) Mesh::type_iterator it = mesh.firstType(_all_dimensions); Mesh::type_iterator last_type = mesh.lastType(_all_dimensions); for (; it != last_type; ++it) { Array<UInt> & tags = mesh.getData<UInt>("tag_0", *it); Array<UInt>::const_vector_iterator tags_it = tags.begin(1); Array<UInt>::const_vector_iterator tags_end = tags.end(1); AKANTU_DEBUG_ASSERT( mesh.getNbElement(*it) == tags.getSize(), "The number of tags does not match the number of elements on rank " << prank << "."); std::cout << std::dec << " I am rank " << prank << " and here's my MeshData dump for types " << *it << " (it should contain " << mesh.getNbElement(*it) << " elements and it has " << tags.getSize() << "!) :" << std::endl; std::cout << std::hex; debug::setDebugLevel(dblTest); for (; tags_it != tags_end; ++tags_it) { std::cout << tags_it->operator()(0) << " "; } debug::setDebugLevel(dblInfo); std::cout << std::endl; } #if defined(AKANTU_USE_IOHELPER) && defined(DUMP) DumperParaview dumper("test-scotch-partition"); dumper.registerMesh(mesh, spatial_dimension, _not_ghost); dumper.registerField("partitions", new DumperIOHelper::ElementPartitionField<>(mesh, spatial_dimension, _not_ghost)); dumper.dump(); DumperParaview dumper_ghost("test-scotch-partition-ghost"); dumper_ghost.registerMesh(mesh, spatial_dimension, _ghost); dumper_ghost.registerField("partitions", new DumperIOHelper::ElementPartitionField<>(mesh, spatial_dimension, _ghost)); dumper_ghost.dump(); #endif //AKANTU_USE_IOHELPER finalize(); return EXIT_SUCCESS; }