diff --git a/packages/00_core.cmake b/packages/00_core.cmake index f25ec9d58..548da2800 100644 --- a/packages/00_core.cmake +++ b/packages/00_core.cmake @@ -1,352 +1,355 @@ #=============================================================================== # @file core.cmake # # @author Guillaume Anciaux # @author Nicolas Richart # # @date Mon Nov 21 18:19:15 2011 # # @brief package description for core # # @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 . # #=============================================================================== set(AKANTU_CORE ON CACHE INTERNAL "core package for Akantu" FORCE) set(AKANTU_CORE_FILES common/aka_array.cc common/aka_array.hh common/aka_array_tmpl.hh common/aka_blas_lapack.hh common/aka_circular_vector.hh common/aka_circular_vector_inline_impl.cc common/aka_common.cc common/aka_common.hh common/aka_common_inline_impl.cc common/aka_csr.hh common/aka_error.cc common/aka_error.hh common/aka_event_handler.hh common/aka_extern.cc common/aka_fwd.hh common/aka_grid.hh common/aka_grid_dynamic.hh common/aka_grid_tmpl.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_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.cc fem/by_element_type.hh fem/by_element_type_tmpl.hh fem/element_class.cc fem/element_class.hh fem/element_class_tmpl.hh fem/element_classes/element_class_hexahedron_8_inline_impl.cc fem/element_classes/element_class_pentahedron_6_inline_impl.cc fem/element_classes/element_class_point_1_inline_impl.cc fem/element_classes/element_class_quadrangle_4_inline_impl.cc fem/element_classes/element_class_quadrangle_8_inline_impl.cc fem/element_classes/element_class_segment_2_inline_impl.cc fem/element_classes/element_class_segment_3_inline_impl.cc fem/element_classes/element_class_tetrahedron_10_inline_impl.cc fem/element_classes/element_class_tetrahedron_4_inline_impl.cc fem/element_classes/element_class_triangle_3_inline_impl.cc fem/element_classes/element_class_triangle_6_inline_impl.cc fem/element_group.cc fem/element_group.hh fem/element_group_inline_impl.cc fem/fem.cc fem/fem.hh fem/fem_inline_impl.cc fem/fem_template.hh fem/fem_template_tmpl.hh fem/geometrical_data_tmpl.hh fem/geometrical_element.cc fem/group_manager.cc fem/group_manager.hh fem/group_manager_inline_impl.cc fem/integration_element.cc fem/integrator.hh fem/integrator_gauss.hh fem/integrator_gauss_inline_impl.cc fem/interpolation_element.cc fem/interpolation_element_tmpl.hh fem/mesh.cc fem/mesh.hh fem/mesh_filter.hh fem/mesh_data.cc fem/mesh_data.hh fem/mesh_data_tmpl.hh fem/mesh_inline_impl.cc fem/node_group.cc fem/node_group.hh fem/node_group_inline_impl.cc fem/shape_functions.hh fem/shape_functions_inline_impl.cc fem/shape_lagrange.cc fem/shape_lagrange.hh fem/shape_lagrange_inline_impl.cc fem/shape_linked.cc fem/shape_linked.hh fem/shape_linked_inline_impl.cc io/dumper/dumpable.hh io/dumper/dumpable_inline_impl.hh io/mesh_io.cc io/mesh_io.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.hh io/parser/parser_tmpl.hh + io/parser/cppargparse/cppargparse.hh + io/parser/cppargparse/cppargparse.cc + io/parser/cppargparse/cppargparse_tmpl.hh mesh_utils/mesh_partition.cc mesh_utils/mesh_partition.hh mesh_utils/mesh_partition/mesh_partition_mesh_data.cc mesh_utils/mesh_partition/mesh_partition_mesh_data.hh mesh_utils/mesh_partition/mesh_partition_scotch.hh mesh_utils/mesh_pbc.cc mesh_utils/mesh_utils.cc mesh_utils/mesh_utils.hh mesh_utils/mesh_utils_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/integration_scheme/generalized_trapezoidal.hh model/integration_scheme/generalized_trapezoidal_inline_impl.cc model/integration_scheme/integration_scheme_1st_order.hh model/integration_scheme/integration_scheme_2nd_order.hh model/integration_scheme/newmark-beta.hh model/integration_scheme/newmark-beta_inline_impl.cc 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_list.hh model/solid_mechanics/material_random_internal.hh 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/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/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_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 solver/solver.cc solver/solver.hh solver/sparse_matrix.cc solver/sparse_matrix.hh solver/sparse_matrix_inline_impl.cc synchronizer/communication_buffer.hh synchronizer/communication_buffer_inline_impl.cc synchronizer/data_accessor.cc synchronizer/data_accessor.hh synchronizer/data_accessor_inline_impl.cc synchronizer/distributed_synchronizer.cc synchronizer/distributed_synchronizer.hh synchronizer/distributed_synchronizer_tmpl.hh synchronizer/dof_synchronizer.cc synchronizer/dof_synchronizer.hh synchronizer/dof_synchronizer_inline_impl.cc synchronizer/filtered_synchronizer.cc synchronizer/filtered_synchronizer.hh synchronizer/mpi_type_wrapper.hh synchronizer/pbc_synchronizer.cc synchronizer/pbc_synchronizer.hh synchronizer/real_static_communicator.hh 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_registry.cc synchronizer/synchronizer_registry.hh ) set(AKANTU_CORE_DEB_DEPEND libboost-dev ) set(AKANTU_CORE_TESTS test_csr test_facet_element_mapping test_facet_extraction_tetrahedron_4 test_facet_extraction_triangle_3 test_grid test_interpolate_stress test_local_material test_material_damage_non_local test_material_thermal test_matrix test_mesh_boundary test_mesh_data test_mesh_io_msh test_mesh_io_msh_physical_names test_mesh_partitionate_mesh_data test_parser test_pbc_tweak test_purify_mesh test_solid_mechanics_model_bar_traction2d test_solid_mechanics_model_bar_traction2d_structured test_solid_mechanics_model_bar_traction2d_structured_pbc test_solid_mechanics_model_boundary_condition test_solid_mechanics_model_circle_2 test_solid_mechanics_model_cube3d test_solid_mechanics_model_cube3d_pbc test_solid_mechanics_model_cube3d_tetra10 test_solid_mechanics_model_square test_solid_mechanics_model_material_eigenstrain test_static_memory test_surface_extraction_tetrahedron_4 test_surface_extraction_triangle_3 test_vector test_vector_iterator test_weight test_math ) set(AKANTU_CORE_MANUAL_FILES manual.sty manual.cls manual.tex manual-macros.sty manual-titlepages.tex manual-introduction.tex manual-gettingstarted.tex manual-io.tex manual-solidmechanicsmodel.tex manual-lumping.tex manual-elements.tex manual-appendix-elements.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/hooke_law.pdf figures/hot-point-1.png figures/hot-point-2.png figures/implicit_dynamic.pdf figures/implicit_dynamic.svg figures/implicit_static.pdf figures/implicit_static.svg figures/insertion.pdf figures/interpolate.pdf figures/interpolate.svg figures/law.pdf figures/static_analysis.png figures/stress_strain_el.pdf figures/tangent.pdf figures/tangent.svg figures/vectors.pdf figures/vectors.svg 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 ) find_program(READLINK_COMMAND readlink) find_program(ADDR2LINE_COMMAND addr2line) mark_as_advanced(READLINK_COMMAND) mark_as_advanced(ADDR2LINE_COMMAND) include(CheckFunctionExists) check_function_exists(clock_gettime _clock_gettime) if(NOT _clock_gettime) set(AKANTU_USE_OBSOLETE_GETTIMEOFDAY ON) else() set(AKANTU_USE_OBSOLETE_GETTIMEOFDAY OFF) endif() diff --git a/src/common/aka_common.cc b/src/common/aka_common.cc index a5b94612b..3f92997e5 100644 --- a/src/common/aka_common.cc +++ b/src/common/aka_common.cc @@ -1,72 +1,125 @@ /** * @file aka_common.cc * * @author Nicolas Richart * * @date Mon Jun 14 19:12:20 2010 * * @brief Initialization of global variables * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_static_memory.hh" #include "static_communicator.hh" #include "aka_random_generator.hh" +#include "parser.hh" +#include "cppargparse.hh" /* -------------------------------------------------------------------------- */ __BEGIN_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); debug::debugger.setParallelContext(comm.whoAmI(), comm.getNbProc()); debug::initSignalHandler(); - long int seed = time(NULL) * (comm.whoAmI() + 1); + static_argparser.setExternalExitFunction(debug::Debugger::exit); + static_argparser.addArgument("--aka_input_file", "Akantu's input file", + 1, cppargparse::_string, std::string()); + static_argparser.addArgument("--aka_debug_level", "Akantu's overall debug level", 1, + cppargparse::_integer, int(dblWarning)); + + static_argparser.parse(argc, argv, cppargparse::_remove_parsed); + + std::string infile = static_argparser["aka_input_file"]; + if(infile == "") infile = input_file; + + debug::setDebugLevel(dblError); + + if ("" != infile) { + static_parser.parse(infile); + } + + long int seed; + try { + seed = static_parser.getParameter("seed", _ppsc_current_scope); + } catch (debug::Exception & e) { + seed = time(NULL); + } + + int dbl_level = static_argparser["aka_debug_level"]; + debug::setDebugLevel(DebugLevel(dbl_level)); + + seed *= (comm.whoAmI() + 1); Rand48Generator::seed(seed); RandGenerator::seed(seed); AKANTU_DEBUG_INFO("Random seed set to " << seed); + AKANTU_DEBUG_OUT(); + } /* -------------------------------------------------------------------------- */ void finalize() { AKANTU_DEBUG_IN(); if(StaticMemory::isInstantiated()) delete &(StaticMemory::getStaticMemory()); if(StaticCommunicator::isInstantiated()) { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); comm.barrier(); delete &comm; } AKANTU_DEBUG_OUT(); } +/* -------------------------------------------------------------------------- */ +cppargparse::ArgumentParser & getStaticArgumentParser() { + return static_argparser; +} + +/* -------------------------------------------------------------------------- */ +const Parser & getStaticParser() { + return static_parser; +} + +/* -------------------------------------------------------------------------- */ +const ParserSection & getUserParser() { + return *(static_parser.getSubSections(_st_user).first); +} __END_AKANTU__ diff --git a/src/common/aka_common.hh b/src/common/aka_common.hh index 03c0aa118..9dab5158f 100644 --- a/src/common/aka_common.hh +++ b/src/common/aka_common.hh @@ -1,546 +1,560 @@ /** * @file aka_common.hh * * @author Nicolas Richart * * @date Mon Jun 14 19:12:20 2010 * * @brief common type descriptions for akantu * * @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 . * * @section DESCRIPTION * * All common things to be included in the projects files * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COMMON_HH__ #define __AKANTU_COMMON_HH__ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #define __BEGIN_AKANTU__ namespace akantu { #define __END_AKANTU__ } /* -------------------------------------------------------------------------- */ #include "aka_config.hh" #include "aka_error.hh" #include "aka_safe_enum.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Common types */ /* -------------------------------------------------------------------------- */ typedef double Real; typedef unsigned int UInt; typedef unsigned long long UInt64; typedef signed int Int; typedef std::string ID; static const Real UINT_INIT_VALUE = 0; #ifdef AKANTU_NDEBUG static const Real REAL_INIT_VALUE = 0; #else static const Real REAL_INIT_VALUE = std::numeric_limits::quiet_NaN(); #endif /* -------------------------------------------------------------------------- */ /* Memory types */ /* -------------------------------------------------------------------------- */ typedef UInt MemoryID; /* -------------------------------------------------------------------------- */ /* Mesh/FEM/Model types */ /* -------------------------------------------------------------------------- */ typedef std::string Surface; typedef std::pair SurfacePair; typedef std::list< SurfacePair > SurfacePairList; /* -------------------------------------------------------------------------- */ extern const UInt _all_dimensions; /// @boost sequence of element to loop on in global tasks #define AKANTU_REGULAR_ELEMENT_TYPE \ (_point_1) \ (_segment_2) \ (_segment_3) \ (_triangle_3) \ (_triangle_6) \ (_quadrangle_4) \ (_quadrangle_8) \ (_tetrahedron_4) \ (_tetrahedron_10) \ (_pentahedron_6) \ (_hexahedron_8) #if defined(AKANTU_STRUCTURAL_MECHANICS) #define AKANTU_STRUCTURAL_ELEMENT_TYPE \ (_bernoulli_beam_2) \ (_bernoulli_beam_3) #else #define AKANTU_STRUCTURAL_ELEMENT_TYPE #endif #if defined(AKANTU_COHESIVE_ELEMENT) # define AKANTU_COHESIVE_ELEMENT_TYPE \ (_cohesive_2d_4) \ (_cohesive_2d_6) \ (_cohesive_1d_2) \ (_cohesive_3d_6) \ (_cohesive_3d_12) #else # define AKANTU_COHESIVE_ELEMENT_TYPE #endif #define AKANTU_ALL_ELEMENT_TYPE \ AKANTU_REGULAR_ELEMENT_TYPE \ AKANTU_COHESIVE_ELEMENT_TYPE \ AKANTU_STRUCTURAL_ELEMENT_TYPE #define AKANTU_NOT_STRUCTURAL_ELEMENT_TYPE \ AKANTU_REGULAR_ELEMENT_TYPE \ AKANTU_COHESIVE_ELEMENT_TYPE /// @enum ElementType type of elements enum ElementType { _not_defined, _point_1, _segment_2, ///< first order segment _segment_3, ///< second order segment _triangle_3, ///< first order triangle _triangle_6, ///< second order triangle _tetrahedron_4, ///< first order tetrahedron _tetrahedron_10, ///< second order tetrahedron _quadrangle_4, ///< first order quadrangle _quadrangle_8, ///< second order quadrangle _hexahedron_8, ///< first order hexahedron _pentahedron_6, ///< first order pentahedron _bernoulli_beam_2, ///< Bernoulli beam 2D _bernoulli_beam_3, ///< Bernoulli beam 3D #if defined(AKANTU_COHESIVE_ELEMENT) _cohesive_2d_4, ///< first order 2D cohesive _cohesive_2d_6, ///< second order 2D cohesive _cohesive_1d_2, ///< first order 1D cohesive _cohesive_3d_6, ///< first order 3D cohesive _cohesive_3d_12, ///< second order 3D cohesive #endif _max_element_type }; /// @enum GeometricalType type of element potentially contained in a Mesh enum GeometricalType { _gt_point, ///< point @remark only for some algorithm to be generic like mesh partitioning */ _gt_segment_2, ///< 2 nodes segment _gt_segment_3, ///< 3 nodes segment _gt_triangle_3, ///< 3 nodes triangle _gt_triangle_6, ///< 6 nodes triangle _gt_quadrangle_4, ///< 4 nodes quadrangle _gt_quadrangle_8, ///< 8 nodes quadrangle _gt_tetrahedron_4, ///< 4 nodes tetrahedron _gt_tetrahedron_10, ///< 10 nodes tetrahedron _gt_hexahedron_8, ///< 8 nodes hexahedron _gt_pentahedron_6, ///< 6 nodes pentahedron #if defined(AKANTU_COHESIVE_ELEMENT) _gt_cohesive_2d_4, ///< 4 nodes 2D cohesive _gt_cohesive_2d_6, ///< 6 nodes 2D cohesive _gt_cohesive_1d_2, ///< 2 nodes 1D cohesive _gt_cohesive_3d_6, ///< 6 nodes 3D cohesive _gt_cohesive_3d_12, ///< 12 nodes 3D cohesive #endif _gt_not_defined }; /// @enum InterpolationType type of elements enum InterpolationType { _itp_lagrange_point_1, ///< zeroth (!) order lagrangian point (for compatibility purposes) _itp_lagrange_segment_2, ///< first order lagrangian segment _itp_lagrange_segment_3, ///< second order lagrangian segment _itp_lagrange_triangle_3, ///< first order lagrangian triangle _itp_lagrange_triangle_6, ///< second order lagrangian triangle _itp_lagrange_quadrangle_4, ///< first order lagrangian quadrangle _itp_serendip_quadrangle_8, /**< second order serendipian quadrangle @remark used insted of the 9 node lagrangian element */ _itp_lagrange_tetrahedron_4, ///< first order lagrangian tetrahedron _itp_lagrange_tetrahedron_10, ///< second order lagrangian tetrahedron _itp_lagrange_hexahedron_8, ///< first order lagrangian hexahedron _itp_lagrange_pentahedron_6, ///< first order lagrangian pentahedron _itp_bernoulli_beam, ///< Bernoulli beam _itp_not_defined }; //! standard output stream operator for ElementType inline std::ostream & operator <<(std::ostream & stream, ElementType type); enum ElementKind { _ek_regular, _ek_cohesive, _ek_structural, _ek_not_defined }; /// enum MeshIOType type of mesh reader/writer enum MeshIOType { _miot_auto, _miot_gmsh, _miot_diana }; /// enum AnalysisMethod type of solving method used to solve the equation of motion enum AnalysisMethod { _static, _implicit_dynamic, _explicit_lumped_mass, _explicit_lumped_capacity, _explicit_consistent_mass }; /// enum SolveConvergenceMethod different resolution algorithms enum SolveConvergenceMethod { _scm_newton_raphson_tangent, ///< Newton-Raphson with tangent matrix _scm_newton_raphson_tangent_modified, ///< Newton-Raphson with constant tangent matrix _scm_newton_raphson_tangent_not_computed ///< Newton-Raphson with constant tangent matrix (user has to assemble it) }; /// enum SolveConvergenceCriteria different convergence criteria enum SolveConvergenceCriteria { _scc_residual, ///< Use residual to test the convergence _scc_increment ///< Use increment to test the convergence }; /// enum CohesiveMethod type of insertion of cohesive elements enum CohesiveMethod { _intrinsic, _extrinsic }; /// myfunction(double * position, double * stress/force, double * normal, unsigned int material_id) typedef void (*BoundaryFunction)(double *,double *, double*, unsigned int); /// @enum BoundaryFunctionType type of function passed for boundary conditions enum BoundaryFunctionType { _bft_stress, _bft_traction, _bft_traction_local }; /// @enum SparseMatrixType type of sparse matrix used enum SparseMatrixType { _unsymmetric, _symmetric }; /* -------------------------------------------------------------------------- */ /* Contact */ /* -------------------------------------------------------------------------- */ typedef ID ContactID; typedef ID ContactSearchID; typedef ID ContactNeighborStructureID; enum ContactType { _ct_not_defined = 0, _ct_2d_expli = 1, _ct_3d_expli = 2, _ct_rigid = 3 }; enum ContactSearchType { _cst_not_defined = 0, _cst_2d_expli = 1, _cst_expli = 2 }; enum ContactNeighborStructureType { _cnst_not_defined = 0, _cnst_regular_grid = 1, _cnst_2d_grid = 2 }; /* -------------------------------------------------------------------------- */ /* Friction */ /* -------------------------------------------------------------------------- */ typedef ID FrictionID; /* -------------------------------------------------------------------------- */ /* Ghosts handling */ /* -------------------------------------------------------------------------- */ typedef ID SynchronizerID; /// @enum CommunicatorType type of communication method to use enum CommunicatorType { _communicator_mpi, _communicator_dummy }; /// @enum SynchronizationTag type of synchronizations enum SynchronizationTag { //--- SolidMechanicsModel tags --- _gst_smm_mass, //< synchronization of the SolidMechanicsModel.mass _gst_smm_for_strain, //< synchronization of the SolidMechanicsModel.current_position _gst_smm_boundary, //< synchronization of the boundary, forces, velocities and displacement _gst_smm_uv, //< synchronization of the nodal velocities and displacement _gst_smm_res, //< synchronization of the nodal residual _gst_smm_init_mat, //< synchronization of the data to initialize materials _gst_smm_stress, //< synchronization of the stresses to compute the internal forces _gst_smmc_facets, //< synchronization of facet data to setup facet synch _gst_smmc_facets_conn, //< synchronization of facet global connectivity _gst_smmc_facets_stress, //< synchronization of facets' stress to setup facet synch _gst_smmc_damage, //< synchronization of damage //--- CohesiveElementInserter tags --- _gst_ce_inserter, //< synchronization of global nodes id of newly inserted cohesive elements //--- GroupManager tags --- _gst_gm_clusters, //< synchronization of clusters //--- HeatTransfer tags --- _gst_htm_capacity, //< synchronization of the nodal heat capacity _gst_htm_temperature, //< synchronization of the nodal temperature _gst_htm_gradient_temperature, //< synchronization of the element gradient temperature //--- LevelSet tags --- /// synchronization of the nodal level set value phi _gst_htm_phi, /// synchronization of the element gradient phi _gst_htm_gradient_phi, //--- Material non local --- _gst_mnl_for_average, //< synchronization of data to average in non local material _gst_mnl_weight, //< synchronization of data for the weight computations //--- General tags --- _gst_test, //< Test tag _gst_material_id, //< synchronization of the material ids //--- Contact & Friction --- _gst_cf_nodal, //< synchronization of disp, velo, and current position _gst_cf_incr //< synchronization of increment }; /// standard output stream operator for SynchronizationTag inline std::ostream & operator <<(std::ostream & stream, SynchronizationTag type); /// @enum GhostType type of ghost enum GhostType { _not_ghost, _ghost, _casper // not used but a real cute ghost }; /* -------------------------------------------------------------------------- */ struct GhostType_def { typedef GhostType type; static const type _begin_ = _not_ghost; static const type _end_ = _casper; }; typedef safe_enum ghost_type_t; /// standard output stream operator for GhostType inline std::ostream & operator <<(std::ostream & stream, GhostType type); /// @enum SynchronizerOperation reduce operation that the synchronizer can perform enum SynchronizerOperation { _so_sum, _so_min, _so_max, _so_null }; /* -------------------------------------------------------------------------- */ /* Global defines */ /* -------------------------------------------------------------------------- */ #define AKANTU_MIN_ALLOCATION 2000 #define AKANTU_INDENT " " #define AKANTU_INCLUDE_INLINE_IMPL /* -------------------------------------------------------------------------- */ // int 2 type construct template struct Int2Type { enum { result = d }; }; // type 2 type construct template class Type2Type { typedef T OriginalType; }; /* -------------------------------------------------------------------------- */ template struct is_scalar { enum{ value = false }; }; #define AKANTU_SPECIFY_IS_SCALAR(type) \ template<> \ struct is_scalar { \ enum { value = true }; \ } AKANTU_SPECIFY_IS_SCALAR(Real); AKANTU_SPECIFY_IS_SCALAR(UInt); AKANTU_SPECIFY_IS_SCALAR(Int); AKANTU_SPECIFY_IS_SCALAR(bool); template < typename T1, typename T2 > struct is_same { enum { value = false }; // is_same represents a bool. }; template < typename T > struct is_same { enum { value = true }; }; /* -------------------------------------------------------------------------- */ #define AKANTU_SET_MACRO(name, variable, type) \ inline void set##name (type variable) { \ this->variable = variable; \ } #define AKANTU_GET_MACRO(name, variable, type) \ inline type get##name () const { \ return variable; \ } #define AKANTU_GET_MACRO_NOT_CONST(name, variable, type) \ inline type get##name () { \ return variable; \ } #define AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, \ support, con) \ inline con Array & \ get##name (const support & el_type, \ const GhostType & ghost_type = _not_ghost) con { \ return variable(el_type, ghost_type); \ } #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType,) #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType, const) #define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType,) #define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE_CONST(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType, const) /* -------------------------------------------------------------------------- */ +/// initialize the static part of akantu void initialize(int & argc, char ** & argv); - +/// initialize the static part of akantu and read the global input_file +void initialize(const std::string & input_file, int & argc, char ** & argv); /* -------------------------------------------------------------------------- */ +/// finilize correctly akantu and clean the memory void finalize (); - /* -------------------------------------------------------------------------- */ + /* * For intel compiler annoying remark */ #if defined(__INTEL_COMPILER) /// remark #981: operands are evaluated in unspecified order #pragma warning ( disable : 981 ) /// remark #383: value copied to temporary, reference to temporary used #pragma warning ( disable : 383 ) #endif //defined(__INTEL_COMPILER) /* -------------------------------------------------------------------------- */ /* string manipulation */ /* -------------------------------------------------------------------------- */ inline std::string to_lower(const std::string & str); /* -------------------------------------------------------------------------- */ inline std::string trim(const std::string & to_trim); __END_AKANTU__ +#include "aka_fwd.hh" + +__BEGIN_AKANTU__ + +/// get access to the internal argument parser +cppargparse::ArgumentParser & getStaticArgumentParser(); + +/// get access to the internal input file parser +const Parser & getStaticParser(); + +/// get access to the user part of the internal input file parser +const ParserSection & getUserParser(); + +__END_AKANTU__ + /* -------------------------------------------------------------------------- */ // BOOST PART: TOUCH ONLY IF YOU KNOW WHAT YOU ARE DOING #include #define AKANTU_BOOST_CASE_MACRO(r,macro,type) \ case type : { macro(type); break; } #define AKANTU_BOOST_ELEMENT_SWITCH(macro1, list1) \ do { \ switch(type) { \ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, macro1, list1) \ default: { \ AKANTU_DEBUG_ERROR("Type (" << UInt(type) << ") not handled by this function"); \ } \ } \ } while(0) #define AKANTU_BOOST_ALL_ELEMENT_SWITCH(macro) \ AKANTU_BOOST_ELEMENT_SWITCH(macro, \ AKANTU_ALL_ELEMENT_TYPE) #define AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(macro) \ AKANTU_BOOST_ELEMENT_SWITCH(macro, \ AKANTU_REGULAR_ELEMENT_TYPE) #define AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(macro) \ AKANTU_BOOST_ELEMENT_SWITCH(macro, \ AKANTU_COHESIVE_ELEMENT_TYPE) #define AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(macro) \ AKANTU_BOOST_ELEMENT_SWITCH(macro, \ AKANTU_STRUCTURAL_ELEMENT_TYPE) #define AKANTU_BOOST_LIST_MACRO(r,macro,type) \ macro(type) #define AKANTU_BOOST_ELEMENT_LIST(macro, list) \ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_LIST_MACRO,macro,list) #define AKANTU_BOOST_ALL_ELEMENT_LIST(macro) \ AKANTU_BOOST_ELEMENT_LIST(macro, AKANTU_ALL_ELEMENT_TYPE) #define AKANTU_BOOST_REGULAR_ELEMENT_LIST(macro) \ AKANTU_BOOST_ELEMENT_LIST(macro, AKANTU_REGULAR_ELEMENT_TYPE) #define AKANTU_BOOST_STRUCTURAL_ELEMENT_LIST(macro) \ AKANTU_BOOST_ELEMENT_LIST(macro, AKANTU_STRUCTURAL_ELEMENT_TYPE) #define AKANTU_BOOST_COHESIVE_ELEMENT_LIST(macro) \ AKANTU_BOOST_ELEMENT_LIST(macro, AKANTU_COHESIVE_ELEMENT_TYPE) #include "aka_common_inline_impl.cc" - -#include "aka_fwd.hh" - - #endif /* __AKANTU_COMMON_HH__ */ diff --git a/src/common/aka_error.cc b/src/common/aka_error.cc index dd4c607c0..c70edd6b0 100644 --- a/src/common/aka_error.cc +++ b/src/common/aka_error.cc @@ -1,318 +1,319 @@ /** * @file aka_error.cc * * @author Nicolas Richart * * @date Mon Sep 06 00:18:58 2010 * * @brief handling of errors * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_config.hh" #include "aka_error.hh" #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #include #include #if defined(AKANTU_USE_OBSOLETE_GETTIMEOFDAY) # include #else # include #endif #ifdef AKANTU_USE_MPI # include #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ namespace debug { static void printBacktraceAndExit(int sig) { printBacktrace(sig); debugger.exit(EXIT_FAILURE); } /* ------------------------------------------------------------------------ */ void initSignalHandler() { struct sigaction action; action.sa_handler = &printBacktraceAndExit; sigemptyset(&(action.sa_mask)); action.sa_flags = SA_RESETHAND; sigaction(SIGSEGV, &action, NULL); sigaction(SIGABRT, &action, NULL); } /* ------------------------------------------------------------------------ */ std::string demangle(const char* symbol) { int status; std::string result; char * demangled_name; if ((demangled_name = abi::__cxa_demangle(symbol, NULL, 0, &status)) != NULL) { result = demangled_name; free(demangled_name); } else { result = symbol; } return result; //return symbol; } /* ------------------------------------------------------------------------ */ std::string exec(std::string cmd) { FILE* pipe = popen(cmd.c_str(), "r"); if (!pipe) return ""; char buffer[1024]; std::string result = ""; while(!feof(pipe)) { if(fgets(buffer, 128, pipe) != NULL) result += buffer; } result = result.substr(0, result.size()-1); pclose(pipe); return result; } /* ------------------------------------------------------------------------ */ void printBacktrace(__attribute__((unused)) int sig) { AKANTU_DEBUG_INFO("Caught signal " << sig << "!"); #if defined(READLINK_COMMAND) && defined(ADDR2LINE_COMMAND) std::string me = ""; char buf[1024]; /* The manpage says it won't null terminate. Let's zero the buffer. */ memset(buf, 0, sizeof(buf)); /* Note we use sizeof(buf)-1 since we may need an extra char for NUL. */ if (readlink("/proc/self/exe", buf, sizeof(buf)-1)) me = std::string(buf); std::ifstream inmaps; inmaps.open("/proc/self/maps"); std::map addr_map; std::string line; while(inmaps.good()) { std::getline(inmaps, line); std::stringstream sstr(line); size_t first = line.find('-'); std::stringstream sstra(line.substr(0,first)); size_t addr; sstra >> std::hex >> addr; std::string lib; sstr >> lib; sstr >> lib; sstr >> lib; sstr >> lib; sstr >> lib; sstr >> lib; if(lib != "" && addr_map.find(lib) == addr_map.end()) { addr_map[lib] = addr; } } if(me != "") addr_map[me] = 0; #endif const size_t max_depth = 100; size_t stack_depth; void *stack_addrs[max_depth]; char **stack_strings; size_t i; stack_depth = backtrace(stack_addrs, max_depth); stack_strings = backtrace_symbols(stack_addrs, stack_depth); std::cerr << "BACKTRACE : " << stack_depth << " stack frames." <> std::hex >> addr; std::cerr << location << " [" << call << "]"; #if defined(READLINK_COMMAND) && defined(ADDR2LINE_COMMAND) std::map::iterator it = addr_map.find(location); if(it != addr_map.end()) { std::stringstream syscom; syscom << BOOST_PP_STRINGIZE(ADDR2LINE_COMMAND) << " 0x" << std::hex << (addr - it->second) << " -i -e " << location; std::string line = exec(syscom.str()); std::cerr << " (" << line << ")" <(cout)->close(); delete cout; } } /* ------------------------------------------------------------------------ */ void Debugger::exit(int status) { + if (status != EXIT_SUCCESS) { #ifndef AKANTU_NDEBUG - int * a = NULL; - *a = 1; + int * a = NULL; + *a = 1; #endif - if (status != EXIT_SUCCESS) - akantu::debug::printBacktrace(15); #ifdef AKANTU_USE_MPI - MPI_Abort(MPI_COMM_WORLD, MPI_ERR_UNKNOWN); + MPI_Abort(MPI_COMM_WORLD, MPI_ERR_UNKNOWN); #endif - exit(status); // not called when compiled with MPI due to MPI_Abort, but - // MPI_Abort does not have the noreturn attribute + } + + std::exit(status); // not called when compiled with MPI due to MPI_Abort, but + // MPI_Abort does not have the noreturn attribute } /*------------------------------------------------------------------------- */ void Debugger::throwException(const std::string & info, const std::string & file, unsigned int line, __attribute__((unused)) bool silent, __attribute__((unused)) const std::string & location) const throw(akantu::debug::Exception){ #if !defined(AKANTU_NDEBUG) if(!silent) { printMessage("###", dblWarning, info + location); } #endif debug::Exception ex(info, file, line); throw ex; } /* ------------------------------------------------------------------------ */ void Debugger::printMessage(const std::string & prefix, const DebugLevel & level, const std::string & info) const { if(this->level >= level) { #if defined(AKANTU_USE_OBSOLETE_GETTIMEOFDAY) struct timeval time; gettimeofday(&time, NULL); double timestamp = time.tv_sec*1e6 + time.tv_usec; /*in us*/ #else struct timespec time; clock_gettime(CLOCK_REALTIME_COARSE, &time); double timestamp = time.tv_sec*1e6 + time.tv_nsec * 1e-3; /*in us*/ #endif *(cout) << parallel_context << "{" << (unsigned int)timestamp << "} " << prefix << " " << info << std::endl; } } /* ------------------------------------------------------------------------ */ void Debugger::setDebugLevel(const DebugLevel & level) { this->level = level; } /* ------------------------------------------------------------------------ */ const DebugLevel & Debugger::getDebugLevel() const { return level; } /* ------------------------------------------------------------------------ */ void Debugger::setLogFile(const std::string & filename) { if(file_open) { dynamic_cast(cout)->close(); delete cout; } std::ofstream * fileout = new std::ofstream(filename.c_str()); file_open = true; cout = fileout; } std::ostream & Debugger::getOutputStream() { return *cout; } /* ------------------------------------------------------------------------ */ void Debugger::setParallelContext(int rank, int size) { std::stringstream sstr; UInt pad = std::ceil(std::log10(size)); sstr << "<" << getpid() << ">[R" << std::setfill(' ') << std::right << std::setw(pad) << rank << "|S" << size << "] "; parallel_context = sstr.str(); } void setDebugLevel(const DebugLevel & level) { debugger.setDebugLevel(level); } const DebugLevel & getDebugLevel() { return debugger.getDebugLevel(); } } __END_AKANTU__ diff --git a/src/common/aka_error.hh b/src/common/aka_error.hh index 9b246f656..da441addb 100644 --- a/src/common/aka_error.hh +++ b/src/common/aka_error.hh @@ -1,288 +1,288 @@ /** * @file aka_error.hh * * @author Nicolas Richart * * @date Mon Jun 14 19:12:20 2010 * * @brief error management and internal exceptions * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ERROR_HH__ #define __AKANTU_ERROR_HH__ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ enum DebugLevel { dbl0 = 0, dblError = 0, dblAssert = 0, dbl1 = 1, dblException = 1, dblCritical = 1, dbl2 = 2, dblMajor = 2, dbl3 = 3, dblCall = 3, dblSecondary = 3, dblHead = 3, dbl4 = 4, dblWarning = 4, dbl5 = 5, dblInfo = 5, dbl6 = 6, dblIn = 6, dblOut = 6, dbl7 = 7, dbl8 = 8, dblTrace = 8, dbl9 = 9, dblAccessory = 9, dbl10 = 10, dblDebug = 42, dbl100 = 100, dblDump = 100, dblTest = 1337 }; /* -------------------------------------------------------------------------- */ #define AKANTU_LOCATION "(" << __func__ << "(): " << __FILE__ << ":" << __LINE__ << ")" /* -------------------------------------------------------------------------- */ namespace debug { void setDebugLevel(const DebugLevel & level); const DebugLevel & getDebugLevel(); void initSignalHandler(); std::string demangle(const char * symbol); std::string exec(std::string cmd); void printBacktrace(int sig); /* -------------------------------------------------------------------------- */ /// exception class that can be thrown by akantu class Exception : public std::exception { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: //! full constructor Exception(std::string info, std::string file, unsigned int line) : _info(info), _file(file), _line(line) { } //! destructor virtual ~Exception() throw() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual const char* what() const throw() { return _info.c_str(); } virtual const char* info() const throw() { std::stringstream stream; stream << "akantu::Exception" << " : " << _info << " [" << _file << ":" << _line << "]"; return stream.str().c_str(); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// exception description and additionals std::string _info; /// file it is thrown from std::string _file; /// ligne it is thrown from unsigned int _line; }; /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Exception & _this) { stream << _this.what(); return stream; } /* -------------------------------------------------------------------------- */ class Debugger { public: Debugger(); virtual ~Debugger(); - void exit(int status) __attribute__ ((noreturn)); + static void exit(int status) __attribute__ ((noreturn)); void throwException(const std::string & info, const std::string & file, unsigned int line, __attribute__((unused)) bool silent, __attribute__((unused)) const std::string & location) const throw(akantu::debug::Exception) __attribute__ ((noreturn)); void printMessage(const std::string & prefix, const DebugLevel & level, const std::string & info) const; void setOutStream(std::ostream & out) { cout = &out; } std::ostream & getOutStream() { return *cout; } public: void setParallelContext(int rank, int size); void setDebugLevel(const DebugLevel & level); const DebugLevel & getDebugLevel() const; void setLogFile(const std::string & filename); std::ostream & getOutputStream(); inline bool testLevel(const DebugLevel & level) const { return (this->level >= (level)); } private: std::string parallel_context; std::ostream * cout; bool file_open; DebugLevel level; }; extern Debugger debugger; } /* -------------------------------------------------------------------------- */ #define AKANTU_STRINGSTREAM_IN(_str, _sstr); \ do { \ std::stringstream _dbg_s_info; \ _dbg_s_info << _sstr; \ _str = _dbg_s_info.str(); \ } while(0) /* -------------------------------------------------------------------------- */ #define AKANTU_EXCEPTION(info) \ AKANTU_EXCEPTION_(info, false) #define AKANTU_SILENT_EXCEPTION(info) \ AKANTU_EXCEPTION_(info, true) #define AKANTU_EXCEPTION_(info, silent) \ do { \ std::stringstream _dbg_str; \ _dbg_str << info; \ std::stringstream _dbg_loc; _dbg_loc << AKANTU_LOCATION; \ ::akantu::debug::debugger.throwException(_dbg_str.str(), \ __FILE__, \ __LINE__, \ silent, \ _dbg_loc.str()); \ } while(0) /* -------------------------------------------------------------------------- */ #ifdef AKANTU_NDEBUG #define AKANTU_DEBUG_TEST(level) (false) #define AKANTU_DEBUG_LEVEL_IS_TEST() (false) #define AKANTU_DEBUG(level,info) #define AKANTU_DEBUG_(pref,level,info) #define AKANTU_DEBUG_IN() #define AKANTU_DEBUG_OUT() #define AKANTU_DEBUG_INFO(info) #define AKANTU_DEBUG_WARNING(info) #define AKANTU_DEBUG_TRACE(info) #define AKANTU_DEBUG_ASSERT(test,info) #define AKANTU_DEBUG_ERROR(info) AKANTU_EXCEPTION(info) #define AKANTU_DEBUG_TO_IMPLEMENT() ::akantu::debug::debugger.exit(EXIT_FAILURE) /* -------------------------------------------------------------------------- */ #else #define AKANTU_DEBUG(level, info) \ AKANTU_DEBUG_(" ",level, info) #define AKANTU_DEBUG_(pref, level, info) \ do { \ std::string _dbg_str; \ AKANTU_STRINGSTREAM_IN(_dbg_str, info << " " << AKANTU_LOCATION); \ ::akantu::debug::debugger.printMessage(pref, level, _dbg_str); \ } while(0) #define AKANTU_DEBUG_TEST(level) \ (::akantu::debug::debugger.testLevel(level)) #define AKANTU_DEBUG_LEVEL_IS_TEST() \ (::akantu::debug::debugger.testLevel(dblTest)) #define AKANTU_DEBUG_IN() \ AKANTU_DEBUG_("==>", ::akantu::dblIn, __func__ << "()") #define AKANTU_DEBUG_OUT() \ AKANTU_DEBUG_("<==", ::akantu::dblOut, __func__ << "()") #define AKANTU_DEBUG_INFO(info) \ AKANTU_DEBUG_("---", ::akantu::dblInfo, info) #define AKANTU_DEBUG_WARNING(info) \ AKANTU_DEBUG_("/!\\", ::akantu::dblWarning, info) #define AKANTU_DEBUG_TRACE(info) \ AKANTU_DEBUG_(">>>", ::akantu::dblTrace, info) #define AKANTU_DEBUG_ASSERT(test,info) \ do { \ if (!(test)) { \ AKANTU_DEBUG_("!!! ", ::akantu::dblAssert, "assert [" << #test << "] " \ << info); \ ::akantu::debug::debugger.exit(EXIT_FAILURE); \ } \ } while(0) #define AKANTU_DEBUG_ERROR(info) \ do { \ AKANTU_DEBUG_("!!! ", ::akantu::dblError, info); \ ::akantu::debug::debugger.exit(EXIT_FAILURE); \ } while(0) #define AKANTU_DEBUG_TO_IMPLEMENT() \ AKANTU_DEBUG_ERROR(__func__ << " : not implemented yet !") #endif // AKANTU_NDEBUG /* -------------------------------------------------------------------------- */ } #endif /* __AKANTU_ERROR_HH__ */ diff --git a/src/common/aka_extern.cc b/src/common/aka_extern.cc index 6bce20367..8adc702cc 100644 --- a/src/common/aka_extern.cc +++ b/src/common/aka_extern.cc @@ -1,91 +1,95 @@ /** * @file aka_extern.cc * * @author Nicolas Richart * + * @date Mon Jun 14 19:12:20 2010 * * @brief initialisation of all global variables * to insure the order of creation * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_array.hh" #include "aka_math.hh" #include "aka_random_generator.hh" #include "parser.hh" +#include "cppargparse.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #if defined(AKANTU_DEBUG_TOOLS) # include "aka_debug_tools.hh" #endif __BEGIN_AKANTU__ /** \todo write function to get this * values from the environment or a config file */ /* -------------------------------------------------------------------------- */ /* error.hpp variables */ /* -------------------------------------------------------------------------- */ namespace debug { /// standard output for debug messages std::ostream *_akantu_debug_cout = &std::cerr; /// standard output for normal messages std::ostream & _akantu_cout = std::cout; - /// debug level - DebugLevel _debug_level = dblInfo; - /// parallel context used in debug messages std::string _parallel_context = ""; Debugger debugger; #if defined(AKANTU_DEBUG_TOOLS) DebugElementManager element_manager; #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::parser_permissive = false; Real Math::tolerance = std::numeric_limits::epsilon(); const UInt _all_dimensions = UInt(-1); const Array empty_filter(0, 1, "empty_filter"); template<> long int RandGenerator::_seed = 0; template<> long int RandGenerator::_seed = 0; // useless just defined due to a template instantiation template<> long int RandGenerator::_seed = 0; template<> long int RandGenerator::_seed = 0; template<> long int Rand48Generator::_seed = 0; /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/common/aka_fwd.hh b/src/common/aka_fwd.hh index 0eb2ca45b..5491868b7 100644 --- a/src/common/aka_fwd.hh +++ b/src/common/aka_fwd.hh @@ -1,51 +1,61 @@ /** * @file aka_fwd.hh * @author Nicolas Richart * @author Alejandro M. Aragón * @date Thu Jan 3 15:15:00 2013 * * @brief File containing forward declarations in akantu * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_FWD_HH__ #define __AKANTU_FWD_HH__ -namespace akantu { +namespace cppargparse { + class ArgumentParser; +} + +namespace akantu { template class Matrix; template class Vector; template class Tensor3; template::value > class Array; template class SpatialGrid; // Model element template class ModelElement; extern const Array empty_filter; + class Parser; + class ParserSection; + + extern Parser static_parser; + + extern cppargparse::ArgumentParser static_argparser; } #endif /* __AKANTU_FWD_HH__ */ diff --git a/src/fem/fem.hh b/src/fem/fem.hh index 86084e006..36debea3e 100644 --- a/src/fem/fem.hh +++ b/src/fem/fem.hh @@ -1,365 +1,365 @@ /** * @file fem.hh * * @author Guillaume Anciaux * @author Nicolas Richart * * @date Tue Jul 20 23:40:43 2010 * * @brief FEM class * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_FEM_HH__ #define __AKANTU_FEM_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "mesh.hh" #include "element_class.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class Integrator; class ShapeFunctions; } __BEGIN_AKANTU__ class QuadraturePoint : public Element { public: typedef Vector position_type; public: QuadraturePoint(ElementType type = _not_defined, UInt element = 0, UInt num_point = 0, GhostType ghost_type = _not_ghost) : Element(type, element, ghost_type), num_point(num_point), global_num(0), position((Real *)NULL, 0) { }; QuadraturePoint(UInt element, UInt num_point, UInt global_num, const position_type & position, ElementType type, GhostType ghost_type = _not_ghost) : Element(type, element, ghost_type), num_point(num_point), global_num(global_num), position((Real *)NULL, 0) { this->position.shallowCopy(position); }; QuadraturePoint(const QuadraturePoint & quad) : Element(quad), num_point(quad.num_point), global_num(quad.global_num), position((Real *) NULL, 0) { position.shallowCopy(quad.position); }; inline QuadraturePoint & operator=(const QuadraturePoint & q) { if(this != &q) { element = q.element; type = q.type; ghost_type = q.ghost_type; num_point = q.num_point; global_num = q.global_num; position.shallowCopy(q.position); } return *this; } AKANTU_GET_MACRO(Position, position, const position_type &); void setPosition(const position_type & position) { this->position.shallowCopy(position); } /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "QuadraturePoint ["; Element::printself(stream, 0); stream << ", " << num_point << "]"; } public: UInt num_point; UInt global_num; private: position_type position; }; /** * The generic FEM class derived in a FEMTemplate class containing the * shape functions and the integration method */ class FEM : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FEM(Mesh & mesh, UInt spatial_dimension = _all_dimensions, ID id = "fem", MemoryID memory_id = 0); virtual ~FEM(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// build the profile of the sparse matrix corresponding to the mesh void initSparseMatrixProfile(SparseMatrixType sparse_matrix_type = _unsymmetric); /// pre-compute all the shape functions, their derivatives and the jacobians virtual void initShapeFunctions(const GhostType & ghost_type = _not_ghost) = 0; /// extract the nodal values and store them per element template static void extractNodalToElementField(const Mesh & mesh, const Array & nodal_f, Array & elemental_f, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter); /// filter a field template static void filterElementalData(const Mesh & mesh, const Array & quad_f, Array & filtered_f, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter); /* ------------------------------------------------------------------------ */ /* Integration method bridges */ /* ------------------------------------------------------------------------ */ /// integrate f for all elements of type "type" virtual void integrate(const Array & f, Array &intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter) const = 0; /// integrate a scalar value on all elements of type "type" virtual Real integrate(const Array & f, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter) const = 0; /// integrate f for all quadrature points of type "type" virtual void integrateOnQuadraturePoints(const Array & f, Array &intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter) const = 0; /// integrate one element scalar value on all elements of type "type" virtual Real integrate(const Vector & f, const ElementType & type, UInt index, const GhostType & ghost_type = _not_ghost) const = 0; /* ------------------------------------------------------------------------ */ /* compatibility with old FEM fashion */ /* ------------------------------------------------------------------------ */ /// get the number of quadrature points virtual UInt getNbQuadraturePoints(const ElementType & type, const GhostType & ghost_type = _not_ghost) const = 0; /// get the precomputed shapes const virtual Array & getShapes(const ElementType & type, - const GhostType & ghost_type = _not_ghost) const = 0; + const GhostType & ghost_type = _not_ghost) const = 0; /// get the derivatives of shapes const virtual Array & getShapesDerivatives(const ElementType & type, - const GhostType & ghost_type = _not_ghost, - UInt id = 0) const = 0; + const GhostType & ghost_type = _not_ghost, + UInt id = 0) const = 0; /// get quadrature points const virtual Matrix & getQuadraturePoints(const ElementType & type, - const GhostType & ghost_type = _not_ghost) const = 0; + const GhostType & ghost_type = _not_ghost) const = 0; /* ------------------------------------------------------------------------ */ /* Shape method bridges */ /* ------------------------------------------------------------------------ */ virtual void gradientOnQuadraturePoints(const Array &u, Array &nablauq, const UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter) const = 0; virtual void interpolateOnQuadraturePoints(const Array &u, Array &uq, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter) const = 0; virtual void interpolateOnQuadraturePoints(const Array & u, ByElementTypeReal & uq, const ByElementTypeUInt * filter_elements = NULL) const = 0; /* ------------------------------------------------------------------------ */ /* Other methods */ /* ------------------------------------------------------------------------ */ /// pre-compute normals on control points virtual void computeNormalsOnControlPoints(const GhostType & ghost_type = _not_ghost) = 0; /// pre-compute normals on control points virtual void computeNormalsOnControlPoints(__attribute__((unused)) const Array & field, __attribute__((unused)) const GhostType & ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// pre-compute normals on control points virtual void computeNormalsOnControlPoints(__attribute__((unused)) const Array & field, __attribute__((unused)) Array & normal, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type = _not_ghost) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// assemble vectors void assembleArray(const Array & elementary_vect, Array & nodal_values, const Array & equation_number, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter, Real scale_factor = 1) const; /// assemble matrix in the complete sparse matrix void assembleMatrix(const Array & elementary_mat, SparseMatrix & matrix, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter) const; /// assemble a field as a lumped matrix (ex. rho in lumped mass) virtual void assembleFieldLumped(__attribute__ ((unused)) const Array & field_1, __attribute__ ((unused)) UInt nb_degree_of_freedom, __attribute__ ((unused)) Array & lumped, __attribute__ ((unused)) const Array & equation_number, __attribute__ ((unused)) ElementType type, __attribute__ ((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); }; /// assemble a field as a matrix (ex. rho to mass matrix) virtual void assembleFieldMatrix(__attribute__ ((unused)) const Array & field_1, __attribute__ ((unused)) UInt nb_degree_of_freedom, __attribute__ ((unused)) SparseMatrix & matrix, __attribute__ ((unused)) ElementType type, __attribute__ ((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; private: /// initialise the class void init(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(ElementDimension, element_dimension, UInt); /// get the mesh contained in the fem object inline Mesh & getMesh() const; /// get the in-radius of an element static inline Real getElementInradius(const Matrix & coord, const ElementType & type); /// get the normals on quadrature points AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NormalsOnQuadPoints, normals_on_quad_points, Real); /// get cohesive element type for a given facet type static inline ElementType getCohesiveElementType(const ElementType & type_facet); virtual const ShapeFunctions & getShapeFunctionsInterface() const = 0; virtual const Integrator & getIntegratorInterface() const = 0; static inline InterpolationType getInterpolationType(const ElementType & el_type); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// spatial dimension of the problem UInt element_dimension; /// the mesh on which all computation are made Mesh & mesh; /// normals at quadrature points ByElementTypeReal normals_on_quad_points; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "fem_inline_impl.cc" #endif /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const FEM & _this) { _this.printself(stream); return stream; } /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const QuadraturePoint & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #include "fem_template.hh" #endif /* __AKANTU_FEM_HH__ */ diff --git a/src/fem/group_manager.cc b/src/fem/group_manager.cc index cf4f6751e..74014bbf0 100644 --- a/src/fem/group_manager.cc +++ b/src/fem/group_manager.cc @@ -1,806 +1,807 @@ /** * @file group_manager.cc * * @author Dana Christen * @author Nicolas Richart * @author David Kammer * @author Marco Vocialta * * @date Wed Mar 06 09:30:00 2013 * * @brief Stores information about ElementGroup and NodeGroup * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "group_manager.hh" #include "mesh.hh" #include "aka_csr.hh" #include "mesh_utils.hh" #include "element_group.hh" #include "node_group.hh" #include "data_accessor.hh" #include "distributed_synchronizer.hh" /* -------------------------------------------------------------------------- */ #include #include #include #include #include #include /* -------------------------------------------------------------------------- */ __BEGIN_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() { ElementGroups::iterator eit = element_groups.begin(); ElementGroups::iterator eend = element_groups.end(); for(; eit != eend ; ++eit) delete (eit->second); NodeGroups::iterator nit = node_groups.begin(); NodeGroups::iterator 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(); NodeGroups::iterator 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 << "_nodes"); } NodeGroup * node_group = new NodeGroup(group_name, id + ":" + group_name + "_node_group", memory_id); node_groups[group_name] = node_group; AKANTU_DEBUG_OUT(); return *node_group; } /* -------------------------------------------------------------------------- */ template 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); ElementGroups::iterator 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); } ElementGroup * element_group = new ElementGroup(group_name, mesh, new_node_group, dimension, id + ":" + group_name + "_element_group", memory_id); node_groups[group_name + "_nodes"] = &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(); ElementGroups::iterator eit = element_groups.find(group_name); ElementGroups::iterator 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(); ElementGroups::iterator eit = element_groups.begin(); ElementGroups::iterator eend = element_groups.end(); for(; eit != eend ; ++eit) { this->destroyElementGroup(eit->first, destroy_node_groups); } 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 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 { typedef std::set< std::pair > DistantIDs; public: ClusterSynchronizer(GroupManager & group_manager, UInt element_dimension, std::string cluster_name_prefix, ByElementTypeUInt & element_to_fragment, DistributedSynchronizer & distributed_synchronizer, UInt nb_cluster) : group_manager(group_manager), element_dimension(element_dimension), cluster_name_prefix(cluster_name_prefix), element_to_fragment(element_to_fragment), distributed_synchronizer(distributed_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 nb_cluster_per_proc(nb_proc); nb_cluster_per_proc(rank) = nb_cluster; comm.allGather(nb_cluster_per_proc.storage(), 1); 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 distributed_synchronizer.computeBufferSize(*this, _gst_gm_clusters); distributed_synchronizer.asynchronousSynchronize(*this, _gst_gm_clusters); distributed_synchronizer.waitEndSynchronize(*this, _gst_gm_clusters); /// count total number of pairs Array nb_pairs(nb_proc); nb_pairs(rank) = distant_ids.size(); comm.allGather(nb_pairs.storage(), 1); 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 total_pairs(total_nb_pairs, 2); DistantIDs::iterator ids_it = distant_ids.begin(); DistantIDs::iterator ids_end = distant_ids.end(); for (; ids_it != ids_end; ++ids_it, ++local_pair_index) { total_pairs(local_pair_index, 0) = ids_it->first; total_pairs(local_pair_index, 1) = ids_it->second; } /// communicate pairs to all processors nb_pairs *= 2; comm.allGatherV(total_pairs.storage(), nb_pairs.storage()); /// renumber clusters Array::iterator > pairs_it = total_pairs.begin(2); Array::iterator > pairs_end = total_pairs.end(2); /// generate fragment list std::vector< std::set > global_clusters; UInt total_nb_cluster = 0; Array is_fragment_in_cluster(global_nb_fragment, 1, false); std::queue fragment_check_list; while (total_pairs.getSize() != 0) { /// create a new cluster ++total_nb_cluster; global_clusters.resize(total_nb_cluster); std::set & 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 & 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::iterator it = global_clusters[c].begin(); std::set::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; GroupManager::element_group_iterator 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 getNbDataForElements(const Array & elements, SynchronizationTag tag) const { if (tag == _gst_gm_clusters) return elements.getSize() * sizeof(UInt); return 0; } inline void packElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag) const { if (tag != _gst_gm_clusters) return; Array::const_iterator<> el_it = elements.begin(); Array::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 unpackElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag) { if (tag != _gst_gm_clusters) return; Array::const_iterator<> el_it = elements.begin(); Array::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; ByElementTypeUInt & element_to_fragment; DistributedSynchronizer & distributed_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, DistributedSynchronizer * distributed_synchronizer, Mesh * mesh_facets) { AKANTU_DEBUG_IN(); UInt nb_proc = StaticCommunicator::getStaticCommunicator().getNbProc(); std::string tmp_cluster_name_prefix = cluster_name_prefix; ByElementTypeUInt * element_to_fragment = NULL; if (nb_proc > 1 && distributed_synchronizer) { element_to_fragment = new ByElementTypeUInt; mesh.initByElementTypeArray(*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, distributed_synchronizer); } std::list unseen_elements; Element el; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; 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); for (UInt e = 0; e < nb_element; ++e) { el.element = e; if (filter(el)) unseen_elements.push_back(el); } } } Array checked_node(mesh.getNbNodes(), 1, false); UInt nb_cluster = 0; /// keep looping until all elements are seen while(!unseen_elements.empty()) { /// create a new cluster std::stringstream sstr; sstr << tmp_cluster_name_prefix << "_" << nb_cluster; ElementGroup & cluster = createElementGroup(sstr.str(), element_dimension, true); ++nb_cluster; /// initialize the queue of elements to check in the current cluster std::list::iterator uns_it = unseen_elements.begin(); Element uns_el = *uns_it; unseen_elements.erase(uns_it); // point element are cluster by themself if(element_dimension == 0) { cluster.add(uns_el); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(el.type); Vector 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_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 && distributed_synchronizer) (*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_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 & 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]; if (check_el == ElementNull || check_el == el) continue; std::list::iterator it_clus = std::find(unseen_elements.begin(), unseen_elements.end(), check_el); /// if neighbor not seen yet, add it to check list and /// remove it from unseen elements if(it_clus != unseen_elements.end()) { unseen_elements.erase(it_clus); element_to_add.push(check_el); } } } UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(el.type); Vector 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); checked_node(node) = true; } } } } if (nb_proc > 1 && distributed_synchronizer) { ClusterSynchronizer cluster_synchronizer(*this, element_dimension, cluster_name_prefix, *element_to_fragment, *distributed_synchronizer, nb_cluster); nb_cluster = cluster_synchronizer.synchronize(); delete element_to_fragment; } if (mesh_facets_created) delete mesh_facets; AKANTU_DEBUG_OUT(); return nb_cluster; } /* -------------------------------------------------------------------------- */ template void GroupManager::createGroupsFromMeshData(const std::string & dataset_name) { std::set group_names; const ByElementTypeArray & datas = mesh.getData(dataset_name); typedef typename ByElementTypeArray::type_iterator type_iterator; 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 & 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!"); for(UInt e(0); e < nb_element; ++e) { std::stringstream sstr; sstr << dataset(e); group_names.insert(sstr.str()); } } } /// @todo sharing the group names in parallel to avoid trouble with groups /// present only on a sub set of processors std::set::iterator git = group_names.begin(); std::set::iterator gend = group_names.end(); for (;git != gend; ++git) createElementGroup(*git, _all_dimensions); 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 & 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::const_iterator< Vector > 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); const Vector & connect = *cit; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connect[n]; group.addNode(node); } } } } git = group_names.begin(); for (;git != gend; ++git) { getElementGroup(*git).getNodeGroup().removeDuplicate(); getElementGroup(*git).optimize(); } } template void GroupManager::createGroupsFromMeshData(const std::string & dataset_name); template void GroupManager::createGroupsFromMeshData(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); CSR node_to_elem; MeshUtils::buildNode2Elements(mesh, node_to_elem, _all_dimensions); std::set seen; Array::const_iterator<> itn = node_group.begin(); Array::const_iterator<> endn = node_group.end(); for (;itn != endn; ++itn) { CSR::iterator ite = node_to_elem.begin(*itn); CSR::iterator ende = node_to_elem.end(*itn); for (;ite != ende; ++ite) { const Element & elem = *ite; if(dimension != _all_dimensions && dimension != Mesh::getSpatialDimension(elem.type)) continue; if(seen.find(elem) != seen.end()) continue; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(elem.type); Array::const_iterator< Vector > conn_it = mesh.getConnectivity(elem.type, elem.ghost_type).begin(nb_nodes_per_element); const Vector & conn = conn_it[elem.element]; UInt count = 0; for (UInt n = 0; n < conn.size(); ++n) { count += (node_group.getNodes().find(conn(n)) != -1 ? 1 : 0); } if(count == nb_nodes_per_element) group.add(elem); seen.insert(elem); } } group.optimize(); } /* -------------------------------------------------------------------------- */ 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 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; } __END_AKANTU__ diff --git a/src/fem/mesh.hh b/src/fem/mesh.hh index 31e4d1aea..1e56b4d12 100644 --- a/src/fem/mesh.hh +++ b/src/fem/mesh.hh @@ -1,667 +1,668 @@ /** * @file mesh.hh * * @author Guillaume Anciaux * @author Marco Vocialta * @author Nicolas Richart * @author Dana Christen * @author David Kammer * * @date Fri Jun 18 11:47:19 2010 * * @brief the class representing the meshes * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_HH__ #define __AKANTU_MESH_HH__ /* -------------------------------------------------------------------------- */ #include "aka_config.hh" #include "aka_common.hh" #include "aka_memory.hh" #include "aka_array.hh" #include "element_class.hh" #include "by_element_type.hh" #include "aka_event_handler.hh" #include "group_manager.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Element */ /* -------------------------------------------------------------------------- */ class Element; extern const Element ElementNull; class Element { public: Element(ElementType type = _not_defined, UInt element = 0, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) : type(type), element(element), ghost_type(ghost_type), kind(kind) {}; Element(const Element & element) { this->type = element.type; this->element = element.element; this->ghost_type = element.ghost_type; this->kind = element.kind; } inline bool operator==(const Element & elem) const { return ((element == elem.element) && (type == elem.type) && (ghost_type == elem.ghost_type) && (kind == elem.kind)); } inline bool operator!=(const Element & elem) const { return ((element != elem.element) || (type != elem.type) || (ghost_type != elem.ghost_type) || (kind != elem.kind)); } bool operator<(const Element& rhs) const { bool res = (rhs == ElementNull) || ((this->kind < rhs.kind) || ((this->kind == rhs.kind) && ((this->ghost_type < rhs.ghost_type) || ((this->ghost_type == rhs.ghost_type) && ((this->type < rhs.type) || ((this->type == rhs.type) && (this->element < rhs.element))))))); return res; } virtual ~Element() {}; /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; public: ElementType type; UInt element; GhostType ghost_type; ElementKind kind; }; struct CompElementLess { bool operator() (const Element& lhs, const Element& rhs) const { return lhs < rhs; } }; __END_AKANTU__ #include "mesh_data.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Mesh modifications events */ /* -------------------------------------------------------------------------- */ template class MeshEvent { public: virtual ~MeshEvent() {} const Array & getList() const { return list; } Array & getList() { return list; } protected: Array list; }; class Mesh; class NewNodesEvent : public MeshEvent { public: virtual ~NewNodesEvent() {}; }; class RemovedNodesEvent : public MeshEvent { public: virtual ~RemovedNodesEvent() {}; inline RemovedNodesEvent(const Mesh & mesh); AKANTU_GET_MACRO_NOT_CONST(NewNumbering, new_numbering, Array &); AKANTU_GET_MACRO(NewNumbering, new_numbering, const Array &); private: Array new_numbering; }; class NewElementsEvent : public MeshEvent { public: virtual ~NewElementsEvent() {}; }; class RemovedElementsEvent : public MeshEvent { public: virtual ~RemovedElementsEvent() {}; inline RemovedElementsEvent(const Mesh & mesh); AKANTU_GET_MACRO(NewNumbering, new_numbering, const ByElementTypeUInt &); AKANTU_GET_MACRO_NOT_CONST(NewNumbering, new_numbering, ByElementTypeUInt &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(NewNumbering, new_numbering, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NewNumbering, new_numbering, UInt); protected: ByElementTypeUInt new_numbering; }; /* -------------------------------------------------------------------------- */ class MeshEventHandler { public: virtual ~MeshEventHandler() {}; /* ------------------------------------------------------------------------ */ /* Internal code */ /* ------------------------------------------------------------------------ */ private: inline void sendEvent(const NewNodesEvent & event) { onNodesAdded (event.getList(), event); } inline void sendEvent(const RemovedNodesEvent & event) { onNodesRemoved(event.getList(), event.getNewNumbering(), event); } inline void sendEvent(const NewElementsEvent & event) { onElementsAdded (event.getList(), event); } inline void sendEvent(const RemovedElementsEvent & event) { onElementsRemoved(event.getList(), event.getNewNumbering(), event); } template friend class EventHandlerManager; /* ------------------------------------------------------------------------ */ /* Interface */ /* ------------------------------------------------------------------------ */ public: virtual void onNodesAdded (__attribute__((unused)) const Array & nodes_list, __attribute__((unused)) const NewNodesEvent & event) { } virtual void onNodesRemoved(__attribute__((unused)) const Array & nodes_list, __attribute__((unused)) const Array & new_numbering, __attribute__((unused)) const RemovedNodesEvent & event) { } virtual void onElementsAdded (__attribute__((unused)) const Array & elements_list, __attribute__((unused)) const NewElementsEvent & event) { } virtual void onElementsRemoved(__attribute__((unused)) const Array & elements_list, __attribute__((unused)) const ByElementTypeUInt & new_numbering, __attribute__((unused)) const RemovedElementsEvent & event) { } }; /* -------------------------------------------------------------------------- */ /* Mesh */ /* -------------------------------------------------------------------------- */ /** * @class Mesh this contain the coordinates of the nodes in the Mesh.nodes * Array, and the connectivity. The connectivity are stored in by element * types. * * To know all the element types present in a mesh you can get the * Mesh::ConnectivityTypeList * * In order to loop on all element you have to loop on all types like this : * @code{.cpp} Mesh::type_iterator it = mesh.firstType(dim, ghost_type); Mesh::type_iterator end = mesh.lastType(dim, ghost_type); for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it); const Array & conn = mesh.getConnectivity(*it); for(UInt e = 0; e < nb_element; ++e) { ... } } @endcode */ class Mesh : protected Memory, public EventHandlerManager, public GroupManager { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /// constructor that create nodes coordinates array Mesh(UInt spatial_dimension, const ID & id = "mesh", const MemoryID & memory_id = 0); /// constructor that use an existing nodes coordinates array, by knowing its ID Mesh(UInt spatial_dimension, const ID & nodes_id, const ID & id, const MemoryID & memory_id = 0); /** * constructor that use an existing nodes coordinates * array, by getting the vector of coordinates */ Mesh(UInt spatial_dimension, Array & nodes, const ID & id = "mesh", const MemoryID & memory_id = 0); virtual ~Mesh(); /// @typedef ConnectivityTypeList list of the types present in a Mesh typedef std::set ConnectivityTypeList; /// read the mesh from a file void read (const std::string & filename, const MeshIOType & mesh_io_type = _miot_auto); /// write the mesh to a file void write(const std::string & filename, const MeshIOType & mesh_io_type = _miot_auto); private: /// initialize the connectivity to NULL and other stuff void init(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /// function that computes the bounding box (fills xmin, xmax) void computeBoundingBox(); #ifdef AKANTU_CORE_CXX11 /// translate the mesh by the given amount in x[, y[, z]] directions template void translate(Args... params); #endif /// init a by-element-type real vector with provided ids template void initByElementTypeArray(ByElementTypeArray & v, UInt nb_component, UInt spatial_dimension, const bool & flag_nb_node_per_elem_multiply = false, ElementKind element_kind = _ek_regular, bool size_to_nb_element = false) const; /// @todo: think about nicer way to do it template void initByElementTypeArray(ByElementTypeArray & v, UInt nb_component, UInt spatial_dimension, GhostType ghost_type, const bool & flag_nb_node_per_elem_multiply = false, ElementKind element_kind = _ek_regular, bool size_to_nb_element = false) const; /// @todo: think about nicer way to do it /// extract coordinates of nodes from an element template inline void extractNodalValuesFromElement(const Array & nodal_values, T * elemental_values, UInt * connectivity, UInt n_nodes, UInt nb_degree_of_freedom) const; /// extract coordinates of nodes from a reversed element inline void extractNodalCoordinatesFromPBCElement(Real * local_coords, UInt * connectivity, UInt n_nodes); /// convert a element to a linearized element inline UInt elementToLinearized(const Element & elem) const; /// convert a linearized element to an element inline Element linearizedToElement (UInt linearized_element) const; /// update the types offsets array for the conversions inline void updateTypesOffsets(const GhostType & ghost_type); /// add a Array of connectivity for the type . inline void addConnectivityType(const ElementType & type, const GhostType & ghost_type = _not_ghost); /* ------------------------------------------------------------------------ */ template inline void sendEvent(Event & event) { // if(event.getList().getSize() != 0) EventHandlerManager::sendEvent(event); } /* ------------------------------------------------------------------------ */ template inline void removeNodesFromArray(Array & vect, const Array & new_numbering); /// initialize normals void initNormals(); /// init facets' mesh Mesh & initMeshFacets(const ID & id = "mesh_facets"); /// define parent mesh void defineMeshParent(const Mesh & mesh); /// get global connectivity array void getGlobalConnectivity(Array & global_connectivity, ElementType type, GhostType ghost_type); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the id of the mesh AKANTU_GET_MACRO(ID, Memory::id, const ID &); /// get the spatial dimension of the mesh = number of component of the coordinates AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); /// get the nodes Array aka coordinates AKANTU_GET_MACRO(Nodes, *nodes, const Array &); AKANTU_GET_MACRO_NOT_CONST(Nodes, *nodes, Array &); /// get the normals for the elements AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Normals, normals, Real); /// get the number of nodes AKANTU_GET_MACRO(NbNodes, nodes->getSize(), UInt); /// get the Array of global ids of the nodes (only used in parallel) AKANTU_GET_MACRO(GlobalNodesIds, *nodes_global_ids, const Array &); /// get the global id of a node inline UInt getNodeGlobalId(UInt local_id) const; /// get the global number of nodes inline UInt getNbGlobalNodes() const; /// get the nodes type Array AKANTU_GET_MACRO(NodesType, nodes_type, const Array &); protected: AKANTU_GET_MACRO_NOT_CONST(NodesType, nodes_type, Array &); public: inline Int getNodeType(UInt local_id) const; /// say if a node is a pure ghost node inline bool isPureGhostNode(UInt n) const; /// say if a node is pur local or master node inline bool isLocalOrMasterNode(UInt n) const; inline bool isLocalNode(UInt n) const; inline bool isMasterNode(UInt n) const; inline bool isSlaveNode(UInt n) const; AKANTU_GET_MACRO(XMin, lower_bounds[0], Real); AKANTU_GET_MACRO(YMin, lower_bounds[1], Real); AKANTU_GET_MACRO(ZMin, lower_bounds[2], Real); AKANTU_GET_MACRO(XMax, upper_bounds[0], Real); AKANTU_GET_MACRO(YMax, upper_bounds[1], Real); AKANTU_GET_MACRO(ZMax, upper_bounds[2], Real); inline void getLowerBounds(Real * lower) const; inline void getUpperBounds(Real * upper) const; inline void getLocalLowerBounds(Real * lower) const; inline void getLocalUpperBounds(Real * upper) const; /// get the connectivity Array for a given type AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Connectivity, connectivities, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Connectivity, connectivities, UInt); AKANTU_GET_MACRO(Connectivities, connectivities, const ByElementTypeArray &); /// get the number of element of a type in the mesh inline UInt getNbElement(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /// get the number of element for a given ghost_type and a given dimension inline UInt getNbElement(const UInt spatial_dimension = _all_dimensions, const GhostType & ghost_type = _not_ghost, const ElementKind & kind = _ek_not_defined) const; /// get the connectivity list either for the elements or the ghost elements inline const ConnectivityTypeList & getConnectivityTypeList(const GhostType & ghost_type = _not_ghost) const; /// compute the barycenter of a given element inline void getBarycenter(UInt element, const ElementType & type, Real * barycenter, GhostType ghost_type = _not_ghost) const; inline void getBarycenter(const Element & element, Vector & barycenter) const; /// get the element connected to a subelement const Array< std::vector > & getElementToSubelement(const ElementType & el_type, const GhostType & ghost_type = _not_ghost) const; /// get the element connected to a subelement Array< std::vector > & getElementToSubelement(const ElementType & el_type, const GhostType & ghost_type = _not_ghost); /// get the subelement connected to an element const Array & getSubelementToElement(const ElementType & el_type, const GhostType & ghost_type = _not_ghost) const; /// get the subelement connected to an element Array & getSubelementToElement(const ElementType & el_type, const GhostType & ghost_type = _not_ghost); /// get a name field associated to the mesh template inline const Array & getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type = _not_ghost) const; /// get a name field associated to the mesh template inline Array & getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type = _not_ghost); /// get a name field associated to the mesh template inline const ByElementTypeArray & getData(const std::string & data_name) const; /// get a name field associated to the mesh template inline ByElementTypeArray & getData(const std::string & data_name); /// templated getter returning the pointer to data in MeshData (modifiable) template inline Array * getDataPointer(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type = _not_ghost, UInt nb_component = 1, - bool size_to_nb_element = true); + bool size_to_nb_element = true, + bool resize_with_parent = false); /// Facets mesh accessor AKANTU_GET_MACRO(MeshFacets, *mesh_facets, const Mesh &); AKANTU_GET_MACRO_NOT_CONST(MeshFacets, *mesh_facets, Mesh &); /// Parent mesh accessor AKANTU_GET_MACRO(MeshParent, *mesh_parent, const Mesh &); inline bool isMeshFacets() const {return is_mesh_facets;} /* ------------------------------------------------------------------------ */ /* Wrappers on ElementClass functions */ /* ------------------------------------------------------------------------ */ public: /// get the number of nodes per element for a given element type static inline UInt getNbNodesPerElement(const ElementType & type); /// get the number of nodes per element for a given element type considered as /// a first order element static inline ElementType getP1ElementType(const ElementType & type); /// get the kind of the element type static inline ElementKind getKind(const ElementType & type); /// get spatial dimension of a type of element static inline UInt getSpatialDimension(const ElementType & type); /// get number of facets of a given element type static inline UInt getNbFacetsPerElement(const ElementType & type); /// get local connectivity of a facet for a given facet type static inline MatrixProxy getFacetLocalConnectivity(const ElementType & type); /// get connectivity of facets for a given element inline Matrix getFacetConnectivity(UInt element, const ElementType & type, const GhostType & ghost_type) const; /// get the type of the surface element associated to a given element static inline ElementType getFacetType(const ElementType & type); /* ------------------------------------------------------------------------ */ /* Element type Iterator */ /* ------------------------------------------------------------------------ */ typedef ByElementTypeArray::type_iterator type_iterator; inline type_iterator firstType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) const { return connectivities.firstType(dim, ghost_type, kind); } inline type_iterator lastType(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_regular) const { return connectivities.lastType(dim, ghost_type, kind); } /* ------------------------------------------------------------------------ */ /* Private methods for friends */ /* ------------------------------------------------------------------------ */ private: friend class MeshIOMSH; friend class MeshIOMSHStruct; friend class MeshIODiana; friend class MeshUtils; friend class DistributedSynchronizer; template friend class SpatialGrid; #if defined(AKANTU_COHESIVE_ELEMENT) friend class CohesiveElementInserter; #endif AKANTU_GET_MACRO(NodesPointer, nodes, Array *); /// get a pointer to the nodes_global_ids Array and create it if necessary inline Array * getNodesGlobalIdsPointer(); /// get a pointer to the nodes_type Array and create it if necessary inline Array * getNodesTypePointer(); /// get a pointer to the connectivity Array for the given type and create it if necessary inline Array * getConnectivityPointer(const ElementType & type, const GhostType & ghost_type = _not_ghost); /// get a pointer to the element_to_subelement Array for the given type and create it if necessary inline Array< std::vector > * getElementToSubelementPointer(const ElementType & type, const GhostType & ghost_type = _not_ghost); /// get a pointer to the subelement_to_element Array for the given type and create it if necessary inline Array * getSubelementToElementPointer(const ElementType & type, const GhostType & ghost_type = _not_ghost); AKANTU_GET_MACRO_NOT_CONST(MeshData, mesh_data, MeshData &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// array of the nodes coordinates Array * nodes; /// global node ids Array * nodes_global_ids; /// node type, -3 pure ghost, -2 master for the node, -1 normal node, i in /// [0-N] slave node and master is proc i Array nodes_type; /// global number of nodes; UInt nb_global_nodes; /// boolean to know if the nodes have to be deleted with the mesh or not bool created_nodes; /// all class of elements present in this mesh (for heterogenous meshes) ByElementTypeUInt connectivities; /// map to normals for all class of elements present in this mesh ByElementTypeReal normals; /// list of all existing types in the mesh ConnectivityTypeList type_set; /// the spatial dimension of this mesh UInt spatial_dimension; /// types offsets Array types_offsets; /// list of all existing types in the mesh ConnectivityTypeList ghost_type_set; /// ghost types offsets Array ghost_types_offsets; /// min of coordinates Real lower_bounds[3]; /// max of coordinates Real upper_bounds[3]; /// size covered by the mesh on each direction Real size[3]; /// local min of coordinates Real local_lower_bounds[3]; /// local max of coordinates Real local_upper_bounds[3]; /// Extra data loaded from the mesh file MeshData mesh_data; /// facets' mesh Mesh * mesh_facets; /// parent mesh (this is set for mesh_facets meshes) const Mesh * mesh_parent; /// defines if current mesh is mesh_facets or not bool is_mesh_facets; }; /* -------------------------------------------------------------------------- */ /* Inline functions */ /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Element & _this) { _this.printself(stream); return stream; } #include "mesh_inline_impl.cc" #include "by_element_type_tmpl.hh" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Mesh & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_MESH_HH__ */ diff --git a/src/fem/mesh_inline_impl.cc b/src/fem/mesh_inline_impl.cc index 5d1d78a94..3d1b66fc6 100644 --- a/src/fem/mesh_inline_impl.cc +++ b/src/fem/mesh_inline_impl.cc @@ -1,541 +1,546 @@ /** * @file mesh_inline_impl.cc * * @author Guillaume Anciaux * @author Marco Vocialta * @author Nicolas Richart * * @date Thu Jul 15 00:41:12 2010 * * @brief Implementation of the inline functions of the mesh class * * @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 . * */ __END_AKANTU__ #if defined(AKANTU_COHESIVE_ELEMENT) # include "cohesive_element.hh" #endif #include "static_communicator.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ inline RemovedNodesEvent::RemovedNodesEvent(const Mesh & mesh) : new_numbering(mesh.getNbNodes(), 1, "new_numbering") { } /* -------------------------------------------------------------------------- */ inline RemovedElementsEvent::RemovedElementsEvent(const Mesh & mesh) : new_numbering("new_numbering", mesh.getID()) { } /* -------------------------------------------------------------------------- */ template <> inline void Mesh::sendEvent(RemovedElementsEvent & event) { connectivities.onElementsRemoved(event.getNewNumbering()); EventHandlerManager::sendEvent(event); } /* -------------------------------------------------------------------------- */ template <> inline void Mesh::sendEvent(RemovedNodesEvent & event) { if(created_nodes) removeNodesFromArray(*nodes , event.getNewNumbering()); if(nodes_global_ids) removeNodesFromArray(*nodes_global_ids, event.getNewNumbering()); if(nodes_type.getSize() != 0) removeNodesFromArray(nodes_type , event.getNewNumbering()); EventHandlerManager::sendEvent(event); } /* -------------------------------------------------------------------------- */ template inline void Mesh::removeNodesFromArray(Array & vect, const Array & new_numbering) { Array tmp(vect.getSize(), vect.getNbComponent()); UInt nb_component = vect.getNbComponent(); UInt new_nb_nodes = 0; for (UInt i = 0; i < new_numbering.getSize(); ++i) { UInt new_i = new_numbering(i); if(new_i != UInt(-1)) { memcpy(tmp.storage() + new_i * nb_component, vect.storage() + i * nb_component, nb_component * sizeof(T)); ++new_nb_nodes; } } tmp.resize(new_nb_nodes); vect.copy(tmp); } /* -------------------------------------------------------------------------- */ #ifdef AKANTU_CORE_CXX11 template inline void Mesh::translate(Args... params) { // check that the number of parameters corresponds to the dimension AKANTU_DEBUG_ASSERT(sizeof...(Args) <= spatial_dimension , "Number of arguments greater than dimension."); // unpack parameters Real s[] = { params... }; Array& nodes = getNodes(); for (UInt i = 0; i < nodes.getSize(); ++i) for (UInt k = 0; k < sizeof...(Args); ++k) nodes(i, k) += s[k]; } #endif /* -------------------------------------------------------------------------- */ inline UInt Mesh::elementToLinearized(const Element & elem) const { AKANTU_DEBUG_ASSERT(elem.type < _max_element_type && elem.element < types_offsets.storage()[elem.type+1], "The element " << elem << "does not exists in the mesh " << getID()); return types_offsets.storage()[elem.type] + elem.element; } /* -------------------------------------------------------------------------- */ inline Element Mesh::linearizedToElement (UInt linearized_element) const { UInt t; for (t = _not_defined; t != _max_element_type && linearized_element >= types_offsets(t); ++t); AKANTU_DEBUG_ASSERT(linearized_element < types_offsets(t), "The linearized element " << linearized_element << "does not exists in the mesh " << getID()); --t; ElementType type = ElementType(t); return Element(type, linearized_element - types_offsets.storage()[t], _not_ghost, getKind(type)); } /* -------------------------------------------------------------------------- */ inline void Mesh::updateTypesOffsets(const GhostType & ghost_type) { Array * types_offsets_ptr = &this->types_offsets; if(ghost_type == _ghost) types_offsets_ptr = &this->ghost_types_offsets; Array & types_offsets = *types_offsets_ptr; types_offsets.clear(); type_iterator it = firstType(_all_dimensions, ghost_type, _ek_not_defined); type_iterator last = lastType(_all_dimensions, ghost_type, _ek_not_defined); for (; it != last; ++it) types_offsets(*it) = connectivities(*it, ghost_type).getSize(); for (UInt t = _not_defined + 1; t < _max_element_type; ++t) types_offsets(t) += types_offsets(t - 1); for (UInt t = _max_element_type; t > _not_defined; --t) types_offsets(t) = types_offsets(t - 1); types_offsets(0) = 0; } /* -------------------------------------------------------------------------- */ inline const Mesh::ConnectivityTypeList & Mesh::getConnectivityTypeList(const GhostType & ghost_type) const { if (ghost_type == _not_ghost) return type_set; else return ghost_type_set; } /* -------------------------------------------------------------------------- */ inline Array * Mesh::getNodesGlobalIdsPointer() { AKANTU_DEBUG_IN(); if(nodes_global_ids == NULL) { std::stringstream sstr; sstr << getID() << ":nodes_global_ids"; nodes_global_ids = &(alloc(sstr.str(), nodes->getSize(), 1)); } AKANTU_DEBUG_OUT(); return nodes_global_ids; } /* -------------------------------------------------------------------------- */ inline Array * Mesh::getNodesTypePointer() { AKANTU_DEBUG_IN(); if(nodes_type.getSize() == 0) { nodes_type.resize(nodes->getSize()); nodes_type.set(-1); } AKANTU_DEBUG_OUT(); return &nodes_type; } /* -------------------------------------------------------------------------- */ inline Array * Mesh::getConnectivityPointer(const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Array * tmp; if(!connectivities.exists(type, ghost_type)) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); tmp = &(connectivities.alloc(0, nb_nodes_per_element, type, ghost_type)); AKANTU_DEBUG_INFO("The connectivity vector for the type " << type << " created"); if (ghost_type == _not_ghost) type_set.insert(type); else ghost_type_set.insert(type); updateTypesOffsets(ghost_type); } else { tmp = &connectivities(type, ghost_type); } AKANTU_DEBUG_OUT(); return tmp; } /* -------------------------------------------------------------------------- */ inline Array< std::vector > * Mesh::getElementToSubelementPointer(const ElementType & type, const GhostType & ghost_type) { - return getDataPointer< std::vector >("element_to_subelement", type, ghost_type); + Array< std::vector > * tmp = + getDataPointer< std::vector >("element_to_subelement", type, ghost_type, 1, true); + return tmp; } /* -------------------------------------------------------------------------- */ inline Array * Mesh::getSubelementToElementPointer(const ElementType & type, const GhostType & ghost_type) { - return getDataPointer("subelement_to_element", type, ghost_type, getNbFacetsPerElement(type)); + Array * tmp = + getDataPointer("subelement_to_element", type, ghost_type, + getNbFacetsPerElement(type), true, is_mesh_facets); + return tmp; } /* -------------------------------------------------------------------------- */ inline const Array< std::vector > & Mesh::getElementToSubelement(const ElementType & type, const GhostType & ghost_type) const { return getData< std::vector >("element_to_subelement", type, ghost_type); } /* -------------------------------------------------------------------------- */ inline Array< std::vector > & Mesh::getElementToSubelement(const ElementType & type, const GhostType & ghost_type) { return getData< std::vector >("element_to_subelement", type, ghost_type); } /* -------------------------------------------------------------------------- */ inline const Array & Mesh::getSubelementToElement(const ElementType & type, const GhostType & ghost_type) const { return getData("subelement_to_element", type, ghost_type); } /* -------------------------------------------------------------------------- */ inline Array & Mesh::getSubelementToElement(const ElementType & type, const GhostType & ghost_type) { return getData("subelement_to_element", type, ghost_type); } /* -------------------------------------------------------------------------- */ template inline Array * Mesh::getDataPointer(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type, UInt nb_component, - bool size_to_nb_element) { + bool size_to_nb_element, + bool resize_with_parent) { Array & tmp = mesh_data.getElementalDataArrayAlloc(data_name, el_type, ghost_type, nb_component); if (size_to_nb_element) { - if (is_mesh_facets && getSpatialDimension(el_type) == spatial_dimension) + if (resize_with_parent) tmp.resize(mesh_parent->getNbElement(el_type, ghost_type)); else - tmp.resize(getNbElement(el_type, ghost_type)); - } - else { + tmp.resize(this->getNbElement(el_type, ghost_type)); + } else { tmp.resize(0); } return &tmp; } /* -------------------------------------------------------------------------- */ template inline const Array & Mesh::getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type) const { return mesh_data.getElementalDataArray(data_name, el_type, ghost_type); } /* -------------------------------------------------------------------------- */ template inline Array & Mesh::getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type) { return mesh_data.getElementalDataArray(data_name, el_type, ghost_type); } /* -------------------------------------------------------------------------- */ template inline const ByElementTypeArray & Mesh::getData(const std::string & data_name) const { return mesh_data.getElementalData(data_name); } /* -------------------------------------------------------------------------- */ template inline ByElementTypeArray & Mesh::getData(const std::string & data_name) { return mesh_data.getElementalData(data_name); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbElement(const ElementType & type, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); try { const Array & conn = connectivities(type, ghost_type); AKANTU_DEBUG_OUT(); return conn.getSize(); } catch (...) { AKANTU_DEBUG_OUT(); return 0; } } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbElement(const UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & kind) const { AKANTU_DEBUG_IN(); UInt nb_element = 0; type_iterator it = firstType(spatial_dimension, ghost_type, kind); type_iterator last = lastType(spatial_dimension, ghost_type, kind); for (; it != last; ++it) nb_element += getNbElement(*it, ghost_type); AKANTU_DEBUG_OUT(); return nb_element; } /* -------------------------------------------------------------------------- */ inline void Mesh::getBarycenter(UInt element, const ElementType & type, Real * barycenter, GhostType ghost_type) const { AKANTU_DEBUG_IN(); UInt * conn_val = getConnectivity(type, ghost_type).storage(); UInt nb_nodes_per_element = getNbNodesPerElement(type); Real local_coord[spatial_dimension * nb_nodes_per_element]; UInt offset = element * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { memcpy(local_coord + n * spatial_dimension, nodes->storage() + conn_val[offset + n] * spatial_dimension, spatial_dimension*sizeof(Real)); } Math::barycenter(local_coord, nb_nodes_per_element, spatial_dimension, barycenter); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void Mesh::getBarycenter(const Element & element, Vector & barycenter) const { getBarycenter(element.element, element.type, barycenter.storage(), element.ghost_type); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbNodesPerElement(const ElementType & type) { UInt nb_nodes_per_element = 0; #define GET_NB_NODES_PER_ELEMENT(type) \ nb_nodes_per_element = ElementClass::getNbNodesPerElement() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_NODES_PER_ELEMENT); #undef GET_NB_NODES_PER_ELEMENT return nb_nodes_per_element; } /* -------------------------------------------------------------------------- */ inline ElementType Mesh::getP1ElementType(const ElementType & type) { ElementType p1_type = _not_defined; #define GET_P1_TYPE(type) \ p1_type = ElementClass::getP1ElementType() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_P1_TYPE); #undef GET_P1_TYPE return p1_type; } /* -------------------------------------------------------------------------- */ inline ElementKind Mesh::getKind(const ElementType & type) { ElementKind kind = _ek_not_defined; #define GET_KIND(type) \ kind = ElementClass::getKind() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_KIND); #undef GET_KIND return kind; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getSpatialDimension(const ElementType & type) { UInt spatial_dimension = 0; #define GET_SPATIAL_DIMENSION(type) \ spatial_dimension = ElementClass::getSpatialDimension() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_SPATIAL_DIMENSION); #undef GET_SPATIAL_DIMENSION return spatial_dimension; } /* -------------------------------------------------------------------------- */ inline ElementType Mesh::getFacetType(const ElementType & type) { ElementType surface_type = _not_defined; #define GET_FACET_TYPE(type) \ surface_type = ElementClass::getFacetType() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_FACET_TYPE); #undef GET_FACET_TYPE return surface_type; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbFacetsPerElement(const ElementType & type) { AKANTU_DEBUG_IN(); UInt n_facet = 0; #define GET_NB_FACET(type) \ n_facet = ElementClass::getNbFacetsPerElement() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_FACET); #undef GET_NB_FACET AKANTU_DEBUG_OUT(); return n_facet; } /* -------------------------------------------------------------------------- */ inline MatrixProxy Mesh::getFacetLocalConnectivity(const ElementType & type) { AKANTU_DEBUG_IN(); MatrixProxy mat; #define GET_FACET_CON(type) \ mat = ElementClass::getFacetLocalConnectivityPerElement() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_FACET_CON); #undef GET_FACET_CON AKANTU_DEBUG_OUT(); return mat; } /* -------------------------------------------------------------------------- */ inline Matrix Mesh::getFacetConnectivity(UInt element, const ElementType & type, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); Matrix local_facets(getFacetLocalConnectivity(type), false); Matrix facets(local_facets.rows(), local_facets.cols()); const Array & conn = connectivities(type, ghost_type); for (UInt f = 0; f < facets.rows(); ++f) { for (UInt n = 0; n < facets.cols(); ++n) { facets(f, n) = conn(element, local_facets(f, n)); } } AKANTU_DEBUG_OUT(); return facets; } /* -------------------------------------------------------------------------- */ template inline void Mesh::extractNodalValuesFromElement(const Array & nodal_values, T * local_coord, UInt * connectivity, UInt n_nodes, UInt nb_degree_of_freedom) const { for (UInt n = 0; n < n_nodes; ++n) { memcpy(local_coord + n * nb_degree_of_freedom, nodal_values.storage() + connectivity[n] * nb_degree_of_freedom, nb_degree_of_freedom * sizeof(T)); } } /* -------------------------------------------------------------------------- */ #define DECLARE_GET_BOUND(Var, var) \ inline void Mesh::get##Var##Bounds(Real * var) const { \ for (UInt i = 0; i < spatial_dimension; ++i) { \ var[i] = var##_bounds[i]; \ } \ } \ DECLARE_GET_BOUND(Lower, lower) DECLARE_GET_BOUND(Upper, upper) DECLARE_GET_BOUND(LocalLower, local_lower) DECLARE_GET_BOUND(LocalUpper, local_upper) #undef DECLARE_GET_BOUND /* -------------------------------------------------------------------------- */ inline void Mesh::addConnectivityType(const ElementType & type, const GhostType & ghost_type){ getConnectivityPointer(type, ghost_type); } /* -------------------------------------------------------------------------- */ inline bool Mesh::isPureGhostNode(UInt n) const { return nodes_type.getSize() ? (nodes_type(n) == -3) : false; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isLocalOrMasterNode(UInt n) const { return nodes_type.getSize() ? (nodes_type(n) == -2) || (nodes_type(n) == -1) : true; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isLocalNode(UInt n) const { return nodes_type.getSize() ? nodes_type(n) == -1 : true; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isMasterNode(UInt n) const { return nodes_type.getSize() ? nodes_type(n) == -2 : false; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isSlaveNode(UInt n) const { return nodes_type.getSize() ? nodes_type(n) >= 0 : false; } /* -------------------------------------------------------------------------- */ inline Int Mesh::getNodeType(UInt local_id) const { return nodes_type.getSize() ? nodes_type(local_id) : -1; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNodeGlobalId(UInt local_id) const { return nodes_global_ids ? (*nodes_global_ids)(local_id) : local_id; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbGlobalNodes() const { return nodes_global_ids ? nb_global_nodes : nodes->getSize(); } diff --git a/src/io/parser/cppargparse/cppargparse.cc b/src/io/parser/cppargparse/cppargparse.cc new file mode 100644 index 000000000..8ffbd4c5f --- /dev/null +++ b/src/io/parser/cppargparse/cppargparse.cc @@ -0,0 +1,443 @@ +/** + * @file cppargparse.cc + * + * @author Nicolas Richart + * + * @date Fri Mar 28 17:08:38 2014 + * + * @brief implementation of the ArgumentParser + * + * @section LICENSE + * + * Copyright (©) 2014 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 . + * + */ + +/* -------------------------------------------------------------------------- */ +#include "cppargparse.hh" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace cppargparse { + +/* -------------------------------------------------------------------------- */ +static inline std::string to_upper(const std::string & str) { + std::string lstr = str; + std::transform(lstr.begin(), + lstr.end(), + lstr.begin(), + (int(*)(int))std::toupper); + return lstr; +} + + +/* -------------------------------------------------------------------------- */ +/* ArgumentParser */ +/* -------------------------------------------------------------------------- */ +ArgumentParser::ArgumentParser() : external_exit(NULL) { + this->addArgument("-h;--help", "show this help message and exit", 0, _boolean, false, true); +} + +ArgumentParser::~ArgumentParser() { + for(_Arguments::iterator it = arguments.begin(); it != arguments.end(); ++it) { + delete it->second; + } +} + + void ArgumentParser::_exit(const std::string & msg, int status) { + if(msg != "") { + std::cerr << msg << std::endl; + std::cerr << std::endl; + } + + this->print_help(std::cerr); + + if(external_exit) + (*external_exit)(status); + else { + exit(status); + } +} + +const ArgumentParser::Argument & ArgumentParser::operator[](const std::string & name) const { + Arguments::const_iterator it = success_parsed.find(name); + + if(it != success_parsed.end()) { + return *(it->second); + } else { + throw std::range_error("No argument named \'" + name + + "\' was found in the parsed argument," + + " make sur to specify it \'required\'" + + " or to give it a default value"); + } +} + +/* -------------------------------------------------------------------------- */ +void ArgumentParser::addArgument(const std::string & name_or_flag, + const std::string & help, + int nargs, + ArgumentType type) { + _addArgument(name_or_flag, help, nargs, type); +} + +ArgumentParser::_Argument & ArgumentParser::_addArgument(const std::string & name, + const std::string & help, + int nargs, + ArgumentType type) { + _Argument * arg = NULL; + + switch(type) { + case _string: { arg = new ArgumentStorage(); break; } + case _float: { arg = new ArgumentStorage(); break; } + case _integer: { arg = new ArgumentStorage(); break; } + case _boolean: { arg = new ArgumentStorage(); break; } + } + + arg->help = help; + arg->nargs = nargs; + arg->type = type; + + std::stringstream sstr(name); + std::string item; + std::vector tmp_keys; + while (std::getline(sstr, item, ';')) { + tmp_keys.push_back(item); + } + + int long_key = -1; + int short_key = -1; + bool problem = (tmp_keys.size() > 2) || (name == ""); + for (std::vector::iterator it = tmp_keys.begin(); it != tmp_keys.end(); ++it) { + if(it->find("--") == 0) { + problem |= (long_key != -1); + long_key = it - tmp_keys.begin(); + } else if(it->find("-") == 0) { + problem |= (long_key != -1); + short_key = it - tmp_keys.begin(); + } + } + + problem |= ((tmp_keys.size() == 2) && (long_key == -1 || short_key == -1)); + + if(problem) { + throw std::invalid_argument("Synthax of name or flags is not correct. Possible synthax are \'-f\', \'-f;--foo\', \'--foo\', \'bar\'"); + } + + if(long_key != -1) { + arg->name = tmp_keys[long_key]; + arg->name.erase(0, 2); + } else if(short_key != -1) { + arg->name = tmp_keys[short_key]; + arg->name.erase(0, 1); + } else { + arg->name = tmp_keys[0]; + pos_args.push_back(arg); + arg->required = true; + arg->is_positional = true; + } + + arguments[arg->name] = arg; + + if(!arg->is_positional) { + if(short_key != -1) { + std::string key = tmp_keys[short_key]; + key_args[key] = arg; + arg->keys.push_back(key); + } + + if(long_key != -1) { + std::string key = tmp_keys[long_key]; + key_args[key] = arg; + arg->keys.push_back(key); + } + } + + return *arg; +} + + +/* -------------------------------------------------------------------------- */ +void ArgumentParser::parse(int& argc, char**& argv, int flags) { + bool stop_in_not_parsed = flags & _stop_on_not_parsed; + bool remove_parsed = flags & _remove_parsed; + + std::vector argvs; + + for (int i = 0; i < argc; ++i) { + argvs.push_back(std::string(argv[i])); + } + + unsigned int current_position = 0; + if(this->program_name == "") { + std::string prog = argvs[current_position]; + const char * c_prog = prog.c_str(); + char * c_prog_tmp = strdup(c_prog); + std::string base_prog(basename(c_prog_tmp)); + this->program_name = base_prog; + std::free(c_prog_tmp); + } + + std::queue<_Argument *> positional_queue; + for(PositionalArgument::iterator it = pos_args.begin(); + it != pos_args.end(); ++it) + positional_queue.push(*it); + + std::vector argvs_to_remove; + ++current_position; // consume argv[0] + while(current_position < argvs.size()) { + std::string arg = argvs[current_position]; + ++current_position; + + ArgumentKeyMap::iterator key_it = key_args.find(arg); + + bool is_positional = false; + _Argument * argument_ptr = NULL; + if(key_it == key_args.end()) { + if(positional_queue.empty()) { + if(stop_in_not_parsed) this->_exit("Argument " + arg + " not recognized", EXIT_FAILURE); + continue; + } else { + argument_ptr = positional_queue.front(); + is_positional = true; + --current_position; + } + } else { + argument_ptr = key_it->second; + } + + if(remove_parsed && ! is_positional) { + argvs_to_remove.push_back(current_position - 1); + } + + _Argument & argument = *argument_ptr; + + unsigned int min_nb_val = 0, max_nb_val = 0; + switch(argument.nargs) { + case _one_if_possible: max_nb_val = 1; break; // "?" + case _at_least_one: min_nb_val = 1; // "+" + case _any: max_nb_val = argc - current_position; break; // "*" + default: min_nb_val = max_nb_val = argument.nargs; // "N" + } + + std::vector values; + unsigned int arg_consumed = 0; + if(max_nb_val <= (argc - current_position)) { + for(; arg_consumed < max_nb_val; ++arg_consumed) { + std::string v = argvs[current_position]; + ++current_position; + bool is_key = key_args.find(v) != key_args.end(); + bool is_good_type = checkType(argument.type, v); + + if(!is_key && is_good_type) { + values.push_back(v); + if(remove_parsed) argvs_to_remove.push_back(current_position - 1); + } else { + // unconsume not parsed argument for optional + if(!is_positional || (is_positional && is_key)) --current_position; + break; + } + } + } + + if(arg_consumed < min_nb_val) { + if(!is_positional) { + this->_exit("Not enought values for the argument " + + argument.name + " where provided", EXIT_FAILURE); + } else { + if(stop_in_not_parsed) this->_exit("Argument " + arg + " not recognized", EXIT_FAILURE); + } + } else { + if (is_positional) positional_queue.pop(); + + if(!argument.parsed) { + success_parsed[argument.name] = &argument; + argument.parsed = true; + if((argument.nargs == _one_if_possible || argument.nargs == 0) && arg_consumed == 0) { + if(argument.has_const) + argument.setToConst(); + else if(argument.has_default) + argument.setToDefault(); + } else { + argument.setValues(values); + } + } else { + this->_exit("Argument " + argument.name + + " already present in the list of argument", EXIT_FAILURE); + } + } + } + + for (_Arguments::iterator ait = arguments.begin(); + ait != arguments.end(); ++ait) { + _Argument & argument = *(ait->second); + if(!argument.parsed) { + if(argument.has_default) { + argument.setToDefault(); + success_parsed[argument.name] = &argument; + } + + if(argument.required) { + this->_exit("Argument " + argument.name + " required but not given!", EXIT_FAILURE); + } + } + } + + + // removing the parsed argument if remove_parsed is true + if(argvs_to_remove.size()) { + std::vector::const_iterator next_to_remove = argvs_to_remove.begin(); + for (int i = 0, c = 0; i < argc; ++i) { + if(next_to_remove == argvs_to_remove.end() || i != *next_to_remove) { + argv[c] = argv[i]; + ++c; + } else { + if (next_to_remove != argvs_to_remove.end()) ++next_to_remove; + } + } + + argc -= argvs_to_remove.size(); + } + + if(this->arguments["help"]->parsed) { + this->_exit(); + } +} + +/* -------------------------------------------------------------------------- */ +bool ArgumentParser::checkType(ArgumentType type, const std::string & value) const { + std::stringstream sstr(value); + switch(type) { + case _string: { std::string s; sstr >> s; break; } + case _float: { double d; sstr >> d; break; } + case _integer: { int i; sstr >> i; break; } + case _boolean: { bool b; sstr >> b; break; } + } + + return (sstr.fail() == false); +} + + +/* -------------------------------------------------------------------------- */ +void ArgumentParser::printself(std::ostream & stream) const { + for(Arguments::const_iterator it = success_parsed.begin(); + it != success_parsed.end(); ++it) { + const Argument & argument = *(it->second); + argument.printself(stream); + std::cout << std::endl; + } +} + +/* -------------------------------------------------------------------------- */ +void ArgumentParser::print_usage(std::ostream & stream) const { + stream << "Usage: " << this->program_name; + + std::stringstream sstr_opt; + // print shorten usage + for(_Arguments::const_iterator it = arguments.begin(); + it != arguments.end(); ++it) { + const _Argument & argument = *(it->second); + if(!argument.is_positional) { + if(!argument.required) stream << " ["; + stream << argument.keys[0]; + this->print_usage_nargs(stream, argument); + if(!argument.required) stream << "]"; + } + } + + for(PositionalArgument::const_iterator it = pos_args.begin(); + it != pos_args.end(); ++it) { + const _Argument & argument = **it; + this->print_usage_nargs(stream, argument); + } + + stream << std::endl; +} + +/* -------------------------------------------------------------------------- */ +void ArgumentParser::print_usage_nargs(std::ostream & stream, + const _Argument & argument) const { + std::string u_name = to_upper(argument.name); + switch(argument.nargs) { + case _one_if_possible: stream << " [" << u_name << "]"; break; + case _at_least_one: stream << " " << u_name; + case _any: stream << " [" << u_name << " ...]"; break; + default: + for(int i = 0; i < argument.nargs; ++i) { + stream << " " << u_name; + } + } +} + +void ArgumentParser::print_help(std::ostream & stream) const { + this->print_usage(stream); + if(!pos_args.empty()) { + stream << std::endl; + stream << "positional arguments:" << std::endl; + for(PositionalArgument::const_iterator it = pos_args.begin(); + it != pos_args.end(); ++it) { + const _Argument & argument = **it; + this->print_help_argument(stream, argument); + } + } + + if(!key_args.empty()) { + stream << std::endl; + stream << "optional arguments:" << std::endl; + for(_Arguments::const_iterator it = arguments.begin(); + it != arguments.end(); ++it) { + const _Argument & argument = *(it->second); + if(!argument.is_positional) { + this->print_help_argument(stream, argument); + } + } + } +} + +void ArgumentParser::print_help_argument(std::ostream & stream, const _Argument & argument) const { + std::string key(""); + if(argument.is_positional) + key = argument.name; + else { + std::stringstream sstr; + for(unsigned int i = 0; i < argument.keys.size(); ++i) { + if(i != 0) sstr << ", "; + sstr << argument.keys[i]; + this->print_usage_nargs(sstr, argument); + } + key = sstr.str(); + } + + stream << " " << std::left << std::setw(15) << key << " " << argument.help; + argument.printDefault(stream); + + stream << std::endl; +} + + +} diff --git a/src/io/parser/cppargparse/cppargparse.hh b/src/io/parser/cppargparse/cppargparse.hh new file mode 100644 index 000000000..00e3bfabe --- /dev/null +++ b/src/io/parser/cppargparse/cppargparse.hh @@ -0,0 +1,169 @@ +/** + * @file cppargparse.hh + * + * @author Nicolas Richart + * + * @date Fri Mar 28 14:07:02 2014 + * + * @brief Get the commandline options and store them as short, long and others + * + * @section LICENSE + * + * Copyright (©) 2014 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 . + * + */ + +/* -------------------------------------------------------------------------- */ +#include +#include +#include +#include + + +#ifndef __CPPARGPARSE_HH__ +#define __CPPARGPARSE_HH__ + +namespace cppargparse { + +enum ArgumentType { + _string, + _integer, + _float, + _boolean +}; + +enum ArgumentNargs { + _one_if_possible = -1, + _at_least_one = -2, + _any = -3 +}; + +enum ParseFlags { + _no_flags = 0x0, + _stop_on_not_parsed = 0x1, + _remove_parsed = 0x2 +}; + +inline ParseFlags operator|(const ParseFlags & a, const ParseFlags & b) { + ParseFlags tmp = ParseFlags(int(a) | int(b)); + return tmp; +} + +class ArgumentParser { +public: + class Argument { + public: + Argument() : name(std::string()) {} + virtual ~Argument() {} + virtual void printself(std::ostream & stream) const = 0; + template operator T() const; + std::string name; + }; + + /// constructor + ArgumentParser(); + + /// destroy everything + ~ArgumentParser(); + + /// add an argument with a description + void addArgument(const std::string & name_or_flag, + const std::string & help, + int nargs = 1, + ArgumentType type = _string); + + /// add an argument with an help and a default value + template + void addArgument(const std::string & name_or_flag, + const std::string & help, + int nargs, + ArgumentType type, + T def); + + /// add an argument with an help and a default + const value + template + void addArgument(const std::string & name_or_flag, + const std::string & help, + int nargs, + ArgumentType type, + T def, + T cons); + + /// parse argc, argv + void parse(int & argc, char ** & argv, + int flags = _stop_on_not_parsed); + + /// print the content in the stream + void printself(std::ostream & stream) const; + + /// print the help text + void print_help(std::ostream & stream = std::cout) const; + + /// print the usage text + void print_usage(std::ostream & stream = std::cout) const; + + /// set an external function to replace the exit function from the stdlib + void setExternalExitFunction(void (*external_exit)(int)) { + this->external_exit = external_exit; + } + + /// accessor for a registered argument that was parsed, throw an exception if + /// the argument does not exist or was not set (parsed or default value) + const Argument & operator[](const std::string & name) const; + +private: + class _Argument; + template class ArgumentStorage; + + + _Argument & _addArgument(const std::string & name_or_flag, + const std::string & description, + int nargs, + ArgumentType type); + + void _exit(const std::string & msg = "", int status = 0); + bool checkType(ArgumentType type, const std::string & value) const; + + void print_usage_nargs(std::ostream & stream, const _Argument & argument) const; + void print_help_argument(std::ostream & stream, const _Argument & argument) const; + +private: + typedef std::map _Arguments; + typedef std::map Arguments; + typedef std::map ArgumentKeyMap; + typedef std::vector<_Argument *> PositionalArgument; + + _Arguments arguments; + + ArgumentKeyMap key_args; + PositionalArgument pos_args; + Arguments success_parsed; + + std::string program_name; + void (*external_exit)(int); +}; + +} + +inline std::ostream & operator<<(std::ostream & stream, const cppargparse::ArgumentParser & argparse) { + argparse.printself(stream); + return stream; +} + +#endif /* __CPPARGPARSE_HH__ */ + +#include "cppargparse_tmpl.hh" diff --git a/src/io/parser/cppargparse/cppargparse_tmpl.hh b/src/io/parser/cppargparse/cppargparse_tmpl.hh new file mode 100644 index 000000000..9fbe094d6 --- /dev/null +++ b/src/io/parser/cppargparse/cppargparse_tmpl.hh @@ -0,0 +1,214 @@ +/** + * @file cppargparse_tmpl.hh + * + * @author Nicolas Richart + * + * @date Mon Mar 31 21:15:31 2014 + * + * @brief + * + * @section LICENSE + * + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see . + * + */ + +/* -------------------------------------------------------------------------- */ +#include + +#ifndef __CPPARGPARSE_TMPL_HH__ +#define __CPPARGPARSE_TMPL_HH__ + +namespace cppargparse { +/* -------------------------------------------------------------------------- */ +/* Argument */ +/* -------------------------------------------------------------------------- */ +struct ArgumentParser::_Argument : public Argument { + _Argument() : Argument(), + help(std::string()), + nargs(1), + type(_string), + required(false), + parsed(false), + has_default(false), + has_const(false), + is_positional(false) {} + virtual ~_Argument() {} + + void setValues(std::vector & values) { + for (std::vector::iterator it = values.begin(); + it != values.end(); ++it) { + this->addValue(*it); + } + } + + virtual void addValue(std::string & value) = 0; + virtual void setToDefault() = 0; + virtual void setToConst() = 0; + + std::ostream & printDefault(std::ostream & stream) const { + stream << std::boolalpha; + if(has_default) { + stream << " (default: "; + this->_printDefault(stream); + stream << ")"; + } + if(has_const) { + stream << " (const: "; + this->_printConst(stream); + stream << ")"; + } + return stream; + } + + virtual std::ostream & _printDefault(std::ostream & stream) const = 0; + virtual std::ostream & _printConst(std::ostream & stream) const = 0; + + std::string help; + int nargs; + ArgumentType type; + bool required; + bool parsed; + bool has_default; + bool has_const; + std::vector keys; + bool is_positional; +}; + +/* -------------------------------------------------------------------------- */ +template +class ArgumentParser::ArgumentStorage : public ArgumentParser::_Argument { +public: + ArgumentStorage() : _default(T()), _const(T()), values(std::vector()) {} + + virtual void addValue(std::string & value) { + std::stringstream sstr(value); + T t; + sstr >> t; + values.push_back(t); + } + + virtual void setToDefault() { + values.clear(); + values.push_back(_default); + } + + virtual void setToConst() { + values.clear(); + values.push_back(_const); + } + + void printself(std::ostream & stream) const { + stream << this->name << " ="; + stream << std::boolalpha; // for boolean + for(typename std::vector::const_iterator vit = this->values.begin(); + vit != this->values.end(); ++vit) { + stream << " " << *vit; + } + } + + virtual std::ostream & _printDefault(std::ostream & stream) const { + stream << _default; + return stream; + } + + virtual std::ostream & _printConst(std::ostream & stream) const { + stream << _const; + return stream; + } + + T _default; + T _const; + std::vector values; +}; + +/* -------------------------------------------------------------------------- */ +template<> +inline void ArgumentParser::ArgumentStorage::addValue(std::string & value) { + values.push_back(value); +} + +template +struct is_vector { + enum { value = false }; +}; + + +template +struct is_vector< std::vector > { + enum { value = true }; +}; + + +/* -------------------------------------------------------------------------- */ +template::value> +struct cast_helper { + static T cast(const ArgumentParser::Argument & arg) { + const ArgumentParser::ArgumentStorage & _arg = + dynamic_cast &>(arg); + if(_arg.values.size() == 1) { + return _arg.values[0]; + } else { + throw std::length_error("Not enougth or too many argument where passed for the command line argument: " + arg.name); + } + } +}; + +template +struct cast_helper { + static T cast(const ArgumentParser::Argument & arg) { + const ArgumentParser::ArgumentStorage & _arg = + dynamic_cast &>(arg); + return _arg.values; + } +}; + +/* -------------------------------------------------------------------------- */ +template +ArgumentParser::Argument::operator T() const{ + return cast_helper::cast(*this); +} + +template +void ArgumentParser::addArgument(const std::string & name_or_flag, + const std::string & help, + int nargs, + ArgumentType type, + T def) { + _Argument & arg = _addArgument(name_or_flag, help, nargs, type); + dynamic_cast &>(arg)._default = def; + arg.has_default = true; +} + +template +void ArgumentParser::addArgument(const std::string & name_or_flag, + const std::string & help, + int nargs, + ArgumentType type, + T def, + T cons) { + _Argument & arg = _addArgument(name_or_flag, help, nargs, type); + dynamic_cast &>(arg)._default = def; + arg.has_default = true; + dynamic_cast &>(arg)._const = cons; + arg.has_const = true; +} + + +} + +#endif /* __AKANTU_CPPARGPARSE_TMPL_HH__ */ diff --git a/src/io/parser/parser.cc b/src/io/parser/parser.cc index 854a456ee..39f7ad7ef 100644 --- a/src/io/parser/parser.cc +++ b/src/io/parser/parser.cc @@ -1,229 +1,221 @@ /** * @file parser.cc * * @author Nicolas Richart * * @date Fri Aug 2 12:14:15 2013 * * @brief implementation of the parser * * @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 . * */ /* -------------------------------------------------------------------------- */ // STL #include #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "parser.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ //#include #include #include #include /* -------------------------------------------------------------------------- */ #include "algebraic_parser.hh" #include "input_file_parser.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ ParserSection::~ParserSection() { } /* -------------------------------------------------------------------------- */ ParserParameter & ParserSection::addParameter(const ParserParameter & param) { if(parameters.find(param.getName()) != parameters.end()) AKANTU_EXCEPTION("The parameter \"" + param.getName() + "\" is already defined in this section"); return (parameters.insert (std::pair(param.getName(), param)).first->second); } /* -------------------------------------------------------------------------- */ ParserSection & ParserSection::addSubSection(const ParserSection & section) { return ((sub_sections_by_type.insert (std::pair(section.getType(), section)))->second); } +/* -------------------------------------------------------------------------- */ +std::string Parser::getLastParsedFile() const { + return last_parsed_file; +} + + /* -------------------------------------------------------------------------- */ void Parser::parse(const std::string& filename) { std::ifstream input(filename.c_str()); input.unsetf(std::ios::skipws); // wrap istream into iterator spirit::istream_iterator fwd_begin(input); spirit::istream_iterator fwd_end; // wrap forward iterator with position iterator, to record the position typedef spirit::classic::position_iterator2 pos_iterator_type; pos_iterator_type position_begin(fwd_begin, fwd_end, filename); pos_iterator_type position_end; // parse parser::InputFileGammar ag(this); bool result = qi::phrase_parse(position_begin, position_end, ag, ag.skipper); if(!result || position_begin != position_end) { spirit::classic::file_position pos = position_begin.get_position(); AKANTU_EXCEPTION("Parse error [ " << ag.getErrorMessage() << " ]" << " in file " << filename << " line " << pos.line << " column " << pos.column << std::endl << "'" << position_begin.get_currentline() << "'" << std::endl << std::setw(pos.column) << " " << "^- here"); } try { DebugLevel dbl = debug::getDebugLevel(); debug::setDebugLevel(dblError); bool permissive = getParameter("parser_permissive", _ppsc_current_scope); debug::setDebugLevel(dbl); parser_permissive = permissive; AKANTU_DEBUG_INFO("Parser switched permissive mode to " << std::boolalpha << parser_permissive); } catch (debug::Exception & e) { } - try { - DebugLevel dbl = debug::getDebugLevel(); - debug::setDebugLevel(dblError); - long int seed = getParameter("seed", _ppsc_current_scope); - debug::setDebugLevel(dbl); - - seed *= (StaticCommunicator::getStaticCommunicator().whoAmI() + 1); - - Rand48Generator::seed(seed); - RandGenerator::seed(seed); - AKANTU_DEBUG_INFO("Random seed set to " << seed); - } catch (debug::Exception & e) { - } - - + last_parsed_file = filename; input.close(); } /* -------------------------------------------------------------------------- */ template T Parser::parseType(const std::string & value, Grammar & grammar) { using boost::spirit::ascii::space; std::string::const_iterator b = value.begin(); std::string::const_iterator e = value.end(); T resultat = T(); bool res = false; try { res = qi::phrase_parse(b, e, grammar, space, resultat); } catch(debug::Exception & ex) { AKANTU_EXCEPTION("Could not parse '" << value << "' as a " << debug::demangle(typeid(T).name()) << ", an unknown error append '" << ex.what()); } if(!res || (b != e)) { AKANTU_EXCEPTION("Could not parse '" << value << "' as a " << debug::demangle(typeid(T).name()) << ", an unknown error append '" << std::string(value.begin(), b) << "" << std::string(b, e) << "'"); } return resultat; } /* -------------------------------------------------------------------------- */ Real Parser::parseReal(const std::string & value, const ParserSection & section) { using boost::spirit::ascii::space_type; parser::AlgebraicGammar grammar(section); return Parser::parseType(value, grammar); } /* -------------------------------------------------------------------------- */ Vector Parser::parseVector(const std::string & value, const ParserSection & section) { using boost::spirit::ascii::space_type; parser::VectorGammar grammar(section); return Parser::parseType(value, grammar); } /* -------------------------------------------------------------------------- */ Matrix Parser::parseMatrix(const std::string & value, const ParserSection & section) { using boost::spirit::ascii::space_type; parser::MatrixGammar grammar(section); return Parser::parseType(value, grammar); } /* -------------------------------------------------------------------------- */ RandomParameter Parser::parseRandomParameter(const std::string & value, const ParserSection & section) { using boost::spirit::ascii::space_type; parser::RandomGeneratorGammar grammar(section); parser::ParsableRandomGenerator rg = Parser::parseType(value, grammar); Vector params = rg.parameters; switch(rg.type) { case _rdt_not_defined: return RandomParameter(rg.base); case _rdt_uniform: return RandomParameter(rg.base, UniformDistribution(params(0), params(1))); case _rdt_weibull: return RandomParameter(rg.base, WeibullDistribution(params(0), params(1))); default: AKANTU_EXCEPTION("This is an unknown random distribution in the parser"); } } /* -------------------------------------------------------------------------- */ void ParserSection::printself(std::ostream & stream, unsigned int indent) const { std::string space; std::string ind = AKANTU_INDENT; for(unsigned int i = 0; i < indent; i++, space += ind); stream << space << "Section(" << this->type << ") " << this->name << (option != "" ? (" " + option) : "") << " [" << std::endl; if(!this->parameters.empty()) { stream << space << ind << "Parameters [" << std::endl; Parameters::const_iterator pit = this->parameters.begin(); for(;pit != this->parameters.end(); ++pit) { stream << space << ind << " + "; pit->second.printself(stream); stream << std::endl; } stream << space << ind << "]" << std::endl; } if(!this->sub_sections_by_type.empty()) { stream << space << ind << "Subsections [" << std::endl; SubSections::const_iterator sit = this->sub_sections_by_type.begin(); for (;sit != this->sub_sections_by_type.end(); ++sit) sit->second.printself(stream, indent + 2); stream << std::endl; stream << space << ind << "]" << std::endl; } stream << space << "]"; } __END_AKANTU__ diff --git a/src/io/parser/parser.hh b/src/io/parser/parser.hh index d92c92fa5..a89ff0648 100644 --- a/src/io/parser/parser.hh +++ b/src/io/parser/parser.hh @@ -1,379 +1,384 @@ /** * @file boost_spirit_parser.cc * * @author Nicolas Richart * * @date Wed Jul 24 11:34:23 2013 * * @brief * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_random_generator.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_PARSER_HH__ #define __AKANTU_PARSER_HH__ __BEGIN_AKANTU__ #define AKANTU_SECTION_TYPES \ (global) \ (material) \ (model) \ (heat) \ (rules) \ (non_local) \ (user) \ (not_defined) #define AKANTU_SECTION_TYPES_PREFIX(elem) BOOST_PP_CAT(_st_, elem) #define AKANTU_SECT_PREFIX(s, data, elem) AKANTU_SECTION_TYPES_PREFIX(elem) enum SectionType { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM(AKANTU_SECT_PREFIX, _, AKANTU_SECTION_TYPES)) }; #undef AKANTU_SECT_PREFIX #define AKANTU_SECTION_TYPE_PRINT_CASE(r, data, elem) \ case AKANTU_SECTION_TYPES_PREFIX(elem): { \ stream << BOOST_PP_STRINGIZE(AKANTU_SECTION_TYPES_PREFIX(elem)); \ break; \ } inline std::ostream & operator <<(std::ostream & stream, SectionType type) { switch(type) { BOOST_PP_SEQ_FOR_EACH(AKANTU_SECTION_TYPE_PRINT_CASE, _, AKANTU_SECTION_TYPES) default: stream << "not a SectionType"; break; } return stream; } #undef AKANTU_SECTION_TYPE_PRINT_CASE enum ParserParameterSearchCxt { _ppsc_current_scope = 0x1, _ppsc_parent_scope = 0x2, _ppsc_current_and_parent_scope = 0x3 }; /* ------------------------------------------------------------------------ */ /* Parameters Class */ /* ------------------------------------------------------------------------ */ class ParserSection; class ParserParameter { public: ParserParameter() : parent_section(NULL), name(std::string()), value(std::string()), dbg_filename(std::string()) {} ParserParameter(const std::string & name, const std::string & value, const ParserSection & parent_section) : parent_section(&parent_section), name(name), value(value), dbg_filename(std::string()) {} ParserParameter(const ParserParameter & param) : parent_section(param.parent_section), name(param.name), value(param.value), dbg_filename(param.dbg_filename), dbg_line(param.dbg_line), dbg_column(param.dbg_column) {} virtual ~ParserParameter() {} const std::string & getName() const { return name; } const std::string & getValue() const { return value; } void setDebugInfo(const std::string & filename, UInt line, UInt column) { dbg_filename = filename; dbg_line = line; dbg_column = column; } template inline operator T() const; // template inline operator Vector() const; // template inline operator Matrix() const; void printself(std::ostream & stream, unsigned int indent = 0) const { stream << name << ": " << value << " (" << dbg_filename << ":" << dbg_line << ":" << dbg_column << ")"; } private: void setParent(const ParserSection & sect) { parent_section = § } friend class ParserSection; private: const ParserSection * parent_section; std::string name; std::string value; std::string dbg_filename; UInt dbg_line, dbg_column; }; /* ------------------------------------------------------------------------ */ /* Sections Class */ /* ------------------------------------------------------------------------ */ class ParserSection { public: typedef std::multimap SubSections; typedef std::map Parameters; private: typedef SubSections::const_iterator const_section_iterator_; public: /* ------------------------------------------------------------------------ */ /* SubSection iterator */ /* ------------------------------------------------------------------------ */ class const_section_iterator { public: const_section_iterator(const const_section_iterator & other) : it(other.it) { } const_section_iterator(const const_section_iterator_ & it) : it(it) { } const_section_iterator & operator=(const const_section_iterator & other) { if(this != &other) { it = other.it; } return *this; } const ParserSection & operator* () const { return it->second; } const ParserSection * operator-> () const { return &(it->second); } bool operator==(const const_section_iterator & other) const { return it == other.it; } bool operator!=(const const_section_iterator & other) const { return it != other.it; } const_section_iterator & operator++() { ++it; return *this; } const_section_iterator operator++(int) { const_section_iterator tmp = *this; operator++(); return tmp; } private: const_section_iterator_ it; }; /* ------------------------------------------------------------------------ */ /* Parameters iterator */ /* ------------------------------------------------------------------------ */ class const_parameter_iterator { public: const_parameter_iterator(const const_parameter_iterator & other) : it(other.it) { } const_parameter_iterator(const Parameters::const_iterator & it) : it(it) { } const_parameter_iterator & operator=(const const_parameter_iterator & other) { if(this != &other) { it = other.it; } return *this; } const ParserParameter & operator* () const { return it->second; } const ParserParameter * operator->() { return &(it->second); }; bool operator==(const const_parameter_iterator & other) const { return it == other.it; } bool operator!=(const const_parameter_iterator & other) const { return it != other.it; } const_parameter_iterator & operator++() { ++it; return *this; } const_parameter_iterator operator++(int) { const_parameter_iterator tmp = *this; operator++(); return tmp; } private: Parameters::const_iterator it; }; /* ---------------------------------------------------------------------- */ ParserSection() : parent_section(NULL), name(std::string()), type(_st_not_defined){} ParserSection(const std::string & name, SectionType type) : parent_section(NULL), name(name), type(type) {} ParserSection(const std::string & name, SectionType type, const std::string & option, const ParserSection & parent_section) : parent_section(&parent_section), name(name), type(type), option(option) {} ParserSection(const ParserSection & section) : parent_section(section.parent_section), name(section.name), type(section.type), option(section.option), parameters(section.parameters), sub_sections_by_type(section.sub_sections_by_type) { setChldrenPointers(); } ParserSection & operator=(const ParserSection & other) { if(&other != this) { parent_section = other.parent_section; name = other.name; type = other.type; option = other.option; parameters = other.parameters; sub_sections_by_type = sub_sections_by_type; setChldrenPointers(); } return *this; } virtual ~ParserSection(); virtual void printself(std::ostream & stream, unsigned int indent = 0) const; /* ---------------------------------------------------------------------- */ /* Creation functions */ /* ---------------------------------------------------------------------- */ public: ParserParameter & addParameter(const ParserParameter & param); ParserSection & addSubSection(const ParserSection & section); private: void setChldrenPointers() { Parameters::iterator pit = this->parameters.begin(); for(;pit != this->parameters.end(); ++pit) pit->second.setParent(*this); SubSections::iterator sit = this->sub_sections_by_type.begin(); for (;sit != this->sub_sections_by_type.end(); ++sit) sit->second.setParent(*this); } /* ---------------------------------------------------------------------- */ /* Accessors */ /* ---------------------------------------------------------------------- */ public: std::pair getSubSections(SectionType type = _st_not_defined) const { if(type != _st_not_defined) { std::pair range = sub_sections_by_type.equal_range(type); return std::pair(range.first, range.second); } else { return std::pair(sub_sections_by_type.begin(), sub_sections_by_type.end()); } } std::pair getParameters() const { return std::pair(parameters.begin(), parameters.end()); } /* ---------------------------------------------------------------------- */ const ParserParameter & getParameter(const std::string & name, ParserParameterSearchCxt search_ctx = _ppsc_current_scope) const { Parameters::const_iterator it; if(search_ctx & _ppsc_current_scope) it = parameters.find(name); if(it == parameters.end()) { if((search_ctx & _ppsc_parent_scope) && parent_section) return parent_section->getParameter(name, search_ctx); else { AKANTU_SILENT_EXCEPTION("The parameter " << name << " has not been found in the specified context"); } } return it->second; } /* -------------------------------------------------------------------------- */ template T getParameterValue(const std::string & name, ParserParameterSearchCxt search_ctx = _ppsc_current_scope) const { const ParserParameter & tmp_param = getParameter(name, search_ctx); T t = tmp_param; return t; } /* -------------------------------------------------------------------------- */ const std::string & getName() const { return name; } const SectionType & getType() const { return type; } const std::string & getOption() const { return option; } protected: void setParent(const ParserSection & sect) { parent_section = § } /* ---------------------------------------------------------------------- */ /* Members */ /* ---------------------------------------------------------------------- */ private: const ParserSection * parent_section; std::string name; SectionType type; std::string option; Parameters parameters; SubSections sub_sections_by_type; }; /* ------------------------------------------------------------------------ */ /* Parser Class */ /* ------------------------------------------------------------------------ */ class Parser : public ParserSection { public: Parser() : ParserSection("global", _st_global) {} void parse(const std::string & filename); + std::string getLastParsedFile() const; + + static bool isPermissive() { return parser_permissive; } public: static Real parseReal (const std::string & value, const ParserSection & section); static Vector parseVector(const std::string & value, const ParserSection & section); static Matrix parseMatrix(const std::string & value, const ParserSection & section); static RandomParameter parseRandomParameter(const std::string & value, const ParserSection & section); protected: template static T parseType(const std::string & value, Grammar & grammar); -public: +protected: + friend class Parsable; static bool parser_permissive; + std::string last_parsed_file; }; inline std::ostream & operator <<(std::ostream & stream, const ParserParameter &_this) { _this.printself(stream); return stream; } inline std::ostream & operator <<(std::ostream & stream, const ParserSection & section) { section.printself(stream); return stream; } __END_AKANTU__ #include "parser_tmpl.hh" #endif /* __AKANTU_PARSER_HH__ */ diff --git a/src/mesh_utils/mesh_utils.cc b/src/mesh_utils/mesh_utils.cc index 4c36e96df..f2251275d 100644 --- a/src/mesh_utils/mesh_utils.cc +++ b/src/mesh_utils/mesh_utils.cc @@ -1,1995 +1,2016 @@ /** * @file mesh_utils.cc * * @author Guillaume Anciaux * @author David Simon Kammer * @author Leonardo Snozzi * @author Nicolas Richart * @author Marco Vocialta * * @date Fri Aug 20 12:19:44 2010 * * @brief All mesh utils necessary for various tasks * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "mesh_utils.hh" #include "aka_safe_enum.hh" #include "fem.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2Elements(const Mesh & mesh, CSR & 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::const_iterator< Vector > 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::const_iterator< Vector > 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 & 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; UInt nb_nodes_per_element[nb_types]; UInt * conn_val[nb_types]; 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(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2ElementsByElementType(const Mesh & mesh, CSR & 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, DistributedSynchronizer * synchronizer) { AKANTU_DEBUG_IN(); + UInt spatial_dimension = mesh.getSpatialDimension(); + + buildAllFacets(mesh, mesh_facets, spatial_dimension, to_dimension, synchronizer); + + AKANTU_DEBUG_OUT(); +} +/* -------------------------------------------------------------------------- */ +void MeshUtils::buildAllFacets(const Mesh & mesh, + Mesh & mesh_facets, + UInt from_dimension, + UInt to_dimension, + DistributedSynchronizer * synchronizer) { + AKANTU_DEBUG_IN(); + AKANTU_DEBUG_ASSERT(mesh_facets.isMeshFacets(), "The mesh_facets should be initialized with initMeshFacets"); - UInt spatial_dimension = mesh.getSpatialDimension(); - const ByElementTypeUInt * prank_to_element = NULL; if (synchronizer) { synchronizer->buildPrankToElement(); prank_to_element = &synchronizer->getPrankToElement(); } /// generate facets buildFacetsDimension(mesh, mesh_facets, false, - spatial_dimension, + from_dimension, prank_to_element); /// copy nodes type mesh_facets.nodes_type.resize(mesh.nodes_type.getSize()); mesh_facets.nodes_type.copy(mesh.nodes_type); /// sort facets and generate subfacets - for (UInt i = spatial_dimension - 1; i > to_dimension; --i) { + 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 ByElementTypeUInt * 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 subelements + // example: if the function is called with mesh = mesh_facets + const Mesh & mesh_facets_parent = mesh_facets.getMeshParent(); + mesh_facets.defineMeshParent(mesh); + UInt spatial_dimension = mesh.getSpatialDimension(); const Array & mesh_facets_nodes = mesh_facets.getNodes(); const Array::const_vector_iterator mesh_facets_nodes_it = mesh_facets_nodes.begin(spatial_dimension); CSR node_to_elem; buildNode2Elements(mesh, node_to_elem, dimension); Array counter; + 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; ElementType facet_type = mesh.getFacetType(type); current_element.type = type; UInt nb_element = mesh.getNbElement(type, ghost_type); Array< std::vector > * element_to_subelement = mesh_facets.getElementToSubelementPointer(facet_type, ghost_type); Array * connectivity_facets = mesh_facets.getConnectivityPointer(facet_type, ghost_type); for (UInt el = 0; el < nb_element; ++el) { current_element.element = el; Matrix facets = mesh.getFacetConnectivity(el, type, ghost_type); UInt nb_nodes_per_facet = facets.cols(); for (UInt f = 0; f < facets.rows(); ++f) { Vector facet(nb_nodes_per_facet); for (UInt n = 0; n < nb_nodes_per_facet; ++n) facet(n) = facets(f, n); UInt first_node_nb_elements = node_to_elem.getNbCols(facets(f, 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::iterator first_node_elements = node_to_elem.begin(facet(0)); CSR::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::iterator node_elements_begin = node_to_elem.begin(facet(n)); CSR::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; Array connected_elements; 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 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.getSize(); ++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 & 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.getConnectivityPointer(facet_type, facet_ghost_type); element_to_subelement = mesh_facets.getElementToSubelementPointer(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 & subelement_to_element = *mesh_facets.getSubelementToElementPointer(type, loc_el.ghost_type); for (UInt f_in = 0; f_in < facets.rows(); ++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_facets.getConnectivityPointer(facet_type, facet_ghost_type); element_to_subelement = mesh_facets.getElementToSubelementPointer(facet_type, facet_ghost_type); } } } } } } } } - AKANTU_DEBUG_OUT(); + // restore the parent of mesh_facet + mesh_facets.defineMeshParent(mesh_facets_parent); + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::renumberMeshNodes(Mesh & mesh, UInt * local_connectivities, UInt nb_local_element, UInt nb_ghost_element, ElementType type, Array & old_nodes_numbers) { AKANTU_DEBUG_IN(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); std::map 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::iterator it = renumbering_map.begin(); std::map::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(); /// copy the renumbered connectivity to the right place Array * local_conn = mesh.getConnectivityPointer(type); local_conn->resize(nb_local_element); memcpy(local_conn->storage(), local_connectivities, nb_local_element * nb_nodes_per_element * sizeof(UInt)); Array * ghost_conn = mesh.getConnectivityPointer(type, _ghost); ghost_conn->resize(nb_ghost_element); memcpy(ghost_conn->storage(), local_connectivities + nb_local_element * nb_nodes_per_element, nb_ghost_element * nb_nodes_per_element * sizeof(UInt)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::renumberNodesInConnectivity(UInt * list_nodes, UInt nb_nodes, std::map & renumbering_map) { AKANTU_DEBUG_IN(); UInt * connectivity = list_nodes; UInt new_node_num = renumbering_map.size(); for (UInt n = 0; n < nb_nodes; ++n, ++connectivity) { UInt & node = *connectivity; std::map::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 renumbering_map; RemovedNodesEvent remove_nodes(mesh); Array & 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); const Array & connectivity_vect = mesh.getConnectivity(type, ghost_type); UInt nb_element(connectivity_vect.getSize()); UInt * connectivity = connectivity_vect.storage(); renumberNodesInConnectivity (connectivity, nb_element*nb_nodes_per_element, renumbering_map); } } Array & new_numbering = remove_nodes.getNewNumbering(); std::fill(new_numbering.begin(), new_numbering.end(), UInt(-1)); std::map::iterator it = renumbering_map.begin(); std::map::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(); } /* -------------------------------------------------------------------------- */ void MeshUtils::insertCohesiveElements(Mesh & mesh, Mesh & mesh_facets, const ByElementTypeArray & facet_insertion, Array & doubled_nodes, Array & new_elements) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); if (updateFacetToDouble(mesh_facets, facet_insertion)) { if (spatial_dimension == 1) { doublePointFacet(mesh, mesh_facets, doubled_nodes); } else { doubleFacet(mesh, mesh_facets, spatial_dimension - 1, doubled_nodes, true); findSubfacetToDouble(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(mesh, mesh_facets); doubleSubfacet<3>(mesh, mesh_facets, doubled_nodes); } } updateCohesiveData(mesh, mesh_facets, new_elements); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::doubleNodes(Mesh & mesh, const Array & old_nodes, Array & doubled_nodes) { AKANTU_DEBUG_IN(); Array & position = mesh.getNodes(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt old_nb_nodes = position.getSize(); UInt new_nb_nodes = old_nb_nodes + old_nodes.getSize(); UInt old_nb_doubled_nodes = doubled_nodes.getSize(); UInt new_nb_doubled_nodes = old_nb_doubled_nodes + old_nodes.getSize(); position.resize(new_nb_nodes); doubled_nodes.resize(new_nb_doubled_nodes); Array::iterator > position_begin = position.begin(spatial_dimension); for (UInt n = 0; n < old_nodes.getSize(); ++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 & 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 & f_to_double = mesh_facets.getData("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 > * f_to_subfacet = NULL; Array & subfacet_to_facet = mesh_facets.getSubelementToElement(type_facet, gt_facet); Array & 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::iterator > subfacet_to_facet_begin = subfacet_to_facet.begin(nb_subfacet_per_facet); Array::iterator > 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(mesh, mesh_facets, type_facet, gt_facet, doubled_nodes); } else updateQuadraticSegments(mesh, mesh_facets, type_facet, gt_facet, doubled_nodes); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool MeshUtils::updateFacetToDouble(Mesh & mesh_facets, const ByElementTypeArray & facet_insertion) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh_facets.getSpatialDimension(); bool facets_to_double = false; 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 & f_insertion = facet_insertion(type_facet, gt_facet); Array & f_to_double = mesh_facets.getData("facet_to_double", type_facet, gt_facet); Array< std::vector > & 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 * facet_to_element = NULL; for (UInt f = 0; f < f_insertion.getSize(); ++f) { if (f_insertion(f) == false) continue; facets_to_double = true; if (element_to_facet(f)[1].type == _not_defined || element_to_facet(f)[1].kind == _ek_cohesive) { 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 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 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("facet_to_double", type, gt, 1, false); mesh_facets.getDataPointer > ("facets_to_subfacet_double", type, gt, 1, false); mesh_facets.getDataPointer > ("elements_to_subfacet_double", type, gt, 1, false); mesh_facets.getDataPointer > ("subfacets_to_subsubfacet_double", type, gt, 1, false); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template 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 & f_to_double = mesh_facets.getData("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 * conn_subfacet = NULL; Array * sf_to_double = NULL; Array > * sf_to_subfacet_double = NULL; Array > * f_to_subfacet_double = NULL; Array > * 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 & subfacet_to_facet = mesh_facets.getSubelementToElement(type_facet, gt_facet); Array< std::vector > & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); Array * 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_list; std::vector facet_list; std::vector * subfacet_list; if (subsubfacet_mode) subfacet_list = new std::vector; /// map to filter subfacets Array< std::vector > * 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("facet_to_double", type_subfacet, gt_subfacet); f_to_subfacet_double = & mesh_facets.getData >("facets_to_subfacet_double", type_subfacet, gt_subfacet); el_to_subfacet_double = & mesh_facets.getData >("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("facet_to_double", type_subsubfacet, gt_subsubfacet); sf_to_subfacet_double = & mesh_facets.getData >("subfacets_to_subsubfacet_double", type_subsubfacet, gt_subsubfacet); f_to_subfacet_double = & mesh_facets.getData >("facets_to_subfacet_double", type_subsubfacet, gt_subsubfacet); el_to_subfacet_double = & mesh_facets.getData >("elements_to_subfacet_double", type_subsubfacet, gt_subsubfacet); facet_to_subfacet = & mesh_facets.getElementToSubelement(type_subsubfacet, gt_subsubfacet); } UInt global_ssf = subsubfacet.element; Vector 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(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 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(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(); } /* -------------------------------------------------------------------------- */ void MeshUtils::updateCohesiveData(Mesh & mesh, Mesh & mesh_facets, Array & new_elements) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); bool third_dimension = spatial_dimension == 3; 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 & f_to_double = mesh_facets.getData("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 = FEM::getCohesiveElementType(type_facet); Array * facet_to_coh_element = mesh_facets.getSubelementToElementPointer(type_cohesive, gt_facet); Array & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); Array * conn_cohesive = mesh.getConnectivityPointer(type_cohesive, gt_facet); UInt nb_nodes_per_facet = Mesh::getNbNodesPerElement(type_facet); Array< std::vector > & 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(); } /* -------------------------------------------------------------------------- */ void MeshUtils::doublePointFacet(Mesh & mesh, Mesh & mesh_facets, Array & doubled_nodes) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); if (spatial_dimension != 1) return; Array & 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 & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); Array< std::vector > & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); const Array & f_to_double = mesh_facets.getData("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 & 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 void MeshUtils::updateQuadraticSegments(Mesh & mesh, Mesh & mesh_facets, ElementType type_facet, GhostType gt_facet, Array & doubled_nodes) { AKANTU_DEBUG_IN(); if (type_facet != _segment_3) return; Array & f_to_double = mesh_facets.getData("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 & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); Array< std::vector > & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); /// this ones matter only for segments in 3D Array< std::vector > * el_to_subfacet_double = NULL; Array< std::vector > * f_to_subfacet_double = NULL; if (third_dim_segments) { el_to_subfacet_double = & mesh_facets.getData >("elements_to_subfacet_double", type_facet, gt_facet); f_to_subfacet_double = & mesh_facets.getData >("facets_to_subfacet_double", type_facet, gt_facet); } Array middle_nodes; Array subfacets; 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); subfacets.push_back(facet); } } UInt old_nb_doubled_nodes = doubled_nodes.getSize(); doubleNodes(mesh, middle_nodes, doubled_nodes); for (UInt n = old_nb_doubled_nodes; n < doubled_nodes.getSize(); ++n) { UInt old_node = doubled_nodes(n, 0); UInt new_node = doubled_nodes(n, 1); UInt sf = subfacets(n - old_nb_doubled_nodes); UInt new_facet = old_nb_facet + sf; 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)(sf), &(*f_to_subfacet_double)(sf)); } else { updateElementalConnectivity(mesh, old_node, new_node, element_to_facet(new_facet)); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::updateSubfacetToFacet(Mesh & mesh_facets, ElementType type_subfacet, GhostType gt_subfacet, bool facet_mode) { AKANTU_DEBUG_IN(); Array & sf_to_double = mesh_facets.getData("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 * 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 > * facet_list = NULL; if (facet_mode) facet_list = & mesh_facets.getData >("facets_to_subfacet_double", type_subfacet, gt_subfacet); else facet_list = & mesh_facets.getData >("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 & sf_to_double = mesh_facets.getData("facet_to_double", type_subfacet, gt_subfacet); UInt nb_subfacet_to_double = sf_to_double.getSize(); Array< std::vector > & facet_to_subfacet = mesh_facets.getElementToSubelement(type_subfacet, gt_subfacet); Array< std::vector > * facet_to_subfacet_double = NULL; if (facet_mode) { facet_to_subfacet_double = & mesh_facets.getData >("facets_to_subfacet_double", type_subfacet, gt_subfacet); } else { facet_to_subfacet_double = & mesh_facets.getData >("subfacets_to_subsubfacet_double", type_subfacet, gt_subfacet); } for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) facet_to_subfacet.push_back((*facet_to_subfacet_double)(sf)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MeshUtils::doubleSubfacet(Mesh & mesh, Mesh & mesh_facets, Array & 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 & sf_to_double = mesh_facets.getData("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 & 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); Array 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 > & f_to_subfacet_double = mesh_facets.getData >("facets_to_subfacet_double", type_subfacet, gt_subfacet); Array > & el_to_subfacet_double = mesh_facets.getData >("elements_to_subfacet_double", type_subfacet, gt_subfacet); Array > * sf_to_subfacet_double = NULL; if (spatial_dimension == 3) sf_to_subfacet_double = & mesh_facets.getData >("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 ByElementTypeUInt & global_connectivity, GhostType gt_facet) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh_facets.getSpatialDimension(); Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); /// loop on every ghost facet for(; it != end; ++it) { ElementType type_facet = *it; Array & connectivity = mesh_facets.getConnectivity(type_facet, gt_facet); const Array & g_connectivity = global_connectivity(type_facet, gt_facet); Array > & el_to_f = mesh_facets.getElementToSubelement(type_facet, gt_facet); Array & 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)); /// get global connectivity for local mesh Array global_conn_tmp(nb_facet, nb_nodes_per_facet); mesh_facets.getGlobalConnectivity(global_conn_tmp, type_facet, gt_facet); Array::iterator > conn_it = connectivity.begin(nb_nodes_per_facet); Array::iterator > gconn_tmp_it = global_conn_tmp.begin(nb_nodes_per_facet); Array::const_iterator > conn_glob_it = g_connectivity.begin(nb_nodes_per_facet); Array::iterator > subf_to_f = subfacet_to_facet.begin(nb_subfacet_per_facet); UInt * conn_tmp_pointer = new UInt[nb_nodes_per_facet]; Vector conn_tmp(conn_tmp_pointer, nb_nodes_per_facet); Element el_tmp; Element * subf_tmp_pointer = new Element[nb_subfacet_per_facet]; Vector 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 & gconn_tmp = *gconn_tmp_it; const Vector & conn_glob = *conn_glob_it; Vector & 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_WARNING("There are not facets, add them in the mesh file or call the buildFacet method."); return; } UInt spatial_dimension = mesh.getSpatialDimension(); ByElementTypeReal barycenters("barycenter_tmp", mesh.getID()); mesh.initByElementTypeArray(barycenters, spatial_dimension, _all_dimensions); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { Mesh::type_iterator it = mesh.firstType(_all_dimensions, *gt); Mesh::type_iterator end = mesh.lastType(_all_dimensions, *gt); for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, *gt); Array & barycenters_arr = barycenters(*it, *gt); barycenters_arr.resize(nb_element); Array::vector_iterator bary = barycenters_arr.begin(spatial_dimension); Array::vector_iterator bary_end = barycenters_arr.end(spatial_dimension); for (UInt el = 0; bary != bary_end; ++bary, ++el) { mesh.getBarycenter(el, *it, bary->storage(), *gt); } } } for(Int sp(spatial_dimension); sp >= 1; --sp) { if(mesh.getNbElement(sp) == 0) continue; for (ghost_type_t::iterator git = ghost_type_t::begin(); git != ghost_type_t::end(); ++git) { Mesh::type_iterator tit = mesh.firstType(sp, *git); Mesh::type_iterator tend = mesh.lastType(sp, *git); for (;tit != tend; ++tit) { mesh.getSubelementToElementPointer(*tit, *git)->resize(mesh.getNbElement(*tit, *git)); mesh.getSubelementToElement(*tit, *git).clear(); } tit = mesh.firstType(sp - 1, *git); tend = mesh.lastType(sp - 1, *git); for (;tit != tend; ++tit) { mesh.getElementToSubelementPointer(*tit, *git)->resize(mesh.getNbElement(*tit, *git)); mesh.getElementToSubelement(*tit, *git).clear(); } } CSR nodes_to_elements; buildNode2Elements(mesh, nodes_to_elements, sp); Element facet_element; for (ghost_type_t::iterator git = ghost_type_t::begin(); git != ghost_type_t::end(); ++git) { Mesh::type_iterator tit = mesh.firstType(sp - 1, *git); Mesh::type_iterator tend = mesh.lastType(sp - 1, *git); facet_element.ghost_type = *git; for (;tit != tend; ++tit) { facet_element.type = *tit; Array< std::vector > & element_to_subelement = mesh.getElementToSubelement(*tit, *git); const Array & connectivity = mesh.getConnectivity(*tit, *git); Array::const_iterator< Vector > fit = connectivity.begin(mesh.getNbNodesPerElement(*tit)); Array::const_iterator< Vector > fend = connectivity.end(mesh.getNbNodesPerElement(*tit)); UInt fid = 0; for (;fit != fend; ++fit, ++fid) { const Vector & facet = *fit; facet_element.element = fid; std::map element_seen_counter; UInt nb_nodes_per_facet = mesh.getNbNodesPerElement(Mesh::getP1ElementType(*tit)); for (UInt n(0); n < nb_nodes_per_facet; ++n) { CSR::iterator eit = nodes_to_elements.begin(facet(n)); CSR::iterator eend = nodes_to_elements.end(facet(n)); for(;eit != eend; ++eit) { Element & elem = *eit; std::map::iterator cit = element_seen_counter.find(elem); if(cit != element_seen_counter.end()) { cit->second++; } else { element_seen_counter[elem] = 1; } } } std::vector connected_elements; std::map::iterator cit = element_seen_counter.begin(); std::map::iterator cend = element_seen_counter.end(); for(;cit != cend; ++cit) { if(cit->second == nb_nodes_per_facet) connected_elements.push_back(cit->first); } std::vector::iterator ceit = connected_elements.begin(); std::vector::iterator 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 & subelement_to_element = *(mesh.getSubelementToElementPointer(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!!"); subelement_to_element(elem.element, f) = facet_element; } } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template bool MeshUtils::findElementsAroundSubfacet(const Mesh & mesh, const Mesh & mesh_facets, const Element & starting_element, const Element & end_facet, const Vector & subfacet_connectivity, std::vector & elem_list, std::vector & facet_list, std::vector * subfacet_list) { AKANTU_DEBUG_IN(); /// preallocated stuff before starting bool facet_matched = false; elem_list.resize(0); facet_list.resize(0); if (third_dim_points) subfacet_list->resize(0); elem_list.push_back(starting_element); const Array * facet_connectivity = NULL; const Array * sf_connectivity = NULL; const Array * facet_to_element = NULL; const Array * 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_to_facet = NULL; const Element * opposing_el = NULL; Array elements_to_check; elements_to_check.resize(0); elements_to_check.push_back(starting_element); /// keep going until there are elements to check while (elements_to_check.getSize() != 0) { /// loop over each element to check for (UInt el = 0; el < elements_to_check.getSize(); ++el) { Element & current_el = elements_to_check(el); 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_back(*opposing_el); elem_list.push_back(*opposing_el); #ifndef AKANTU_NDEBUG const Array & 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.erase(el); } } AKANTU_DEBUG_OUT(); return facet_matched; } __END_AKANTU__ // LocalWords: ElementType diff --git a/src/mesh_utils/mesh_utils.hh b/src/mesh_utils/mesh_utils.hh index fe2fb8b35..42c7c9ad8 100644 --- a/src/mesh_utils/mesh_utils.hh +++ b/src/mesh_utils/mesh_utils.hh @@ -1,263 +1,272 @@ /** * @file mesh_utils.hh * * @author Guillaume Anciaux * @author David Simon Kammer * @author Leonardo Snozzi * @author Nicolas Richart * @author Marco Vocialta * * @date Fri Aug 20 12:19:44 2010 * * @brief All mesh utils necessary for various tasks * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "aka_csr.hh" #include "distributed_synchronizer.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_UTILS_HH__ #define __AKANTU_MESH_UTILS_HH__ /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class MeshUtils { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshUtils(); virtual ~MeshUtils(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// build a CSR that contains for each node the linearized number of /// the connected elements of a given spatial dimension static void buildNode2Elements(const Mesh & mesh, CSR & node_to_elem, UInt spatial_dimension = _all_dimensions); /// build a CSR that contains for each node the list of connected /// elements ofr a given spatial dimension static void buildNode2Elements(const Mesh & mesh, CSR & node_to_elem, UInt spatial_dimension = _all_dimensions); /// build a CSR that contains for each node the number of /// the connected elements of a given ElementType static void buildNode2ElementsByElementType(const Mesh & mesh, CSR & node_to_elem, const ElementType & type, const GhostType & ghost_type = _not_ghost); /// build the facets elements on the boundaries of a mesh static void buildFacets(Mesh & mesh); + /// build all the facets elements: boundary and internals and store them in + /// the mesh_facets for element of dimension from_dimension to to_dimension + static void buildAllFacets(const Mesh & mesh, + Mesh & mesh_facets, + UInt from_dimension, + UInt to_dimension, + DistributedSynchronizer * synchronizer = NULL); + /// build all the facets elements: boundary and internals and store them in /// the mesh_facets static void buildAllFacets(const Mesh & mesh, Mesh & mesh_facets, UInt to_dimension = 0, DistributedSynchronizer * synchronizer = NULL); + /// build facets for a given spatial dimension static void buildFacetsDimension(const Mesh & mesh, Mesh & mesh_facets, bool boundary_only, UInt dimension, const ByElementTypeUInt * prank_to_element = NULL); /// take the local_connectivity array as the array of local and ghost /// connectivity, renumber the nodes and set the connectivity of the mesh static void renumberMeshNodes(Mesh & mesh, UInt * local_connectivities, UInt nb_local_element, UInt nb_ghost_element, ElementType type, Array & old_nodes); /// compute pbc pair for on given a direction static void computePBCMap(const Mesh & mymesh, const UInt dir, std::map & pbc_pair); /// compute pbc pair for a surface pair static void computePBCMap(const Mesh & mymesh, const std::pair & surface_pair, const ElementType type, std::map & pbc_pair); /// create a multimap of nodes per surfaces static void buildNodesPerSurface(const Mesh & mesh, CSR & nodes_per_surface); /// remove not connected nodes /!\ this functions renumbers the nodes. static void purifyMesh(Mesh & mesh); /// function to insert cohesive elements on the selected facets static void insertCohesiveElements(Mesh & mesh, Mesh & mesh_facets, const ByElementTypeArray & facet_insertion, Array & doubled_nodes, Array & new_elements); /// fill the subelement to element and the elements to subelements data static void fillElementToSubElementsData(Mesh & mesh); /// flip facets based on global connectivity static void flipFacets(Mesh & mesh_facets, const ByElementTypeUInt & global_connectivity, GhostType gt_facet); /// provide list of elements around a node and check if a given /// facet is reached template static bool findElementsAroundSubfacet(const Mesh & mesh, const Mesh & mesh_facets, const Element & starting_element, const Element & end_facet, const Vector & subfacet_connectivity, std::vector & elem_list, std::vector & facet_list, std::vector * subfacet_list = NULL); /// function to check if a node belongs to a given element static inline bool hasElement(const Array & connectivity, const Element & el, const Vector & nodes); /// reset facet_to_double arrays in the Mesh static void resetFacetToDouble(Mesh & mesh_facets); private: /// match pairs that are on the associated pbc's static void matchPBCPairs(const Mesh & mymesh, const UInt dir, std::vector & selected_left, std::vector & selected_right, std::map & pbc_pair); /// function used by all the renumbering functions static void renumberNodesInConnectivity(UInt * list_nodes, UInt nb_nodes, std::map & renumbering_map); /// update facet_to_subfacet static void updateFacetToSubfacet(Mesh & mesh_facets, ElementType type_subfacet, GhostType gt_subfacet, bool facet_mode); /// update subfacet_to_facet static void updateSubfacetToFacet(Mesh & mesh_facets, ElementType type_subfacet, GhostType gt_subfacet, bool facet_mode); /// function to double a given facet and update the list of doubled /// nodes static void doubleFacet(Mesh & mesh, Mesh & mesh_facets, UInt facet_dimension, Array & doubled_nodes, bool facet_mode); /// function to double a subfacet given start and end index for /// local facet_to_subfacet vector, and update the list of doubled /// nodes template static void doubleSubfacet(Mesh & mesh, Mesh & mesh_facets, Array & doubled_nodes); /// double a node static void doubleNodes(Mesh & mesh, const Array & old_nodes, Array & doubled_nodes); /// fill facet_to_double array in the mesh static bool updateFacetToDouble(Mesh & mesh_facets, const ByElementTypeArray & facet_insertion); /// find subfacets to be doubled template static void findSubfacetToDouble(Mesh & mesh, Mesh & mesh_facets); /// double facets (points) in 1D static void doublePointFacet(Mesh & mesh, Mesh & mesh_facets, Array & doubled_nodes); /// update cohesive element data static void updateCohesiveData(Mesh & mesh, Mesh & mesh_facets, Array & new_elements); /// update elemental connectivity after doubling a node inline static void updateElementalConnectivity(Mesh & mesh, UInt old_node, UInt new_node, const std::vector & element_list, const std::vector * facet_list = NULL); /// double middle nodes if facets are _segment_3 template static void updateQuadraticSegments(Mesh & mesh, Mesh & mesh_facets, ElementType type_facet, GhostType gt_facet, Array & doubled_nodes); /// remove elements on a vector inline static bool removeElementsInVector(const std::vector & elem_to_remove, std::vector & elem_list); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "mesh_utils_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_MESH_UTILS_HH__ */ diff --git a/src/model/heat_transfer/heat_transfer_model.cc b/src/model/heat_transfer/heat_transfer_model.cc index 7cc862c7c..195b54fc5 100644 --- a/src/model/heat_transfer/heat_transfer_model.cc +++ b/src/model/heat_transfer/heat_transfer_model.cc @@ -1,957 +1,956 @@ /** * @file heat_transfer_model.cc * * @author Rui Wang * @author Srinivasa Babu Ramisetti * @author Guillaume Anciaux * @author Nicolas Richart * @author David Simon Kammer * @author Lucas Frerot * * @date Sun May 01 19:14:43 2011 * * @brief Implementation of HeatTransferModel class * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "heat_transfer_model.hh" #include "aka_math.hh" #include "aka_common.hh" #include "fem_template.hh" #include "mesh.hh" #include "static_communicator.hh" #include "parser.hh" #include "generalized_trapezoidal.hh" #ifdef AKANTU_USE_MUMPS #include "solver_mumps.hh" #endif #ifdef AKANTU_USE_IOHELPER # include "dumper_paraview.hh" # include "dumper_iohelper_tmpl.hh" # include "dumper_iohelper_tmpl_homogenizing_field.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ const HeatTransferModelOptions default_heat_transfer_model_options(_explicit_lumped_capacity); /* -------------------------------------------------------------------------- */ HeatTransferModel::HeatTransferModel(Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id) : Model(mesh, dim, id, memory_id), Dumpable(), Parsable(_st_heat, id), integrator(new ForwardEuler()), stiffness_matrix(NULL), jacobian_matrix(NULL), temperature_gradient ("temperature_gradient", id), temperature_on_qpoints ("temperature_on_qpoints", id), conductivity_on_qpoints ("conductivity_on_qpoints", id), k_gradt_on_qpoints ("k_gradt_on_qpoints", id), int_bt_k_gT ("int_bt_k_gT", id), bt_k_gT ("bt_k_gT", id), conductivity(spatial_dimension, spatial_dimension), thermal_energy ("thermal_energy", id) { AKANTU_DEBUG_IN(); createSynchronizerRegistry(this); std::stringstream sstr; sstr << id << ":fem"; registerFEMObject(sstr.str(), mesh,spatial_dimension); this->temperature= NULL; this->residual = NULL; this->boundary = NULL; #ifdef AKANTU_USE_IOHELPER this->registerDumper("paraview_all", id, true); this->addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_regular); #endif this->registerParam("conductivity" , conductivity , _pat_parsmod); this->registerParam("conductivity_variation", conductivity_variation, 0., _pat_parsmod); this->registerParam("temperature_reference" , T_ref , 0., _pat_parsmod); this->registerParam("capacity" , capacity , _pat_parsmod); this->registerParam("density" , density , _pat_parsmod); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initModel() { getFEM().initShapeFunctions(_not_ghost); getFEM().initShapeFunctions(_ghost); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initParallel(MeshPartition * partition, DataAccessor * data_accessor) { AKANTU_DEBUG_IN(); if (data_accessor == NULL) data_accessor = this; Synchronizer & synch_parallel = createParallelSynch(partition,data_accessor); synch_registry->registerSynchronizer(synch_parallel, _gst_htm_capacity); synch_registry->registerSynchronizer(synch_parallel, _gst_htm_temperature); synch_registry->registerSynchronizer(synch_parallel, _gst_htm_gradient_temperature); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initPBC() { AKANTU_DEBUG_IN(); Model::initPBC(); PBCSynchronizer * synch = new PBCSynchronizer(pbc_pair); synch_registry->registerSynchronizer(*synch, _gst_htm_capacity); synch_registry->registerSynchronizer(*synch, _gst_htm_temperature); changeLocalEquationNumberForPBC(pbc_pair,1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initArrays() { AKANTU_DEBUG_IN(); UInt nb_nodes = getFEM().getMesh().getNbNodes(); std::stringstream sstr_temp; sstr_temp << Model::id << ":temperature"; std::stringstream sstr_temp_rate; sstr_temp_rate << Model::id << ":temperature_rate"; std::stringstream sstr_inc; sstr_inc << Model::id << ":increment"; std::stringstream sstr_ext_flx; sstr_ext_flx << Model::id << ":external_flux"; std::stringstream sstr_residual; sstr_residual << Model::id << ":residual"; std::stringstream sstr_lump; sstr_lump << Model::id << ":lumped"; std::stringstream sstr_boun; sstr_boun << Model::id << ":boundary"; temperature = &(alloc(sstr_temp.str(), nb_nodes, 1, REAL_INIT_VALUE)); temperature_rate = &(alloc(sstr_temp_rate.str(), nb_nodes, 1, REAL_INIT_VALUE)); increment = &(alloc(sstr_inc.str(), nb_nodes, 1, REAL_INIT_VALUE)); external_heat_rate = &(alloc(sstr_ext_flx.str(), nb_nodes, 1, REAL_INIT_VALUE)); residual = &(alloc(sstr_residual.str(), nb_nodes, 1, REAL_INIT_VALUE)); capacity_lumped = &(alloc(sstr_lump.str(), nb_nodes, 1, REAL_INIT_VALUE)); boundary = &(alloc(sstr_boun.str(), nb_nodes, 1, false)); Mesh::ConnectivityTypeList::const_iterator it; /* -------------------------------------------------------------------------- */ // byelementtype vectors getFEM().getMesh().initByElementTypeArray(temperature_on_qpoints, 1, spatial_dimension); getFEM().getMesh().initByElementTypeArray(temperature_gradient, spatial_dimension, spatial_dimension); getFEM().getMesh().initByElementTypeArray(conductivity_on_qpoints, spatial_dimension*spatial_dimension, spatial_dimension); getFEM().getMesh().initByElementTypeArray(k_gradt_on_qpoints, spatial_dimension, spatial_dimension); getFEM().getMesh().initByElementTypeArray(bt_k_gT, 1, spatial_dimension,true); getFEM().getMesh().initByElementTypeArray(int_bt_k_gT, 1, spatial_dimension,true); getFEM().getMesh().initByElementTypeArray(thermal_energy, 1, spatial_dimension); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; const Mesh::ConnectivityTypeList & type_list = getFEM().getMesh().getConnectivityTypeList(gt); for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_element = getFEM().getMesh().getNbElement(*it, gt); UInt nb_quad_points = this->getFEM().getNbQuadraturePoints(*it, gt) * nb_element; temperature_on_qpoints(*it, gt).resize(nb_quad_points); temperature_on_qpoints(*it, gt).clear(); temperature_gradient(*it, gt).resize(nb_quad_points); temperature_gradient(*it, gt).clear(); conductivity_on_qpoints(*it, gt).resize(nb_quad_points); conductivity_on_qpoints(*it, gt).clear(); k_gradt_on_qpoints(*it, gt).resize(nb_quad_points); k_gradt_on_qpoints(*it, gt).clear(); bt_k_gT(*it, gt).resize(nb_quad_points); bt_k_gT(*it, gt).clear(); int_bt_k_gT(*it, gt).resize(nb_element); int_bt_k_gT(*it, gt).clear(); thermal_energy(*it, gt).resize(nb_element); thermal_energy(*it, gt).clear(); } } /* -------------------------------------------------------------------------- */ dof_synchronizer = new DOFSynchronizer(getFEM().getMesh(),1); dof_synchronizer->initLocalDOFEquationNumbers(); dof_synchronizer->initGlobalDOFEquationNumbers(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initSolver(__attribute__((unused)) SolverOptions & options) { #if !defined(AKANTU_USE_MUMPS) // or other solver in the future \todo add AKANTU_HAS_SOLVER in CMake AKANTU_DEBUG_ERROR("You should at least activate one solver."); #else UInt nb_global_nodes = mesh.getNbGlobalNodes(); delete jacobian_matrix; std::stringstream sstr; sstr << Memory::id << ":jacobian_matrix"; jacobian_matrix = new SparseMatrix(nb_global_nodes, _symmetric, 1, sstr.str(), memory_id); jacobian_matrix->buildProfile(mesh, *dof_synchronizer); delete stiffness_matrix; std::stringstream sstr_sti; sstr_sti << Memory::id << ":stiffness_matrix"; stiffness_matrix = new SparseMatrix(*jacobian_matrix, sstr_sti.str(), memory_id); #ifdef AKANTU_USE_MUMPS std::stringstream sstr_solv; sstr_solv << Memory::id << ":solver"; solver = new SolverMumps(*jacobian_matrix, sstr_solv.str()); dof_synchronizer->initScatterGatherCommunicationScheme(); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif //AKANTU_USE_MUMPS if(solver) solver->initialize(options); #endif //AKANTU_HAS_SOLVER } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initImplicit(SolverOptions & solver_options) { method = _static; initSolver(solver_options); } /* -------------------------------------------------------------------------- */ HeatTransferModel::~HeatTransferModel() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::assembleCapacityLumped(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); FEM & fem = getFEM(); const Mesh::ConnectivityTypeList & type_list = fem.getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_element = getFEM().getMesh().getNbElement(*it,ghost_type); UInt nb_quadrature_points = getFEM().getNbQuadraturePoints(*it, ghost_type); Array rho_1 (nb_element * nb_quadrature_points,1, capacity * density); fem.assembleFieldLumped(rho_1,1,*capacity_lumped, dof_synchronizer->getLocalDOFEquationNumbers(), *it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::assembleCapacityLumped() { AKANTU_DEBUG_IN(); capacity_lumped->clear(); assembleCapacityLumped(_not_ghost); assembleCapacityLumped(_ghost); getSynchronizerRegistry().synchronize(_gst_htm_capacity); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::updateResidual() { AKANTU_DEBUG_IN(); /// @f$ r = q_{ext} - q_{int} - C \dot T @f$ // start synchronization synch_registry->asynchronousSynchronize(_gst_htm_temperature); // finalize communications synch_registry->waitEndSynchronize(_gst_htm_temperature); //clear the array /// first @f$ r = q_{ext} @f$ // residual->clear(); residual->copy(*external_heat_rate); /// then @f$ r -= q_{int} @f$ // update the not ghost ones updateResidual(_not_ghost); // update for the received ghosts updateResidual(_ghost); /* if (method == _explicit_lumped_capacity) { this->solveExplicitLumped(); }*/ AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::assembleStiffnessMatrix() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the new stiffness matrix."); stiffness_matrix->clear(); switch(mesh.getSpatialDimension()) { case 1: this->assembleStiffnessMatrix<1>(_not_ghost); break; case 2: this->assembleStiffnessMatrix<2>(_not_ghost); break; case 3: this->assembleStiffnessMatrix<3>(_not_ghost); break; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void HeatTransferModel::assembleStiffnessMatrix(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Mesh & mesh = this->getFEM().getMesh(); 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) { this->assembleStiffnessMatrix(*it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void HeatTransferModel::assembleStiffnessMatrix(const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); SparseMatrix & K = *stiffness_matrix; const Array & shapes_derivatives = this->getFEM().getShapesDerivatives(type, ghost_type); UInt nb_element = mesh.getNbElement(type, ghost_type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = getFEM().getNbQuadraturePoints(type, ghost_type); /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_d_b_size = nb_nodes_per_element; Array * bt_d_b = new Array(nb_element * nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B"); Matrix Bt_D(nb_nodes_per_element, dim); Array::const_iterator< Matrix > shapes_derivatives_it = shapes_derivatives.begin(dim, nb_nodes_per_element); Array::iterator< Matrix > Bt_D_B_it = bt_d_b->begin(bt_d_b_size, bt_d_b_size); this->computeConductivityOnQuadPoints(ghost_type); Array::iterator< Matrix > D_it = conductivity_on_qpoints(type, ghost_type).begin(dim, dim); Array::iterator< Matrix > D_end = conductivity_on_qpoints(type, ghost_type).end(dim, dim); for (; D_it != D_end; ++D_it, ++Bt_D_B_it, ++shapes_derivatives_it) { Matrix & D = *D_it; const Matrix & B = *shapes_derivatives_it; Matrix & Bt_D_B = *Bt_D_B_it; Bt_D.mul(B, D); Bt_D_B.mul(Bt_D, B); } /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array * K_e = new Array(nb_element, bt_d_b_size * bt_d_b_size, "K_e"); this->getFEM().integrate(*bt_d_b, *K_e, bt_d_b_size * bt_d_b_size, type, ghost_type); delete bt_d_b; this->getFEM().assembleMatrix(*K_e, K, 1, type, ghost_type); delete K_e; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::solveStatic() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving Ku = f"); AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, "You should first initialize the implicit solver and assemble the stiffness matrix"); UInt nb_nodes = temperature->getSize(); UInt nb_degree_of_freedom = temperature->getNbComponent() * nb_nodes; jacobian_matrix->copyContent(*stiffness_matrix); jacobian_matrix->applyBoundary(*boundary); increment->clear(); solver->setRHS(*residual); solver->solve(*increment); Real * increment_val = increment->storage(); Real * temperature_val = temperature->storage(); bool * boundary_val = boundary->storage(); for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++temperature_val, ++increment_val, ++boundary_val) { if (!(*boundary_val)) { *temperature_val += *increment_val; } else { *increment_val = 0.0; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::computeConductivityOnQuadPoints(const GhostType & ghost_type) { const Mesh::ConnectivityTypeList & type_list = this->getFEM().getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; Array & temperature_interpolated = temperature_on_qpoints(*it, ghost_type); //compute the temperature on quadrature points this->getFEM().interpolateOnQuadraturePoints(*temperature, temperature_interpolated, 1 ,*it,ghost_type); Array::matrix_iterator C_it = conductivity_on_qpoints(*it, ghost_type).begin(spatial_dimension, spatial_dimension); Array::matrix_iterator C_end = conductivity_on_qpoints(*it, ghost_type).end(spatial_dimension, spatial_dimension); Array::iterator T_it = temperature_interpolated.begin(); for (;C_it != C_end; ++C_it, ++T_it) { Matrix & C = *C_it; Real & T = *T_it; C = conductivity; Matrix variation(spatial_dimension, spatial_dimension, conductivity_variation * (T - T_ref)); C += conductivity_variation; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::computeKgradT(const GhostType & ghost_type) { computeConductivityOnQuadPoints(ghost_type); const Mesh::ConnectivityTypeList & type_list = this->getFEM().getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { const ElementType & type = *it; if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; Array & gradient = temperature_gradient(*it, ghost_type); this->getFEM().gradientOnQuadraturePoints(*temperature, gradient, 1 ,*it, ghost_type); Array::matrix_iterator C_it = conductivity_on_qpoints(*it, ghost_type).begin(spatial_dimension, spatial_dimension); Array::vector_iterator BT_it = gradient.begin(spatial_dimension); Array::vector_iterator k_BT_it = k_gradt_on_qpoints(type, ghost_type).begin(spatial_dimension); Array::vector_iterator k_BT_end = k_gradt_on_qpoints(type, ghost_type).end(spatial_dimension); for (;k_BT_it != k_BT_end; ++k_BT_it, ++BT_it, ++C_it) { Vector & k_BT = *k_BT_it; Vector & BT = *BT_it; Matrix & C = *C_it; k_BT.mul(C, BT); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::updateResidual(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); const Mesh::ConnectivityTypeList & type_list = this->getFEM().getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; Array & shapes_derivatives = const_cast &>(getFEM().getShapesDerivatives(*it,ghost_type)); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); // compute k \grad T computeKgradT(ghost_type); Array::vector_iterator k_BT_it = k_gradt_on_qpoints(*it,ghost_type).begin(spatial_dimension); Array::matrix_iterator B_it = shapes_derivatives.begin(spatial_dimension, nb_nodes_per_element); Array::vector_iterator Bt_k_BT_it = bt_k_gT(*it,ghost_type).begin(nb_nodes_per_element); Array::vector_iterator Bt_k_BT_end = bt_k_gT(*it,ghost_type).end(nb_nodes_per_element); for (;Bt_k_BT_it != Bt_k_BT_end; ++Bt_k_BT_it, ++B_it, ++k_BT_it) { Vector & k_BT = *k_BT_it; Vector & Bt_k_BT = *Bt_k_BT_it; Matrix & B = *B_it; Bt_k_BT.mul(B, k_BT); } this->getFEM().integrate(bt_k_gT(*it,ghost_type), int_bt_k_gT(*it,ghost_type), nb_nodes_per_element, *it,ghost_type); this->getFEM().assembleArray(int_bt_k_gT(*it,ghost_type), *residual, dof_synchronizer->getLocalDOFEquationNumbers(), 1, *it,ghost_type, empty_filter, -1); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::solveExplicitLumped() { AKANTU_DEBUG_IN(); /// finally @f$ r -= C \dot T @f$ // lumped C UInt nb_nodes = temperature_rate->getSize(); UInt nb_degree_of_freedom = temperature_rate->getNbComponent(); Real * capacity_val = capacity_lumped->storage(); Real * temp_rate_val = temperature_rate->storage(); Real * res_val = residual->storage(); bool * boundary_val = boundary->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { if(!(*boundary_val)) { *res_val -= *capacity_val * *temp_rate_val; } boundary_val++; res_val++; capacity_val++; temp_rate_val++; } #ifndef AKANTU_NDEBUG getSynchronizerRegistry().synchronize(akantu::_gst_htm_gradient_temperature); #endif capacity_val = capacity_lumped->storage(); res_val = residual->storage(); boundary_val = boundary->storage(); Real * inc = increment->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { if(!(*boundary_val)) { *inc = (*res_val / *capacity_val); } res_val++; boundary_val++; inc++; capacity_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::explicitPred() { AKANTU_DEBUG_IN(); integrator->integrationSchemePred(time_step, *temperature, *temperature_rate, *boundary); UInt nb_nodes = temperature->getSize(); UInt nb_degree_of_freedom = temperature->getNbComponent(); Real * temp = temperature->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n, ++temp) if(*temp < 0.) *temp = 0.; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::explicitCorr() { AKANTU_DEBUG_IN(); integrator->integrationSchemeCorrTempRate(time_step, *temperature, *temperature_rate, *boundary, *increment); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getStableTimeStep() { AKANTU_DEBUG_IN(); Real el_size; Real min_el_size = std::numeric_limits::max(); Real conductivitymax = conductivity(0, 0); //get the biggest parameter from k11 until k33// for(UInt i = 0; i < spatial_dimension; i++) for(UInt j = 0; j < spatial_dimension; j++) conductivitymax = std::max(conductivity(i, j), conductivitymax); const Mesh::ConnectivityTypeList & type_list = getFEM().getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(getFEM().getMesh().getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_nodes_per_element = getFEM().getMesh().getNbNodesPerElement(*it); Array coord(0, nb_nodes_per_element*spatial_dimension); FEM::extractNodalToElementField(getFEM().getMesh(), getFEM().getMesh().getNodes(), coord, *it, _not_ghost); Array::matrix_iterator el_coord = coord.begin(spatial_dimension, nb_nodes_per_element); UInt nb_element = getFEM().getMesh().getNbElement(*it); for (UInt el = 0; el < nb_element; ++el, ++el_coord) { el_size = getFEM().getElementInradius(*el_coord, *it); min_el_size = std::min(min_el_size, el_size); } AKANTU_DEBUG_INFO("The minimum element size : " << min_el_size << " and the max conductivity is : " << conductivitymax); } Real min_dt = 2 * min_el_size * min_el_size * density * capacity / conductivitymax; StaticCommunicator::getStaticCommunicator().allReduce(&min_dt, 1, _so_min); AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ void HeatTransferModel::readMaterials() { std::pair - sub_sect = parser.getSubSections(_st_heat); + sub_sect = getStaticParser().getSubSections(_st_heat); Parser::const_section_iterator it = sub_sect.first; const ParserSection & section = *it; this->parseSection(section); } /* -------------------------------------------------------------------------- */ -void HeatTransferModel::initFull(const std::string & material_file, const ModelOptions & options){ - Model::initFull(material_file, options); +void HeatTransferModel::initFull(const ModelOptions & options){ + Model::initFull(options); readMaterials(); const HeatTransferModelOptions & my_options = dynamic_cast(options); //initialize the vectors initArrays(); temperature->clear(); temperature_rate->clear(); external_heat_rate->clear(); method = my_options.analysis_method; if (method == _static) { initImplicit(); } } /* -------------------------------------------------------------------------- */ - void HeatTransferModel::initFEMBoundary(bool create_surface) { if(create_surface) MeshUtils::buildFacets(getFEM().getMesh()); FEM & fem_boundary = getFEMBoundary(); fem_boundary.initShapeFunctions(); fem_boundary.computeNormalsOnControlPoints(); } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::computeThermalEnergyByNode() { AKANTU_DEBUG_IN(); Real ethermal = 0.; Array::vector_iterator heat_rate_it = residual->begin(residual->getNbComponent()); Array::vector_iterator heat_rate_end = residual->end(residual->getNbComponent()); UInt n = 0; for(;heat_rate_it != heat_rate_end; ++heat_rate_it, ++n) { Real heat = 0; bool is_local_node = mesh.isLocalOrMasterNode(n); bool is_not_pbc_slave_node = !getIsPBCSlaveNode(n); bool count_node = is_local_node && is_not_pbc_slave_node; Vector & heat_rate = *heat_rate_it; for (UInt i = 0; i < heat_rate.size(); ++i) { if (count_node) heat += heat_rate[i] * time_step; } ethermal += heat; } StaticCommunicator::getStaticCommunicator().allReduce(ðermal, 1, _so_sum); AKANTU_DEBUG_OUT(); return ethermal; } /* -------------------------------------------------------------------------- */ template void HeatTransferModel::getThermalEnergy(iterator Eth, Array::const_iterator T_it, Array::const_iterator T_end) const { for(;T_it != T_end; ++T_it, ++Eth) { *Eth = capacity * density * *T_it; } } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getThermalEnergy(const ElementType & type, UInt index) { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = getFEM().getNbQuadraturePoints(type); Vector Eth_on_quarature_points(nb_quadrature_points); Array::iterator T_it = this->temperature_on_qpoints(type).begin(); T_it += index * nb_quadrature_points; Array::iterator T_end = T_it + nb_quadrature_points; getThermalEnergy(Eth_on_quarature_points.storage(), T_it, T_end); return getFEM().integrate(Eth_on_quarature_points, type, index); } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getThermalEnergy() { Real Eth = 0; Mesh & mesh = getFEM().getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension); for(; it != last_type; ++it) { UInt nb_element = getFEM().getMesh().getNbElement(*it, _not_ghost); UInt nb_quadrature_points = getFEM().getNbQuadraturePoints(*it, _not_ghost); Array Eth_per_quad(nb_element * nb_quadrature_points, 1); Array::iterator T_it = this->temperature_on_qpoints(*it).begin(); Array::iterator T_end = this->temperature_on_qpoints(*it).end(); getThermalEnergy(Eth_per_quad.begin(), T_it, T_end); Eth += getFEM().integrate(Eth_per_quad, *it); } return Eth; } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getEnergy(const std::string & id) { AKANTU_DEBUG_IN(); Real energy = 0; if("thermal") energy = getThermalEnergy(); // reduction sum over all processors StaticCommunicator::getStaticCommunicator().allReduce(&energy, 1, _so_sum); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getEnergy(const std::string & energy_id, const ElementType & type, UInt index) { AKANTU_DEBUG_IN(); Real energy = 0.; if("thermal") energy = getThermalEnergy(type, index); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #define IF_ADD_NODAL_FIELD(dumper_name, field, type, pad) \ if(field_id == BOOST_PP_STRINGIZE(field)) { \ DumperIOHelper::Field * f = \ new DumperIOHelper::NodalField(*field); \ if(pad) f->setPadding(3); \ internalAddDumpFieldToDumper(dumper_name, \ BOOST_PP_STRINGIZE(field), f); \ } else #define IF_ADD_ELEM_FIELD(dumper_name, field, type, pad) \ if(field_id == BOOST_PP_STRINGIZE(field)) { \ typedef DumperIOHelper::HomogenizedField Field; \ DumperIOHelper::Field * f = \ new Field(getFEM(), \ field, \ spatial_dimension, \ spatial_dimension, \ _not_ghost, \ _ek_regular); \ if(pad) f->setPadding(3); \ internalAddDumpFieldToDumper(dumper_name, \ BOOST_PP_STRINGIZE(field), f); \ } else #endif void HeatTransferModel::addDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id) { #ifdef AKANTU_USE_IOHELPER IF_ADD_NODAL_FIELD(dumper_name, temperature , Real, false) IF_ADD_NODAL_FIELD(dumper_name, temperature_rate , Real, false) IF_ADD_NODAL_FIELD(dumper_name, external_heat_rate, Real, false) IF_ADD_NODAL_FIELD(dumper_name, residual , Real, false) IF_ADD_NODAL_FIELD(dumper_name, capacity_lumped , Real, false) IF_ADD_NODAL_FIELD(dumper_name, boundary , bool, false) IF_ADD_ELEM_FIELD (dumper_name, temperature_gradient, Real, false) if(field_id == "partitions" ) { internalAddDumpFieldToDumper(dumper_name, field_id, new DumperIOHelper::ElementPartitionField<>(mesh, spatial_dimension, _not_ghost, _ek_regular)); } else { AKANTU_DEBUG_ERROR("Field " << field_id << " does not exists in the model " << Model::id); } #endif } /* -------------------------------------------------------------------------- */ void HeatTransferModel::addDumpFieldVectorToDumper(const std::string & dumper_name, const std::string & field_id) { #ifdef AKANTU_USE_IOHELPER IF_ADD_ELEM_FIELD (dumper_name, temperature_gradient, Real, false) { AKANTU_DEBUG_ERROR("Field " << field_id << " does not exists in the model " << Model::id << " or is not dumpable as a vector"); } #endif } /* -------------------------------------------------------------------------- */ void HeatTransferModel::addDumpFieldTensorToDumper(const std::string & dumper_name, const std::string & field_id) { #ifdef AKANTU_USE_IOHELPER AKANTU_DEBUG_ERROR("Field " << field_id << " does not exists in the model " << Model::id << " or is not dumpable as a Tensor"); #endif } __END_AKANTU__ diff --git a/src/model/heat_transfer/heat_transfer_model.hh b/src/model/heat_transfer/heat_transfer_model.hh index 2df7c3b80..cd02a0458 100644 --- a/src/model/heat_transfer/heat_transfer_model.hh +++ b/src/model/heat_transfer/heat_transfer_model.hh @@ -1,381 +1,381 @@ /** * @file heat_transfer_model.hh * * @author Rui Wang * @author Srinivasa Babu Ramisetti * @author Guillaume Anciaux * @author Lucas Frerot * * @date Sun May 01 19:14:43 2011 * * @brief Model of Heat Transfer * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_HEAT_TRANSFER_MODEL_HH__ #define __AKANTU_HEAT_TRANSFER_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_types.hh" #include "aka_voigthelper.hh" #include "aka_memory.hh" #include "model.hh" #include "integrator_gauss.hh" #include "shape_lagrange.hh" #include "dumpable.hh" #include "parsable.hh" #include "solver.hh" namespace akantu { class IntegrationScheme1stOrder; } __BEGIN_AKANTU__ struct HeatTransferModelOptions : public ModelOptions { HeatTransferModelOptions(AnalysisMethod analysis_method = _explicit_lumped_capacity ) : analysis_method(analysis_method) {} AnalysisMethod analysis_method; }; extern const HeatTransferModelOptions default_heat_transfer_model_options; class HeatTransferModel : public Model, public DataAccessor, public Dumpable, public Parsable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef FEMTemplate MyFEMType; HeatTransferModel(Mesh & mesh, UInt spatial_dimension = _all_dimensions, const ID & id = "heat_transfer_model", const MemoryID & memory_id = 0); virtual ~HeatTransferModel() ; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// generic function to initialize everything ready for explicit dynamics - void initFull(const std::string & material_file, const ModelOptions & options = default_heat_transfer_model_options); + void initFull(const ModelOptions & options = default_heat_transfer_model_options); /// initialize the fem object of the boundary void initFEMBoundary(bool create_surface = true); /// read one material file to instantiate all the materials void readMaterials(); /// allocate all vectors void initArrays(); /// register the tags associated with the parallel synchronizer void initParallel(MeshPartition * partition, DataAccessor * data_accessor=NULL); /// initialize the model void initModel(); /// init PBC synchronizer void initPBC(); /// initialize the solver and the jacobian_matrix (called by initImplicit) void initSolver(SolverOptions & solver_options); /// initialize the stuff for the implicit solver void initImplicit(SolverOptions & solver_options = _solver_no_options); /// function to print the contain of the class virtual void printself(__attribute__ ((unused)) std::ostream & stream, __attribute__ ((unused)) int indent = 0) const {}; /* ------------------------------------------------------------------------ */ /* Methods for explicit */ /* ------------------------------------------------------------------------ */ public: /// compute and get the stable time step Real getStableTimeStep(); /// compute the heat flux void updateResidual(); /// calculate the lumped capacity vector for heat transfer problem void assembleCapacityLumped(); /// update the temperature from the temperature rate void explicitPred(); /// update the temperature rate from the increment void explicitCorr(); /// solve the system in temperature rate @f$C\delta \dot T = q_{n+1} - C \dot T_{n}@f$ /// this function needs to be run for dynamics void solveExplicitLumped(); // /// initialize the heat flux // void initializeResidual(Array &temp); // /// initialize temperature // void initializeTemperature(Array &temp); /* ------------------------------------------------------------------------ */ /* Methods for implicit */ /* ------------------------------------------------------------------------ */ public: /// solve the static equilibrium void solveStatic(); // /// assemble the stiffness matrix void assembleStiffnessMatrix(); private: /// compute the heat flux on ghost types void updateResidual(const GhostType & ghost_type); /// calculate the lumped capacity vector for heat transfer problem (w ghosttype) void assembleCapacityLumped(const GhostType & ghost_type); /// assemble the stiffness matrix (w/ ghost type) template void assembleStiffnessMatrix(const GhostType & ghost_type); /// assemble the stiffness matrix template void assembleStiffnessMatrix(const ElementType & type, const GhostType & ghost_type); /// compute the conductivity tensor for each quadrature point in an array void computeConductivityOnQuadPoints(const GhostType & ghost_type); /// compute vector k \grad T for each quadrature point void computeKgradT(const GhostType & ghost_type); /// compute the thermal energy Real computeThermalEnergyByNode(); /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ public: inline UInt getNbDataForElements(const Array & elements, SynchronizationTag tag) const; inline void packElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag) const; inline void unpackElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag); inline UInt getNbDataToPack(SynchronizationTag tag) const; inline UInt getNbDataToUnpack(SynchronizationTag tag) const; inline void packData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const; inline void unpackData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag); /* ------------------------------------------------------------------------ */ /* Dumpable interface */ /* ------------------------------------------------------------------------ */ public: virtual void addDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id); virtual void addDumpFieldVectorToDumper(const std::string & dumper_name, const std::string & field_id); virtual void addDumpFieldTensorToDumper(const std::string & dumper_name, const std::string & field_id); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: inline FEM & getFEMBoundary(std::string name = ""); AKANTU_GET_MACRO(Density, density, Real); AKANTU_GET_MACRO(Capacity, capacity, Real); /// get the dimension of the system space AKANTU_GET_MACRO(SpatialDimension, 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 AKANTU_SET_MACRO(TimeStep, time_step, Real); /// get the assembled heat flux AKANTU_GET_MACRO(Residual, *residual, Array&); /// get the lumped capacity AKANTU_GET_MACRO(CapacityLumped, * capacity_lumped, Array&); /// get the boundary vector AKANTU_GET_MACRO(Boundary, * boundary, Array&); /// get stiffness matrix AKANTU_GET_MACRO(StiffnessMatrix, *stiffness_matrix, const SparseMatrix&); /// get the external heat rate vector AKANTU_GET_MACRO(ExternalHeatRate, * external_heat_rate, Array&); /// get the temperature gradient AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(TemperatureGradient, temperature_gradient, Real); /// get the conductivity on q points AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ConductivityOnQpoints, conductivity_on_qpoints, Real); /// get the conductivity on q points AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(TemperatureOnQpoints, temperature_on_qpoints, Real); /// internal variables AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(KGradtOnQpoints, k_gradt_on_qpoints, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(IntBtKgT, int_bt_k_gT, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(BtKgT, bt_k_gT, Real); /// get the temperature AKANTU_GET_MACRO(Temperature, *temperature, Array &); /// get the temperature derivative AKANTU_GET_MACRO(TemperatureRate, *temperature_rate, Array &); /// get the equation number Array AKANTU_GET_MACRO(EquationNumber, *equation_number, const Array &); /// get the energy denominated by thermal Real getEnergy(const std::string & energy_id, const ElementType & type, UInt index); /// get the energy denominated by thermal Real getEnergy(const std::string & energy_id); /// get the thermal energy for a given element Real getThermalEnergy(const ElementType & type, UInt index); /// get the thermal energy for a given element Real getThermalEnergy(); protected: /* ----------------------------------------------------------------------- */ template void getThermalEnergy(iterator Eth, Array::const_iterator T_it, Array::const_iterator T_end) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: IntegrationScheme1stOrder * integrator; /// time step Real time_step; /// temperatures array Array * temperature; /// temperatures derivatives array Array * temperature_rate; /// increment array (@f$\delta \dot T@f$ or @f$\delta T@f$) Array * increment; /// stiffness matrix SparseMatrix * stiffness_matrix; /// jacobian matrix SparseMatrix * jacobian_matrix; /// the density Real density; /// the speed of the changing temperature ByElementTypeReal temperature_gradient; /// temperature field on quadrature points ByElementTypeReal temperature_on_qpoints; /// conductivity tensor on quadrature points ByElementTypeReal conductivity_on_qpoints; /// vector k \grad T on quad points ByElementTypeReal k_gradt_on_qpoints; /// vector \int \grad N k \grad T ByElementTypeReal int_bt_k_gT; /// vector \grad N k \grad T ByElementTypeReal bt_k_gT; /// external flux vector Array * external_heat_rate; /// residuals array Array * residual; /// position of a dof in the K matrix Array * equation_number; //lumped vector Array * capacity_lumped; /// boundary vector Array * boundary; //realtime Real time; ///capacity Real capacity; //conductivity matrix Matrix conductivity; //linear variation of the conductivity (for temperature dependent conductivity) Real conductivity_variation; // reference temperature for the interpretation of temperature variation Real T_ref; //the biggest parameter of conductivity matrix Real conductivitymax; /// thermal energy by element ByElementTypeReal thermal_energy; /// Solver Solver * solver; /// analysis method AnalysisMethod method; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "heat_transfer_model_inline_impl.cc" #endif /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const HeatTransferModel & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_HEAT_TRANSFER_MODEL_HH__ */ diff --git a/src/model/model.cc b/src/model/model.cc index 0a40ccb32..48db192f2 100644 --- a/src/model/model.cc +++ b/src/model/model.cc @@ -1,217 +1,213 @@ /** * @file model.cc * * @author Guillaume Anciaux * @author David Simon Kammer * @author Nicolas Richart * * @date Mon Oct 03 12:24:07 2011 * * @brief implementation of model common parts * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "model.hh" #include "element_group.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Model::Model(Mesh& m, UInt dim, const ID & id, const MemoryID & memory_id) : Memory(id, memory_id), mesh(m), spatial_dimension(dim == _all_dimensions ? m.getSpatialDimension() : dim), synch_registry(NULL),is_pbc_slave_node(0,1,"is_pbc_slave_node") { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Model::~Model() { AKANTU_DEBUG_IN(); FEMMap::iterator it; for (it = fems.begin(); it != fems.end(); ++it) { if(it->second) delete it->second; } for (it = fems_boundary.begin(); it != fems_boundary.end(); ++it) { if(it->second) delete it->second; } delete synch_registry; delete dof_synchronizer; dof_synchronizer = NULL; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void Model::initFull(std::string input_file, const ModelOptions & options) { +void Model::initFull(const ModelOptions & options) { AKANTU_DEBUG_IN(); - if(input_file != "") { - parser.parse(input_file); - } - initModel(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Model::createSynchronizerRegistry(DataAccessor * data_accessor){ synch_registry = new SynchronizerRegistry(*data_accessor); } /* -------------------------------------------------------------------------- */ void Model::setPBC(UInt x, UInt y, UInt z){ Mesh & mesh = getFEM().getMesh(); mesh.computeBoundingBox(); if (x) MeshUtils::computePBCMap(mesh, 0, pbc_pair); if (y) MeshUtils::computePBCMap(mesh, 1, pbc_pair); if (z) MeshUtils::computePBCMap(mesh, 2, pbc_pair); } /* -------------------------------------------------------------------------- */ void Model::setPBC(SurfacePairList & surface_pairs, ElementType surface_e_type){ Mesh & mesh = getFEM().getMesh(); SurfacePairList::iterator s_it; for(s_it = surface_pairs.begin(); s_it != surface_pairs.end(); ++s_it) { MeshUtils::computePBCMap(mesh, *s_it, surface_e_type, pbc_pair); } } /* -------------------------------------------------------------------------- */ void Model::initPBC() { Mesh & mesh = getFEM().getMesh(); std::map::iterator it = pbc_pair.begin(); std::map::iterator end = pbc_pair.end(); is_pbc_slave_node.resize(mesh.getNbNodes()); #ifndef AKANTU_NDEBUG Real * coords = mesh.getNodes().storage(); UInt dim = mesh.getSpatialDimension(); #endif while(it != end){ UInt i1 = (*it).first; is_pbc_slave_node(i1) = true; #ifndef AKANTU_NDEBUG UInt i2 = (*it).second; AKANTU_DEBUG_INFO("pairing " << i1 << " (" << coords[dim*i1] << "," << coords[dim*i1+1] << "," << coords[dim*i1+2] << ") with " << i2 << " (" << coords[dim*i2] << "," << coords[dim*i2+1] << "," << coords[dim*i2+2] << ")"); #endif ++it; } } /* -------------------------------------------------------------------------- */ DistributedSynchronizer & Model::createParallelSynch(MeshPartition * partition, __attribute__((unused)) DataAccessor * data_accessor){ AKANTU_DEBUG_IN(); /* ------------------------------------------------------------------------ */ /* Parallel initialization */ /* ------------------------------------------------------------------------ */ StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int prank = comm.whoAmI(); DistributedSynchronizer * synch = NULL; if(prank == 0) synch = DistributedSynchronizer::createDistributedSynchronizerMesh(getFEM().getMesh(), partition); else synch = DistributedSynchronizer::createDistributedSynchronizerMesh(getFEM().getMesh(), NULL); AKANTU_DEBUG_OUT(); return *synch; } /* -------------------------------------------------------------------------- */ void Model::dumpGroup(const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); group.dump(); } /* -------------------------------------------------------------------------- */ void Model::dumpGroup(const std::string & group_name, const std::string & dumper_name) { ElementGroup & group = mesh.getElementGroup(group_name); group.dump(dumper_name); } /* -------------------------------------------------------------------------- */ void Model::dumpGroup() { GroupManager::element_group_iterator bit = mesh.element_group_begin(); GroupManager::element_group_iterator bend = mesh.element_group_end(); for(; bit != bend; ++bit) { bit->second->dump(); } } /* -------------------------------------------------------------------------- */ void Model::setGroupDirectory(const std::string & directory) { GroupManager::element_group_iterator bit = mesh.element_group_begin(); GroupManager::element_group_iterator bend = mesh.element_group_end(); for (; bit != bend; ++bit) { bit->second->setDirectory(directory); } } /* -------------------------------------------------------------------------- */ void Model::setGroupDirectory(const std::string & directory, const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); group.setDirectory(directory); } /* -------------------------------------------------------------------------- */ void Model::setGroupBaseName(const std::string & basename, const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); group.setBaseName(basename); } /* -------------------------------------------------------------------------- */ DumperIOHelper & Model::getGroupDumper(const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); return group.getDumper(); } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/model/model.hh b/src/model/model.hh index be8f0ae34..78013009c 100644 --- a/src/model/model.hh +++ b/src/model/model.hh @@ -1,236 +1,230 @@ /** * @file model.hh * * @author Guillaume Anciaux * @author David Simon Kammer * @author Nicolas Richart * * @date Tue Jul 27 18:15:37 2010 * * @brief Interface of a model * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MODEL_HH__ #define __AKANTU_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "mesh.hh" #include "fem.hh" #include "mesh_utils.hh" #include "synchronizer_registry.hh" #include "distributed_synchronizer.hh" #include "static_communicator.hh" #include "mesh_partition.hh" #include "dof_synchronizer.hh" #include "pbc_synchronizer.hh" #include "parser.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ struct ModelOptions { virtual ~ModelOptions() {} }; class DumperIOHelper; class Model : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef Mesh mesh_type; Model(Mesh& mesh, UInt spatial_dimension = _all_dimensions, const ID & id = "model", const MemoryID & memory_id = 0); virtual ~Model(); typedef std::map FEMMap; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: - virtual void initFull(std::string input_file, const ModelOptions & options); + virtual void initFull(const ModelOptions & options); virtual void initModel() = 0; /// create the synchronizer registry object void createSynchronizerRegistry(DataAccessor * data_accessor); /// create a parallel synchronizer and distribute the mesh DistributedSynchronizer & createParallelSynch(MeshPartition * partition, DataAccessor * data_accessor); /// change local equation number so that PBC is assembled properly void changeLocalEquationNumberForPBC(std::map & pbc_pair,UInt dimension); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const = 0; /// initialize the model for PBC void setPBC(UInt x, UInt y, UInt z); void setPBC(SurfacePairList & surface_pairs, ElementType surface_e_type); virtual void initPBC(); /* ------------------------------------------------------------------------ */ /* Access to the dumpable interface of the boundaries */ /* ------------------------------------------------------------------------ */ /// Dump the data for a given group void dumpGroup(const std::string & group_name); void dumpGroup(const std::string & group_name, const std::string & dumper_name); /// Dump the data for all boundaries void dumpGroup(); /// Set the directory for a given group void setGroupDirectory(const std::string & directory, const std::string & group_name); /// Set the directory for all boundaries void setGroupDirectory(const std::string & directory); /// Set the base name for a given group void setGroupBaseName(const std::string & basename, const std::string & group_name); /// Get the internal dumper of a given group DumperIOHelper & getGroupDumper(const std::string & group_name); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get id of model AKANTU_GET_MACRO(ID, id, const ID) /// get the number of surfaces AKANTU_GET_MACRO(Mesh, mesh, Mesh&); /// return the object hadling equation numbers AKANTU_GET_MACRO(DOFSynchronizer, *dof_synchronizer, const DOFSynchronizer &) /// synchronize the boundary in case of parallel run virtual void synchronizeBoundaries() {}; /// return the fem object associated with a provided name inline FEM & getFEM(const ID & name = "") const; /// return the fem boundary object associated with a provided name virtual FEM & getFEMBoundary(const ID & name = ""); /// register a fem object associated with name template inline void registerFEMObject(const std::string & name, Mesh & mesh, UInt spatial_dimension); /// unregister a fem object associated with name inline void unRegisterFEMObject(const std::string & name); /// return the synchronizer registry SynchronizerRegistry & getSynchronizerRegistry(); - /// Get access to the parser - AKANTU_GET_MACRO(Parser, parser, const Parser &); - public: /// return the fem object associated with a provided name template inline FEMClass & getFEMClass(std::string name = "") const; /// return the fem boundary object associated with a provided name template inline FEMClass & getFEMClassBoundary(std::string name = ""); /// get the pbc pairs std::map & getPBCPairs(){return pbc_pair;}; /* ------------------------------------------------------------------------ */ /* Pack and unpack helper functions */ /* ------------------------------------------------------------------------ */ public: inline UInt getNbQuadraturePoints(const Array & elements, const ID & fem_id = ID()) const; protected: /// returns if node is slave in pbc inline bool getIsPBCSlaveNode(const UInt node); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Mesh Mesh & mesh; /// Spatial dimension of the problem UInt spatial_dimension; /// the main fem object present in all models FEMMap fems; /// the fem object present in all models for boundaries FEMMap fems_boundary; /// default fem object std::string default_fem; - /// Parser containing the information parsed by the input file given to initFull - Parser parser; - /// synchronizer registry SynchronizerRegistry * synch_registry; /// handle the equation number things DOFSynchronizer * dof_synchronizer; /// pbc pairs std::map pbc_pair; /// flag per node to know is pbc slave Array is_pbc_slave_node; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "model_inline_impl.cc" #endif /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Model & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_MODEL_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model.cc b/src/model/solid_mechanics/solid_mechanics_model.cc index d7de45d83..32111bac1 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.cc +++ b/src/model/solid_mechanics/solid_mechanics_model.cc @@ -1,1974 +1,1974 @@ /** * @file solid_mechanics_model.cc * * @author Guillaume Anciaux * @author Nicolas Richart * * @date Tue Jul 27 18:15:37 2010 * * @brief Implementation of the SolidMechanicsModel class * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_math.hh" #include "aka_common.hh" #include "solid_mechanics_model.hh" #include "integration_scheme_2nd_order.hh" #include "element_group.hh" #include "static_communicator.hh" #include "dof_synchronizer.hh" #include "element_group.hh" #include #ifdef AKANTU_USE_MUMPS #include "solver_mumps.hh" #endif #ifdef AKANTU_USE_IOHELPER # include "dumper_paraview.hh" # include "dumper_iohelper_tmpl.hh" # include "dumper_iohelper_tmpl_homogenizing_field.hh" # include "dumper_iohelper_tmpl_material_internal_field.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ const SolidMechanicsModelOptions default_solid_mechanics_model_options(_explicit_lumped_mass, false); /* -------------------------------------------------------------------------- */ /** * 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), Dumpable(), BoundaryCondition(), time_step(NAN), f_m2a(1.0), mass_matrix(NULL), velocity_damping_matrix(NULL), stiffness_matrix(NULL), jacobian_matrix(NULL), element_index_by_material("element index by material", id), material_selector(new DefaultMaterialSelector(element_index_by_material)), is_default_material_selector(true), integrator(NULL), increment_flag(false), solver(NULL), synch_parallel(NULL), are_materials_instantiated(false) { AKANTU_DEBUG_IN(); createSynchronizerRegistry(this); registerFEMObject("SolidMechanicsFEM", mesh, spatial_dimension); this->displacement = NULL; this->mass = NULL; this->velocity = NULL; this->acceleration = NULL; this->force = NULL; this->residual = NULL; this->boundary = NULL; this->increment = NULL; this->increment_acceleration = NULL; this->dof_synchronizer = NULL; this->previous_displacement = NULL; materials.clear(); mesh.registerEventHandler(*this); #if defined(AKANTU_USE_IOHELPER) this->registerDumper("paraview_all", id, true); this->addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_regular); #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolidMechanicsModel::~SolidMechanicsModel() { AKANTU_DEBUG_IN(); std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { delete *mat_it; } materials.clear(); delete integrator; delete solver; delete mass_matrix; delete velocity_damping_matrix; if(stiffness_matrix && stiffness_matrix != jacobian_matrix) delete stiffness_matrix; delete jacobian_matrix; delete synch_parallel; if(is_default_material_selector) { delete material_selector; material_selector = NULL; } AKANTU_DEBUG_OUT(); } void SolidMechanicsModel::setTimeStep(Real time_step) { this->time_step = time_step; #if defined(AKANTU_USE_IOHELPER) getDumper().setTimeStep(time_step); #endif } /* -------------------------------------------------------------------------- */ /* Initialisation */ /* -------------------------------------------------------------------------- */ /** * 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(std::string input_file, const ModelOptions & options) { - Model::initFull(input_file, options); +void SolidMechanicsModel::initFull(const ModelOptions & options) { + Model::initFull(options); const SolidMechanicsModelOptions & smm_options = dynamic_cast(options); method = smm_options.analysis_method; // initialize the vectors initArrays(); // set the initial condition to 0 force->clear(); velocity->clear(); acceleration->clear(); displacement->clear(); // initialize pcb if(pbc_pair.size()!=0) initPBC(); // initialize the time integration schemes switch(method) { case _explicit_lumped_mass: initExplicit(); break; case _explicit_consistent_mass: initSolver(); initExplicit(); break; case _implicit_dynamic: initImplicit(true); break; case _static: initImplicit(false); break; default: AKANTU_EXCEPTION("analysis method not recognised by SolidMechanicsModel"); break; } // initialize the materials - if(input_file != "") { + if(getStaticParser().getLastParsedFile() != "") { instantiateMaterials(); } if(!smm_options.no_init_materials) { initMaterials(); } if(increment_flag) initBC(*this, *displacement, *increment, *force); else initBC(*this, *displacement, *force); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initParallel(MeshPartition * partition, DataAccessor * data_accessor) { AKANTU_DEBUG_IN(); if (data_accessor == NULL) 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); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initFEMBoundary() { FEM & fem_boundary = getFEMBoundary(); fem_boundary.initShapeFunctions(_not_ghost); fem_boundary.initShapeFunctions(_ghost); fem_boundary.computeNormalsOnControlPoints(_not_ghost); fem_boundary.computeNormalsOnControlPoints(_ghost); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initExplicit(AnalysisMethod analysis_method) { AKANTU_DEBUG_IN(); //in case of switch from implicit to explicit if(!this->isExplicit()) method = analysis_method; if (integrator) delete integrator; integrator = new CentralDifference(); UInt nb_nodes = acceleration->getSize(); UInt nb_degree_of_freedom = acceleration->getNbComponent(); std::stringstream sstr; sstr << id << ":increment_acceleration"; increment_acceleration = &(alloc(sstr.str(), nb_nodes, nb_degree_of_freedom, Real())); AKANTU_DEBUG_OUT(); } void SolidMechanicsModel::initArraysPreviousDisplacment() { AKANTU_DEBUG_IN(); SolidMechanicsModel::setIncrementFlagOn(); UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_disp_t; sstr_disp_t << id << ":previous_displacement"; previous_displacement = &(alloc (sstr_disp_t.str(), nb_nodes, spatial_dimension, 0.)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Allocate all the needed vectors. By default their are not necessarily set to * 0 * */ void SolidMechanicsModel::initArrays() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_disp; sstr_disp << id << ":displacement"; // std::stringstream sstr_mass; sstr_mass << id << ":mass"; std::stringstream sstr_velo; sstr_velo << id << ":velocity"; std::stringstream sstr_acce; sstr_acce << id << ":acceleration"; std::stringstream sstr_forc; sstr_forc << id << ":force"; std::stringstream sstr_resi; sstr_resi << id << ":residual"; std::stringstream sstr_boun; sstr_boun << id << ":boundary"; displacement = &(alloc(sstr_disp.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); // mass = &(alloc(sstr_mass.str(), nb_nodes, spatial_dimension, 0)); velocity = &(alloc(sstr_velo.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); acceleration = &(alloc(sstr_acce.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); force = &(alloc(sstr_forc.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); residual = &(alloc(sstr_resi.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); boundary = &(alloc(sstr_boun.str(), nb_nodes, spatial_dimension, false)); std::stringstream sstr_curp; sstr_curp << id << ":current_position"; current_position = &(alloc(sstr_curp.str(), 0, spatial_dimension, REAL_INIT_VALUE)); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt, _ek_not_defined); for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, gt); element_index_by_material.alloc(nb_element, 2, *it, gt); } } dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension); dof_synchronizer->initLocalDOFEquationNumbers(); dof_synchronizer->initGlobalDOFEquationNumbers(); 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 getFEM().initShapeFunctions(_not_ghost); getFEM().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::iterator it = pbc_pair.begin(); std::map::iterator end = pbc_pair.end(); UInt dim = mesh.getSpatialDimension(); while(it != end) { for (UInt i=0; iregisterSynchronizer(*synch, _gst_smm_uv); synch_registry->registerSynchronizer(*synch, _gst_smm_mass); synch_registry->registerSynchronizer(*synch, _gst_smm_res); changeLocalEquationNumberForPBC(pbc_pair, mesh.getSpatialDimension()); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateCurrentPosition() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); current_position->resize(nb_nodes); Real * current_position_val = current_position->storage(); Real * position_val = mesh.getNodes().storage(); Real * displacement_val = displacement->storage(); /// compute current_position = initial_position + displacement memcpy(current_position_val, position_val, nb_nodes*spatial_dimension*sizeof(Real)); for (UInt n = 0; n < nb_nodes*spatial_dimension; ++n) { *current_position_val++ += *displacement_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initializeUpdateResidualData() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); residual->resize(nb_nodes); /// copy the forces in residual for boundary conditions memcpy(residual->storage(), force->storage(), nb_nodes*spatial_dimension*sizeof(Real)); // start synchronization synch_registry->asynchronousSynchronize(_gst_smm_uv); synch_registry->waitEndSynchronize(_gst_smm_uv); updateCurrentPosition(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Explicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /** * This function compute the second member of the motion equation. That is to * say the sum of forces @f$ r = F_{ext} - F_{int} @f$. @f$ F_{ext} @f$ is given * by the user in the force vector, and @f$ F_{int} @f$ is computed as @f$ * F_{int} = \int_{\Omega} N \sigma d\Omega@f$ * */ void SolidMechanicsModel::updateResidual(bool need_initialize) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the internal forces"); // f = f_ext - f_int // f = f_ext if(need_initialize) initializeUpdateResidualData(); AKANTU_DEBUG_INFO("Compute local stresses"); std::vector::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 */ synch_registry->asynchronousSynchronize(_gst_mnl_for_average); AKANTU_DEBUG_INFO("Compute non local stresses for local elements"); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllNonLocalStresses(_not_ghost); } AKANTU_DEBUG_INFO("Wait distant non local stresses"); synch_registry->waitEndSynchronize(_gst_mnl_for_average); AKANTU_DEBUG_INFO("Compute non local stresses for ghosts elements"); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllNonLocalStresses(_ghost); } #endif /* ------------------------------------------------------------------------ */ /* assembling the forces internal */ // communicate the stress AKANTU_DEBUG_INFO("Send data for residual assembly"); synch_registry->asynchronousSynchronize(_gst_smm_stress); AKANTU_DEBUG_INFO("Assemble residual for local elements"); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.assembleResidual(_not_ghost); } AKANTU_DEBUG_INFO("Wait distant stresses"); // finalize communications synch_registry->waitEndSynchronize(_gst_smm_stress); AKANTU_DEBUG_INFO("Assemble residual for ghost elements"); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.assembleResidual(_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::computeStresses() { if (isExplicit()) { // start synchronization synch_registry->asynchronousSynchronize(_gst_smm_uv); synch_registry->waitEndSynchronize(_gst_smm_uv); // compute stresses on all local elements for each materials std::vector::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 */ synch_registry->asynchronousSynchronize(_gst_mnl_for_average); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllNonLocalStresses(_not_ghost); } synch_registry->waitEndSynchronize(_gst_mnl_for_average); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllNonLocalStresses(_ghost); } #endif } else { std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllStressesFromTangentModuli(_not_ghost); } } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateResidualInternal() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Update the residual"); // f = f_ext - f_int - Ma - Cv = r - Ma - Cv; if(method != _static) { // f -= Ma if(mass_matrix) { // if full mass_matrix Array * Ma = new Array(*acceleration, true, "Ma"); *Ma *= *mass_matrix; /// \todo check unit conversion for implicit dynamics // *Ma /= f_m2a *residual -= *Ma; delete Ma; } else if (mass) { // else lumped mass UInt nb_nodes = acceleration->getSize(); UInt nb_degree_of_freedom = acceleration->getNbComponent(); Real * mass_val = mass->storage(); Real * accel_val = acceleration->storage(); Real * res_val = residual->storage(); bool * boundary_val = boundary->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { if(!(*boundary_val)) { *res_val -= *accel_val * *mass_val /f_m2a; } boundary_val++; res_val++; mass_val++; accel_val++; } } else { AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix."); } // f -= Cv if(velocity_damping_matrix) { Array * Cv = new Array(*velocity); *Cv *= *velocity_damping_matrix; *residual -= *Cv; delete Cv; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateAcceleration() { AKANTU_DEBUG_IN(); updateResidualInternal(); if(method == _explicit_lumped_mass) { /* residual = residual_{n+1} - M * acceleration_n therefore solution = increment acceleration not acceleration */ solveLumped(*increment_acceleration, *mass, *residual, *boundary, f_m2a); } else if (method == _explicit_consistent_mass) { solve(*increment_acceleration); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveLumped(Array & x, const Array & A, const Array & b, const Array & boundary, Real alpha) { Real * A_val = A.storage(); Real * b_val = b.storage(); Real * x_val = x.storage(); bool * boundary_val = boundary.storage(); UInt nb_degrees_of_freedom = x.getSize() * x.getNbComponent(); for (UInt n = 0; n < nb_degrees_of_freedom; ++n) { if(!(*boundary_val)) { *x_val = alpha * (*b_val / *A_val); } x_val++; A_val++; b_val++; boundary_val++; } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::explicitPred() { AKANTU_DEBUG_IN(); if(increment_flag) { if(previous_displacement) increment->copy(*previous_displacement); else increment->copy(*displacement); } AKANTU_DEBUG_ASSERT(integrator,"itegrator should have been allocated: " << "have called initExplicit ? " << "or initImplicit ?"); integrator->integrationSchemePred(time_step, *displacement, *velocity, *acceleration, *boundary); if(increment_flag) { Real * inc_val = increment->storage(); Real * dis_val = displacement->storage(); UInt nb_degree_of_freedom = displacement->getSize() * displacement->getNbComponent(); for (UInt n = 0; n < nb_degree_of_freedom; ++n) { *inc_val = *dis_val - *inc_val; inc_val++; dis_val++; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::explicitCorr() { AKANTU_DEBUG_IN(); integrator->integrationSchemeCorrAccel(time_step, *displacement, *velocity, *acceleration, *boundary, *increment_acceleration); if(previous_displacement) previous_displacement->copy(*displacement); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveStep() { AKANTU_DEBUG_IN(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeSolveStepEvent(method)); this->explicitPred(); this->updateResidual(); this->updateAcceleration(); this->explicitCorr(); EventManager::sendEvent(SolidMechanicsModelEvent::AfterSolveStepEvent(method)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Implicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /** * Initialize the solver and create the sparse matrices needed. * */ void SolidMechanicsModel::initSolver(__attribute__((unused)) SolverOptions & options) { #if !defined(AKANTU_USE_MUMPS) // or other solver in the future \todo add AKANTU_HAS_SOLVER in CMake AKANTU_DEBUG_ERROR("You should at least activate one solver."); #else UInt nb_global_nodes = mesh.getNbGlobalNodes(); delete jacobian_matrix; std::stringstream sstr; sstr << id << ":jacobian_matrix"; jacobian_matrix = new SparseMatrix(nb_global_nodes * spatial_dimension, _symmetric, spatial_dimension, sstr.str(), memory_id); jacobian_matrix->buildProfile(mesh, *dof_synchronizer); if (!isExplicit()) { delete stiffness_matrix; std::stringstream sstr_sti; sstr_sti << id << ":stiffness_matrix"; stiffness_matrix = new SparseMatrix(*jacobian_matrix, sstr_sti.str(), memory_id); } #ifdef AKANTU_USE_MUMPS std::stringstream sstr_solv; sstr_solv << id << ":solver"; solver = new SolverMumps(*jacobian_matrix, sstr_solv.str()); dof_synchronizer->initScatterGatherCommunicationScheme(); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif //AKANTU_USE_MUMPS if(solver) solver->initialize(options); #endif //AKANTU_HAS_SOLVER } /* -------------------------------------------------------------------------- */ /** * Initialize the implicit solver, either for dynamic or static cases, * * @param dynamic */ void SolidMechanicsModel::initImplicit(bool dynamic, SolverOptions & solver_options) { AKANTU_DEBUG_IN(); method = dynamic ? _implicit_dynamic : _static; if (!increment) setIncrementFlagOn(); initSolver(solver_options); if(method == _implicit_dynamic) { if(integrator) delete integrator; integrator = new TrapezoidalRule2(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initialAcceleration() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving Ma = f"); Solver * acc_solver = NULL; std::stringstream sstr; sstr << id << ":tmp_mass_matrix"; SparseMatrix * tmp_mass = new SparseMatrix(*mass_matrix, sstr.str(), memory_id); #ifdef AKANTU_USE_MUMPS std::stringstream sstr_solver; sstr << id << ":solver_mass_matrix"; acc_solver = new SolverMumps(*mass_matrix, sstr_solver.str()); dof_synchronizer->initScatterGatherCommunicationScheme(); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif //AKANTU_USE_MUMPS acc_solver->initialize(); tmp_mass->applyBoundary(*boundary); acc_solver->setRHS(*residual); acc_solver->solve(*acceleration); delete acc_solver; delete tmp_mass; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleStiffnessMatrix() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the new stiffness matrix."); stiffness_matrix->clear(); // call compute stiffness matrix on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->assembleStiffnessMatrix(_not_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveDynamic() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, "You should first initialize the implicit solver and assemble the stiffness matrix"); AKANTU_DEBUG_ASSERT(mass_matrix != NULL, "You should first initialize the implicit solver and assemble the mass matrix"); // updateResidualInternal(); solve(*increment); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveStatic() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving Ku = f"); AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, "You should first initialize the implicit solver and assemble the stiffness matrix"); UInt nb_nodes = displacement->getSize(); UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes; jacobian_matrix->copyContent(*stiffness_matrix); jacobian_matrix->applyBoundary(*boundary); increment->clear(); solver->setRHS(*residual); solver->solve(*increment); Real * increment_val = increment->storage(); Real * displacement_val = displacement->storage(); bool * boundary_val = boundary->storage(); for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++displacement_val, ++increment_val, ++boundary_val) { if (!(*boundary_val)) { *displacement_val += *increment_val; } else { *increment_val = 0.0; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveStatic(Array & boundary_normal, Array & EulerAngles) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving Ku = f"); AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, "You should first initialize the implicit solver and assemble the stiffness matrix"); UInt nb_nodes = displacement->getSize(); UInt nb_degree_of_freedom = displacement->getNbComponent(); // if(method != _static) jacobian_matrix->copyContent(*stiffness_matrix); Array * residual_rotated = new Array (nb_nodes, nb_degree_of_freedom, "residual_rotated"); //stiffness_matrix->saveMatrix("stiffness_original.out"); jacobian_matrix->applyBoundaryNormal(boundary_normal, EulerAngles, *residual, (*stiffness_matrix).getA(), *residual_rotated); //jacobian_matrix->saveMatrix("stiffness_rotated_dir.out"); jacobian_matrix->applyBoundary(*boundary); solver->setRHS(*residual_rotated); delete residual_rotated; if (!increment) setIncrementFlagOn(); solver->solve(*increment); Matrix T(nb_degree_of_freedom, nb_degree_of_freedom); Matrix small_rhs(nb_degree_of_freedom, nb_degree_of_freedom); Matrix T_small_rhs(nb_degree_of_freedom, nb_degree_of_freedom); Real * increment_val = increment->storage(); Real * displacement_val = displacement->storage(); bool * boundary_val = boundary->storage(); for (UInt n = 0; n < nb_nodes; ++n) { bool constrain_ij = false; for (UInt j = 0; j < nb_degree_of_freedom; j++) { if (boundary_normal(n, j)) { constrain_ij = true; break; } } if (constrain_ij) { if (nb_degree_of_freedom == 2) { Real Theta = EulerAngles(n, 0); T(0, 0) = cos(Theta); T(0, 1) = -sin(Theta); T(1, 1) = cos(Theta); T(1, 0) = sin(Theta); } else if (nb_degree_of_freedom == 3) { Real Theta_x = EulerAngles(n, 0); Real Theta_y = EulerAngles(n, 1); Real Theta_z = EulerAngles(n, 2); T(0, 0) = cos(Theta_y) * cos(Theta_z); T(0, 1) = -cos(Theta_y) * sin(Theta_z); T(0, 2) = sin(Theta_y); T(1, 0) = cos(Theta_x) * sin(Theta_z) + cos(Theta_z) * sin(Theta_x) * sin(Theta_y); T(1, 1) = cos(Theta_x) * cos(Theta_z) - sin(Theta_x) * sin(Theta_y) * sin(Theta_z); T(1, 2) = -cos(Theta_y) * sin(Theta_x); T(2, 0) = sin(Theta_x) * sin(Theta_z) - cos(Theta_x) * cos(Theta_z) * sin(Theta_y); T(2, 1) = cos(Theta_z) * sin(Theta_x) + cos(Theta_x) * sin(Theta_y) * sin(Theta_z); T(2, 2) = cos(Theta_x) * cos(Theta_y); } small_rhs.clear(); T_small_rhs.clear(); for (UInt j = 0; j < nb_degree_of_freedom; j++) if(!(boundary_normal(n,j)) ) small_rhs(j,j)=increment_val[j]; T_small_rhs.mul(T,small_rhs); for (UInt j = 0; j < nb_degree_of_freedom; j++){ if(!(boundary_normal(n,j))){ for (UInt k = 0; k < nb_degree_of_freedom; k++) displacement_val[k]+=T_small_rhs(k,j); } } displacement_val += nb_degree_of_freedom; boundary_val += nb_degree_of_freedom; increment_val += nb_degree_of_freedom; } else { for (UInt j = 0; j < nb_degree_of_freedom; j++, ++displacement_val, ++increment_val, ++boundary_val) { if (!(*boundary_val)) { *displacement_val += *increment_val; } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseMatrix & SolidMechanicsModel::initVelocityDampingMatrix() { if(!velocity_damping_matrix) velocity_damping_matrix = new SparseMatrix(*jacobian_matrix, id + ":velocity_damping_matrix", memory_id); return *velocity_damping_matrix; } /* -------------------------------------------------------------------------- */ template<> bool SolidMechanicsModel::testConvergence<_scc_increment>(Real tolerance, Real & error){ AKANTU_DEBUG_IN(); UInt nb_nodes = displacement->getSize(); UInt nb_degree_of_freedom = displacement->getNbComponent(); error = 0; Real norm[2] = {0., 0.}; Real * increment_val = increment->storage(); bool * boundary_val = boundary->storage(); Real * displacement_val = displacement->storage(); for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); for (UInt d = 0; d < nb_degree_of_freedom; ++d) { if(!(*boundary_val) && is_local_node) { norm[0] += *increment_val * *increment_val; norm[1] += *displacement_val * *displacement_val; } boundary_val++; increment_val++; displacement_val++; } } StaticCommunicator::getStaticCommunicator().allReduce(norm, 2, _so_sum); norm[0] = sqrt(norm[0]); norm[1] = sqrt(norm[1]); AKANTU_DEBUG_ASSERT(!Math::isnan(norm[0]), "Something went wrong in the solve phase"); AKANTU_DEBUG_OUT(); if(norm[1] > Math::getTolerance()) error = norm[0] / norm[1]; else error = norm[0]; //In case the total displacement is zero! return (error < tolerance); } /* -------------------------------------------------------------------------- */ template<> bool SolidMechanicsModel::testConvergence<_scc_residual>(Real tolerance, Real & norm) { AKANTU_DEBUG_IN(); UInt nb_nodes = residual->getSize(); norm = 0; Real * residual_val = residual->storage(); bool * boundary_val = boundary->storage(); for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); if(is_local_node) { for (UInt d = 0; d < spatial_dimension; ++d) { if(!(*boundary_val)) { norm += *residual_val * *residual_val; } boundary_val++; residual_val++; } } else { boundary_val += spatial_dimension; residual_val += spatial_dimension; } } StaticCommunicator::getStaticCommunicator().allReduce(&norm, 1, _so_sum); norm = sqrt(norm); AKANTU_DEBUG_ASSERT(!Math::isnan(norm), "Something goes wrong in the solve phase"); AKANTU_DEBUG_OUT(); return (norm < tolerance); } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceResidual(Real tolerance){ AKANTU_DEBUG_IN(); Real error=0; bool res = this->testConvergence<_scc_residual>(tolerance, error); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceResidual(Real tolerance, Real & error){ AKANTU_DEBUG_IN(); bool res = this->testConvergence<_scc_residual>(tolerance, error); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance){ AKANTU_DEBUG_IN(); Real error=0; bool res = this->testConvergence<_scc_increment>(tolerance, error); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance, Real & error){ AKANTU_DEBUG_IN(); bool res = this->testConvergence<_scc_increment>(tolerance, error); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::implicitPred() { AKANTU_DEBUG_IN(); if(previous_displacement) previous_displacement->copy(*displacement); if(method == _implicit_dynamic) integrator->integrationSchemePred(time_step, *displacement, *velocity, *acceleration, *boundary); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::implicitCorr() { AKANTU_DEBUG_IN(); if(method == _implicit_dynamic) { integrator->integrationSchemeCorrDispl(time_step, *displacement, *velocity, *acceleration, *boundary, *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 = boundary->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(); AKANTU_DEBUG_ASSERT(previous_displacement,"The previous displacement has to be initialized." << " Are you working with Finite or Ineslactic deformations?"); UInt nb_nodes = displacement->getSize(); UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes; Real * incr_val = increment->storage(); Real * disp_val = displacement->storage(); Real * prev_disp_val = previous_displacement->storage(); for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++disp_val, ++incr_val, ++prev_disp_val) *incr_val = (*disp_val - *prev_disp_val); 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(); } /* -------------------------------------------------------------------------- */ /* Information */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::synchronizeBoundaries() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(synch_registry,"Synchronizer registry was not initialized." << " Did you call initParallel?"); synch_registry->synchronize(_gst_smm_boundary); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::synchronizeResidual() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(synch_registry,"Synchronizer registry was not initialized." << " Did you call initPBC?"); synch_registry->synchronize(_gst_smm_res); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::setIncrementFlagOn() { AKANTU_DEBUG_IN(); if(!increment) { UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_inc; sstr_inc << id << ":increment"; increment = &(alloc(sstr_inc.str(), nb_nodes, spatial_dimension, 0.)); } 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, 1, _so_min); AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getStableTimeStep(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Material ** mat_val = &(materials.at(0)); Real min_dt = std::numeric_limits::max(); updateCurrentPosition(); Element elem; elem.ghost_type = ghost_type; elem.kind = _ek_regular; Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type); for(; it != end; ++it) { elem.type = *it; UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*it); UInt nb_element = mesh.getNbElement(*it); Array::iterator< Vector > eibm = element_index_by_material(*it, ghost_type).begin(2); Array X(0, nb_nodes_per_element*spatial_dimension); FEM::extractNodalToElementField(mesh, *current_position, X, *it, _not_ghost); Array::matrix_iterator X_el = X.begin(spatial_dimension, nb_nodes_per_element); for (UInt el = 0; el < nb_element; ++el, ++X_el, ++eibm) { elem.element = (*eibm)(1); Real el_h = getFEM().getElementInradius(*X_el, *it); Real el_c = mat_val[(*eibm)(0)]->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::getPotentialEnergy() { AKANTU_DEBUG_IN(); Real energy = 0.; /// call update residual on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { energy += (*mat_it)->getPotentialEnergy(); } /// reduction sum over all processors StaticCommunicator::getStaticCommunicator().allReduce(&energy, 1, _so_sum); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy() { AKANTU_DEBUG_IN(); if (!mass && !mass_matrix) AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix."); Real ekin = 0.; UInt nb_nodes = mesh.getNbNodes(); Real * vel_val = velocity->storage(); Real * mass_val = mass->storage(); for (UInt n = 0; n < nb_nodes; ++n) { Real mv2 = 0; bool is_local_node = mesh.isLocalOrMasterNode(n); bool is_not_pbc_slave_node = !getIsPBCSlaveNode(n); bool count_node = is_local_node && is_not_pbc_slave_node; for (UInt i = 0; i < spatial_dimension; ++i) { if (count_node) mv2 += *vel_val * *vel_val * *mass_val; vel_val++; mass_val++; } ekin += mv2; } StaticCommunicator::getStaticCommunicator().allReduce(&ekin, 1, _so_sum); AKANTU_DEBUG_OUT(); return ekin * .5; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy(const ElementType & type, UInt index) { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = getFEM().getNbQuadraturePoints(type); Array vel_on_quad(nb_quadrature_points, spatial_dimension); Array filter_element(1, 1, index); getFEM().interpolateOnQuadraturePoints(*velocity, vel_on_quad, spatial_dimension, type, _not_ghost, filter_element); Array::vector_iterator vit = vel_on_quad.begin(spatial_dimension); Array::vector_iterator vend = vel_on_quad.end(spatial_dimension); Vector rho_v2(nb_quadrature_points); Real rho = materials[element_index_by_material(type)(index, 0)]->getRho(); for (UInt q = 0; vit != vend; ++vit, ++q) { rho_v2(q) = rho * vit->dot(*vit); } AKANTU_DEBUG_OUT(); return .5*getFEM().integrate(rho_v2, type, index); } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getExternalWork() { AKANTU_DEBUG_IN(); Real * velo = velocity->storage(); Real * forc = force->storage(); Real * resi = residual->storage(); bool * boun = boundary->storage(); Real work = 0.; UInt nb_nodes = mesh.getNbNodes(); for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); bool is_not_pbc_slave_node = !getIsPBCSlaveNode(n); bool count_node = is_local_node && is_not_pbc_slave_node; for (UInt i = 0; i < spatial_dimension; ++i) { if (count_node) { if(*boun) work -= *resi * *velo * time_step; else work += *forc * *velo * time_step; } ++velo; ++forc; ++resi; ++boun; } } StaticCommunicator::getStaticCommunicator().allReduce(&work, 1, _so_sum); 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.; std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { energy += (*mat_it)->getEnergy(energy_id); } /// reduction sum over all processors StaticCommunicator::getStaticCommunicator().allReduce(&energy, 1, _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); } std::vector::iterator mat_it; Vector mat = element_index_by_material(type, _not_ghost).begin(2)[index]; Real energy = materials[mat(0)]->getEnergy(energy_id, type, mat(1)); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onNodesAdded(const Array & nodes_list, __attribute__((unused)) const NewNodesEvent & event) { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); if(displacement) displacement->resize(nb_nodes); if(mass ) mass ->resize(nb_nodes); if(velocity ) velocity ->resize(nb_nodes); if(acceleration) acceleration->resize(nb_nodes); if(force ) force ->resize(nb_nodes); if(residual ) residual ->resize(nb_nodes); if(boundary ) boundary ->resize(nb_nodes); if(previous_displacement) previous_displacement->resize(nb_nodes); if(increment_acceleration) increment_acceleration->resize(nb_nodes); if(increment) increment->resize(nb_nodes); if(current_position) current_position->resize(nb_nodes); delete dof_synchronizer; dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension); dof_synchronizer->initLocalDOFEquationNumbers(); dof_synchronizer->initGlobalDOFEquationNumbers(); std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->onNodesAdded(nodes_list, event); } if (method != _explicit_lumped_mass) { delete stiffness_matrix; delete jacobian_matrix; delete solver; SolverOptions solver_options; initImplicit((method == _implicit_dynamic), solver_options); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onElementsAdded(const Array & element_list, const NewElementsEvent & event) { AKANTU_DEBUG_IN(); getFEM().initShapeFunctions(_not_ghost); getFEM().initShapeFunctions(_ghost); Array::const_iterator it = element_list.begin(); Array::const_iterator end = element_list.end(); /// \todo have rules to choose the correct material UInt mat_id = 0; UInt * mat_id_vect = NULL; try { const NewMaterialElementsEvent & event_mat = dynamic_cast(event); mat_id_vect = event_mat.getMaterialList().storage(); } catch(...) { } for (UInt el = 0; it != end; ++it, ++el) { const Element & elem = *it; if(mat_id_vect) mat_id = mat_id_vect[el]; else mat_id = (*material_selector)(elem); Material & mat = *materials[mat_id]; UInt mat_index = mat.addElement(elem.type, elem.element, elem.ghost_type); Vector id(2); id[0] = mat_id; id[1] = mat_index; if(!element_index_by_material.exists(elem.type, elem.ghost_type)) element_index_by_material.alloc(0, 2, elem.type, elem.ghost_type); element_index_by_material(elem.type, elem.ghost_type).push_back(id); } std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->onElementsAdded(element_list, event); } if(method != _explicit_lumped_mass) AKANTU_DEBUG_TO_IMPLEMENT(); assembleMassLumped(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onElementsRemoved(__attribute__((unused)) const Array & element_list, const ByElementTypeUInt & new_numbering, const RemovedElementsEvent & event) { // MeshUtils::purifyMesh(mesh); getFEM().initShapeFunctions(_not_ghost); getFEM().initShapeFunctions(_ghost); std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->onElementsRemoved(element_list, new_numbering, event); } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onNodesRemoved(__attribute__((unused)) const Array & element_list, const Array & 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(force ) mesh.removeNodesFromArray(*force , new_numbering); if(residual ) mesh.removeNodesFromArray(*residual , new_numbering); if(boundary ) mesh.removeNodesFromArray(*boundary , new_numbering); if(increment_acceleration) mesh.removeNodesFromArray(*increment_acceleration, new_numbering); if(increment) mesh.removeNodesFromArray(*increment , new_numbering); delete dof_synchronizer; dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension); dof_synchronizer->initLocalDOFEquationNumbers(); dof_synchronizer->initGlobalDOFEquationNumbers(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::reassignMaterial() { AKANTU_DEBUG_IN(); std::vector< Array > element_to_add (materials.size()); std::vector< Array > element_to_remove(materials.size()); Element element; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; element.ghost_type = ghost_type; 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; element.type = type; UInt nb_element = mesh.getNbElement(type, ghost_type); Array & el_index_by_mat = element_index_by_material(type, ghost_type); for (UInt el = 0; el < nb_element; ++el) { element.element = el; UInt old_material = el_index_by_mat(el, 0); 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); } } } } std::vector::iterator mat_it; UInt mat_index = 0; for(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::addDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id) { #ifdef AKANTU_USE_IOHELPER #define ADD_FIELD(field, type) \ internalAddDumpFieldToDumper(dumper_name, \ BOOST_PP_STRINGIZE(field), \ new DumperIOHelper::NodalField(*field)) if(field_id == "displacement") { ADD_FIELD(displacement, Real); } else if(field_id == "mass" ) { ADD_FIELD(mass , Real); } else if(field_id == "velocity" ) { ADD_FIELD(velocity , Real); } else if(field_id == "acceleration") { ADD_FIELD(acceleration, Real); } else if(field_id == "force" ) { ADD_FIELD(force , Real); } else if(field_id == "residual" ) { ADD_FIELD(residual , Real); } else if(field_id == "boundary" ) { ADD_FIELD(boundary , bool); } else if(field_id == "increment" ) { ADD_FIELD(increment , Real); } else if(field_id == "partitions" ) { internalAddDumpFieldToDumper(dumper_name, field_id, new DumperIOHelper::ElementPartitionField<>(mesh, spatial_dimension, _not_ghost, _ek_regular)); } else if(field_id == "element_index_by_material") { internalAddDumpFieldToDumper(dumper_name, field_id, new DumperIOHelper::ElementalField(element_index_by_material, spatial_dimension, _not_ghost, _ek_regular)); } else { bool is_internal = false; /// check if at least one material contains field_id as an internal for (UInt m = 0; m < materials.size() && !is_internal; ++m) { is_internal |= materials[m]->isInternal(field_id); } if (is_internal) { internalAddDumpFieldToDumper (dumper_name, field_id, new DumperIOHelper::HomogenizedField (*this, field_id, spatial_dimension, _not_ghost, _ek_regular)); } else { try { internalAddDumpFieldToDumper (dumper_name, field_id, new DumperIOHelper::ElementalField(mesh.getData(field_id), spatial_dimension, _not_ghost, _ek_regular)); } catch (...) {} try { internalAddDumpFieldToDumper (dumper_name, field_id, new DumperIOHelper::ElementalField(mesh.getData(field_id), spatial_dimension, _not_ghost, _ek_regular)); } catch (...) {} } } #undef ADD_FIELD #endif } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::addDumpGroupField(const std::string & field_id, const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); this->addDumpGroupFieldToDumper(group.getDefaultDumperName(), field_id, group_name); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name) { #ifdef AKANTU_USE_IOHELPER ElementGroup & group = mesh.getElementGroup(group_name); UInt dim = group.getDimension(); const Array * nodal_filter = &(group.getNodes()); const ByElementTypeArray * elemental_filter = &(group.getElements()); #define ADD_FIELD(field, type) \ group.addDumpFieldExternalToDumper(dumper_name, \ BOOST_PP_STRINGIZE(field), \ new DumperIOHelper::NodalField(*field, 0, 0, nodal_filter)) if(field_id == "displacement") { ADD_FIELD(displacement, Real); } else if(field_id == "mass" ) { ADD_FIELD(mass , Real); } else if(field_id == "velocity" ) { ADD_FIELD(velocity , Real); } else if(field_id == "acceleration") { ADD_FIELD(acceleration, Real); } else if(field_id == "force" ) { ADD_FIELD(force , Real); } else if(field_id == "residual" ) { ADD_FIELD(residual , Real); } else if(field_id == "boundary" ) { ADD_FIELD(boundary , bool); } else if(field_id == "increment" ) { ADD_FIELD(increment , Real); } else if(field_id == "partitions" ) { group.addDumpFieldExternalToDumper(dumper_name, field_id, new DumperIOHelper::ElementPartitionField(mesh, dim, _not_ghost, _ek_regular, elemental_filter)); } else if(field_id == "element_index_by_material") { group.addDumpFieldExternalToDumper(dumper_name, field_id, new DumperIOHelper::ElementalField(element_index_by_material, dim, _not_ghost, _ek_regular, elemental_filter)); } else { typedef DumperIOHelper::HomogenizedField Field; group.addDumpFieldExternalToDumper(dumper_name, field_id, new Field(*this, field_id, dim, _not_ghost, _ek_regular, elemental_filter)); } #undef ADD_FIELD #endif } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::removeDumpGroupField(const std::string & field_id, const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); this->removeDumpGroupFieldFromDumper(group.getDefaultDumperName(), field_id, group_name); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::removeDumpGroupFieldFromDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); group.removeDumpFieldFromDumper(dumper_name, field_id); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::addDumpFieldVectorToDumper(const std::string & dumper_name, const std::string & field_id) { #ifdef AKANTU_USE_IOHELPER #define ADD_FIELD(field, type) \ DumperIOHelper::Field * f = \ new DumperIOHelper::NodalField(*field); \ f->setPadding(3); \ internalAddDumpFieldToDumper(dumper_name, BOOST_PP_STRINGIZE(field), f) if(field_id == "displacement") { ADD_FIELD(displacement, Real); } else if(field_id == "mass" ) { ADD_FIELD(mass , Real); } else if(field_id == "velocity" ) { ADD_FIELD(velocity , Real); } else if(field_id == "acceleration") { ADD_FIELD(acceleration, Real); } else if(field_id == "force" ) { ADD_FIELD(force , Real); } else if(field_id == "residual" ) { ADD_FIELD(residual , Real); } else if(field_id == "increment" ) { ADD_FIELD(increment , Real); } else { typedef DumperIOHelper::HomogenizedField Field; Field * field = new Field(*this, field_id, spatial_dimension, spatial_dimension, _not_ghost, _ek_regular); field->setPadding(3); internalAddDumpFieldToDumper(dumper_name, field_id, field); } #undef ADD_FIELD #endif } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::addDumpGroupFieldVector(const std::string & field_id, const std::string & group_name) { ElementGroup & group = mesh.getElementGroup(group_name); this->addDumpGroupFieldVectorToDumper(group.getDefaultDumperName(), field_id, group_name); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::addDumpGroupFieldVectorToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name) { #ifdef AKANTU_USE_IOHELPER ElementGroup & group = mesh.getElementGroup(group_name); UInt dim = group.getDimension(); const Array * nodal_filter = &(group.getNodes()); const ByElementTypeArray * elemental_filter = &(group.getElements()); #define ADD_FIELD(field, type) \ DumperIOHelper::Field * f = \ new DumperIOHelper::NodalField(*field, 0, 0, nodal_filter); \ f->setPadding(3); \ group.addDumpFieldExternalToDumper(dumper_name, BOOST_PP_STRINGIZE(field), f) if(field_id == "displacement") { ADD_FIELD(displacement, Real); } else if(field_id == "mass" ) { ADD_FIELD(mass , Real); } else if(field_id == "velocity" ) { ADD_FIELD(velocity , Real); } else if(field_id == "acceleration") { ADD_FIELD(acceleration, Real); } else if(field_id == "force" ) { ADD_FIELD(force , Real); } else if(field_id == "residual" ) { ADD_FIELD(residual , Real); } else { typedef DumperIOHelper::HomogenizedField Field; Field * field = new Field(*this, field_id, spatial_dimension, dim, _not_ghost, _ek_regular, elemental_filter); field->setPadding(3); group.addDumpFieldExternalToDumper(dumper_name, field_id, field); } #undef ADD_FIELD #endif } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::addDumpFieldTensorToDumper(const std::string & dumper_name, const std::string & field_id) { #ifdef AKANTU_USE_IOHELPER if(field_id == "stress") { typedef DumperIOHelper::HomogenizedField Field; Field * field = new Field(*this, field_id, spatial_dimension, spatial_dimension, _not_ghost, _ek_regular); field->setPadding(3, 3); internalAddDumpFieldToDumper(dumper_name, field_id, field); } else if(field_id == "strain") { typedef DumperIOHelper::HomogenizedField Field; Field * field = new Field(*this, field_id, spatial_dimension, spatial_dimension, _not_ghost, _ek_regular); field->setPadding(3, 3); internalAddDumpFieldToDumper(dumper_name, field_id, field); } else { typedef DumperIOHelper::HomogenizedField Field; Field * field = new Field(*this, field_id, spatial_dimension, spatial_dimension, _not_ghost, _ek_regular); field->setPadding(3, 3); internalAddDumpFieldToDumper(dumper_name, field_id, field); } #endif } /* ------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name) { EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); Dumpable::dump(dumper_name); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name, UInt step) { EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); Dumpable::dump(dumper_name, step); } /* ------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name, Real time, UInt step) { EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); Dumpable::dump(dumper_name, time, step); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump() { Dumpable::dump(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(UInt step) { Dumpable::dump(step); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(Real time, UInt step) { Dumpable::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 : " << spatial_dimension << std::endl; stream << space << " + fem [" << std::endl; getFEM().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); force ->printself(stream, indent + 2); residual ->printself(stream, indent + 2); boundary ->printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + connectivity type information [" << std::endl; element_index_by_material.printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/model/solid_mechanics/solid_mechanics_model.hh b/src/model/solid_mechanics/solid_mechanics_model.hh index 29ada6ca7..6fdf89ffc 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.hh +++ b/src/model/solid_mechanics/solid_mechanics_model.hh @@ -1,714 +1,713 @@ /** * @file solid_mechanics_model.hh * * @author Guillaume Anciaux * @author Nicolas Richart * * @date Tue Jul 27 18:15:37 2010 * * @brief Model of Solid Mechanics * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLID_MECHANICS_MODEL_HH__ #define __AKANTU_SOLID_MECHANICS_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_types.hh" #include "model.hh" #include "data_accessor.hh" #include "mesh.hh" #include "dumpable.hh" #include "boundary_condition.hh" #include "integrator_gauss.hh" #include "shape_lagrange.hh" #include "integration_scheme_2nd_order.hh" #include "solver.hh" #include "material_selector.hh" #include "solid_mechanics_model_event_handler.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class Material; class IntegrationScheme2ndOrder; class Contact; class SparseMatrix; } __BEGIN_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; bool no_init_materials; }; extern const SolidMechanicsModelOptions default_solid_mechanics_model_options; class SolidMechanicsModel : public Model, public DataAccessor, public MeshEventHandler, public Dumpable, public BoundaryCondition, public EventHandlerManager { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: class NewMaterialElementsEvent : public NewElementsEvent { public: AKANTU_GET_MACRO_NOT_CONST(MaterialList, material, Array &); AKANTU_GET_MACRO(MaterialList, material, const Array &); protected: Array material; }; typedef FEMTemplate MyFEMType; protected: typedef EventHandlerManager EventManager; public: SolidMechanicsModel(Mesh & mesh, UInt spatial_dimension = _all_dimensions, const ID & id = "solid_mechanics_model", const MemoryID & memory_id = 0); virtual ~SolidMechanicsModel(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize completely the model - virtual void initFull(std::string material_file, - const ModelOptions & options = default_solid_mechanics_model_options); + virtual void initFull(const ModelOptions & options = default_solid_mechanics_model_options); /// initialize the fem object needed for boundary conditions void initFEMBoundary(); /// register the tags associated with the parallel synchronizer void initParallel(MeshPartition * partition, DataAccessor * data_accessor=NULL); /// allocate all vectors void initArrays(); /// allocate all vectors void initArraysPreviousDisplacment(); /// initialize all internal arrays for materials virtual void initMaterials(); /// initialize the model virtual void initModel(); /// init PBC synchronizer void initPBC(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* PBC */ /* ------------------------------------------------------------------------ */ public: /// change the equation number for proper assembly when using PBC void changeEquationNumberforPBC(std::map & pbc_pair); /// synchronize Residual for output void synchronizeResidual(); protected: /// register PBC synchronizer void registerPBCSynchronizer(); /* ------------------------------------------------------------------------ */ /* Explicit */ /* ------------------------------------------------------------------------ */ public: /// initialize the stuff for the explicit scheme void initExplicit(AnalysisMethod analysis_method = _explicit_lumped_mass); bool isExplicit() { return method == _explicit_lumped_mass|| method == _explicit_consistent_mass; } /// initialize the array needed by updateResidual (residual, current_position) void initializeUpdateResidualData(); /// 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(); void updateIncrement(); void updatePreviousDisplacement(); /// Solve the system @f[ A x = \alpha b @f] with A a lumped matrix void solveLumped(Array & x, const Array & A, const Array & b, const Array & boundary, 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(SolverOptions & options = _solver_no_options); /// initialize the stuff for the implicit solver void initImplicit(bool dynamic = false, SolverOptions & solver_options = _solver_no_options); /// 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 bool solveStep(Real tolerance, UInt max_iteration = 100); template bool solveStep(Real tolerance, Real & error, UInt max_iteration = 100); public: /** * solve Ku = f using the the given convergence method (see * akantu::SolveConvergenceMethod) and the given convergence * criteria (see akantu::SolveConvergenceCriteria) **/ template void solveStatic(Real tolerance, UInt max_iteration); /// solve @f[ A\delta u = f_{ext} - f_{int} @f] in displacement void solveDynamic(); /// solve Ku = f void solveStatic(); /// solve Ku = f void solveStatic(Array & boundary_normal, Array & EulerAngles); /// test if the system is converged template bool testConvergence(Real tolerance, Real & error); /// test the convergence (norm of increment) bool testConvergenceIncrement(Real tolerance) __attribute__((deprecated)); bool testConvergenceIncrement(Real tolerance, Real & error) __attribute__((deprecated)); /// test the convergence (norm of residual) bool testConvergenceResidual(Real tolerance) __attribute__((deprecated)); bool testConvergenceResidual(Real tolerance, Real & error) __attribute__((deprecated)); /// create and return the velocity damping matrix SparseMatrix & initVelocityDampingMatrix(); /// implicit time integration predictor void implicitPred(); /// implicit time integration corrector void implicitCorr(); protected: /// finish the computation of residual to solve in increment void updateResidualInternal(); /// compute the support reaction and store it in force void updateSupportReaction(); public: //protected: Daniel changed it just for a test /// compute A and solve @f[ A\delta u = f_ext - f_int @f] template void solve(Array & increment, Real block_val = 1.); /* ------------------------------------------------------------------------ */ /* Explicit/Implicit */ /* ------------------------------------------------------------------------ */ 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 void registerNewCustomMaterials(const ID & mat_type); /// register an empty material of a given type template 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); /// reassigns materials depending on the material selector void reassignMaterial(); protected: /// register a material in the dynamic database template Material & registerNewMaterial(const ParserSection & mat_section); /// read the material files to instantiate all the materials void instantiateMaterials(); /* ------------------------------------------------------------------------ */ /* 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 & rho, ElementType type, GhostType ghost_type); /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ public: inline virtual UInt getNbDataForElements(const Array & elements, SynchronizationTag tag) const; inline virtual void packElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag) const; inline virtual void unpackElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag); inline virtual UInt getNbDataToPack(SynchronizationTag tag) const; inline virtual UInt getNbDataToUnpack(SynchronizationTag tag) const; inline virtual void packData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const; inline virtual void unpackData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag); protected: inline void splitElementByMaterial(const Array & elements, Array * elements_per_mat) const; /* ------------------------------------------------------------------------ */ /* Mesh Event Handler inherited members */ /* ------------------------------------------------------------------------ */ protected: virtual void onNodesAdded (const Array & nodes_list, const NewNodesEvent & event); virtual void onNodesRemoved(const Array & element_list, const Array & new_numbering, const RemovedNodesEvent & event); virtual void onElementsAdded (const Array & nodes_list, const NewElementsEvent & event); virtual void onElementsRemoved(const Array & element_list, const ByElementTypeUInt & new_numbering, const RemovedElementsEvent & event); /* ------------------------------------------------------------------------ */ /* Dumpable interface */ /* ------------------------------------------------------------------------ */ public: virtual void addDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id); virtual void addDumpGroupField(const std::string & field_id, const std::string & group_name); virtual void addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name); virtual void removeDumpGroupField(const std::string & field_id, const std::string & group_name); virtual void removeDumpGroupFieldFromDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name); virtual void addDumpFieldVectorToDumper(const std::string & dumper_name, const std::string & field_id); virtual void addDumpGroupFieldVector(const std::string & field_id, const std::string & group_name); virtual void addDumpGroupFieldVectorToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name); virtual void addDumpFieldTensorToDumper(const std::string & dumper_name, const std::string & field_id); 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); virtual void dump(); 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, 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); /// 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 &); /// get the SolidMechanicsModel::previous_displacement vector AKANTU_GET_MACRO(PreviousDisplacement, *previous_displacement, Array &); /// get the SolidMechanicsModel::current_position vector \warn only consistent /// after a call to SolidMechanicsModel::updateCurrentPosition AKANTU_GET_MACRO(CurrentPosition, *current_position, const Array &); /// get the SolidMechanicsModel::increment vector \warn only consistent if /// SolidMechanicsModel::setIncrementFlagOn has been called before AKANTU_GET_MACRO(Increment, *increment, Array &); /// get the lumped SolidMechanicsModel::mass vector AKANTU_GET_MACRO(Mass, *mass, Array &); /// get the SolidMechanicsModel::velocity vector AKANTU_GET_MACRO(Velocity, *velocity, Array &); /// get the SolidMechanicsModel::acceleration vector, updated by /// SolidMechanicsModel::updateAcceleration AKANTU_GET_MACRO(Acceleration, *acceleration, Array &); /// get the SolidMechanicsModel::force vector (boundary forces) AKANTU_GET_MACRO(Force, *force, Array &); /// get the SolidMechanicsModel::residual vector, computed by /// SolidMechanicsModel::updateResidual AKANTU_GET_MACRO(Residual, *residual, Array &); /// get the SolidMechanicsModel::boundary vector AKANTU_GET_MACRO(Boundary, *boundary, Array &); /// get the SolidMechnicsModel::incrementAcceleration vector AKANTU_GET_MACRO(IncrementAcceleration, *increment_acceleration, Array &); /// 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(); /// compute the potential energy Real getPotentialEnergy(); /// 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(); /// 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); /// set the Contact object AKANTU_SET_MACRO(Contact, contact, Contact *); /** * @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 FEM object to integrate or interpolate on the boundary inline FEM & getFEMBoundary(const ID & name = ""); /// get integrator AKANTU_GET_MACRO(Integrator, *integrator, const IntegrationScheme2ndOrder &); /// get access to the internal solver AKANTU_GET_MACRO(Solver, *solver, Solver &); /// get synchronizer AKANTU_GET_MACRO(Synchronizer, *synch_parallel, const DistributedSynchronizer &); AKANTU_GET_MACRO(ElementIndexByMaterial, element_index_by_material, const ByElementTypeArray &); /// vectors containing local material element index for each global element index AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementIndexByMaterial, element_index_by_material, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementIndexByMaterial, element_index_by_material, UInt); /// Get the type of analysis method used AKANTU_GET_MACRO(AnalysisMethod, method, AnalysisMethod); protected: friend class Material; template class WeightFunction> friend class MaterialNonLocal; protected: /// compute the stable time step Real getStableTimeStep(const GhostType & ghost_type); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// time step Real time_step; /// conversion coefficient form force/mass to acceleration Real f_m2a; /// displacements array Array * displacement; /// displacements array at the previous time step (used in finite deformation) Array * previous_displacement; /// lumped mass array Array * mass; /// velocities array Array * velocity; /// accelerations array Array * acceleration; /// accelerations array Array * increment_acceleration; /// forces array Array * force; /// residuals array Array * residual; /// boundaries array Array * boundary; /// array of current position used during update residual Array * current_position; /// 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; /// vectors containing local material element index for each global element index ByElementTypeUInt element_index_by_material; /// list of used materials std::vector materials; /// mapping between material name and material internal id std::map materials_names_to_id; /// 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; /// increment of displacement Array * increment; /// flag defining if the increment must be computed or not bool increment_flag; /// solver for implicit Solver * solver; /// object to resolve the contact Contact * contact; /// analysis method check the list in akantu::AnalysisMethod AnalysisMethod method; /// internal synchronizer for parallel computations DistributedSynchronizer * synch_parallel; /// tells if the material are instantiated bool are_materials_instantiated; }; __END_AKANTU__ /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "parser.hh" #include "material.hh" __BEGIN_AKANTU__ #include "solid_mechanics_model_tmpl.hh" #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "solid_mechanics_model_inline_impl.cc" #endif /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const SolidMechanicsModel & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #include "material_selector_tmpl.hh" #endif /* __AKANTU_SOLID_MECHANICS_MODEL_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive.cc index 118bba8b9..09aaff367 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive.cc @@ -1,807 +1,806 @@ /** * @file solid_mechanics_model_cohesive.cc * * @author Marco Vocialta * * @date Tue May 08 13:01:18 2012 * * @brief Solid mechanics model for cohesive elements * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include "shape_cohesive.hh" #include "solid_mechanics_model_cohesive.hh" #include "material_cohesive.hh" #ifdef AKANTU_USE_IOHELPER # include "dumper_paraview.hh" # include "dumper_iohelper_tmpl.hh" # include "dumper_iohelper_tmpl_homogenizing_field.hh" # include "dumper_iohelper_tmpl_material_internal_field.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ const SolidMechanicsModelCohesiveOptions default_solid_mechanics_model_cohesive_options(_explicit_lumped_mass, false, false, true, true); /* -------------------------------------------------------------------------- */ SolidMechanicsModelCohesive::SolidMechanicsModelCohesive(Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id) : SolidMechanicsModel(mesh, dim, id, memory_id), mesh_facets(mesh.initMeshFacets("mesh_facets")), tangents("tangents", id), stress_on_facet("stress_on_facet", id), facet_stress("facet_stress", id), facet_material("facet_material", id), inserter(mesh, mesh_facets) { AKANTU_DEBUG_IN(); facet_generated = false; #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) facet_synchronizer = NULL; facet_stress_synchronizer = NULL; cohesive_distributed_synchronizer = NULL; global_connectivity = NULL; #endif delete material_selector; material_selector = new DefaultMaterialCohesiveSelector(*this); #if defined(AKANTU_USE_IOHELPER) this->registerDumper("cohesive elements", id); this->addDumpMeshToDumper("cohesive elements", mesh, spatial_dimension, _not_ghost, _ek_cohesive); #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolidMechanicsModelCohesive::~SolidMechanicsModelCohesive() { AKANTU_DEBUG_IN(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) delete cohesive_distributed_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) getDumper("cohesive elements").setTimeStep(time_step); #endif } /* -------------------------------------------------------------------------- */ -void SolidMechanicsModelCohesive::initFull(std::string material_file, - const ModelOptions & options) { +void SolidMechanicsModelCohesive::initFull(const ModelOptions & options) { AKANTU_DEBUG_IN(); const SolidMechanicsModelCohesiveOptions & smmc_options = dynamic_cast(options); this->stress_interpolation = smmc_options.stress_interpolation; this->is_extrinsic = smmc_options.extrinsic; if (is_extrinsic) { if (!facet_generated) MeshUtils::buildAllFacets(mesh, mesh_facets); } - SolidMechanicsModel::initFull(material_file, options); + SolidMechanicsModel::initFull(options); if (is_extrinsic) initAutomaticInsertion(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initMaterials() { AKANTU_DEBUG_IN(); /// init element inserter inserter.init(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_synchronizer != NULL) inserter.initParallel(facet_synchronizer); if (facet_stress_synchronizer != NULL) { DataAccessor * data_accessor = this; const ByElementTypeUInt & rank_to_element = synch_parallel->getPrankToElement(); facet_stress_synchronizer->updateFacetStressSynchronizer(inserter, rank_to_element, *data_accessor); } #endif // make sure the material are instantiated if(!are_materials_instantiated) instantiateMaterials(); /// find the first cohesive material UInt cohesive_index = 0; while ((dynamic_cast(materials[cohesive_index]) == NULL) && 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 mesh_facets.initByElementTypeArray(facet_material, 1, spatial_dimension - 1); if (is_extrinsic) { Element element; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { element.ghost_type = *gt; Mesh::type_iterator first = mesh_facets.firstType(spatial_dimension - 1, *gt); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1, *gt); for(;first != last; ++first) { element.type = *first; Array & f_material = facet_material(*first, *gt); UInt nb_element = mesh_facets.getNbElement(*first, *gt); 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(*materials[mat_index]); mat.addFacet(element); } } } } else { 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_cohesive); Mesh::type_iterator last = mesh.lastType(spatial_dimension, *gt, _ek_cohesive); for(;first != last; ++first) { Array & el_id_by_mat = element_index_by_material(*first, *gt); Vector el_mat(2); el_mat(0) = cohesive_index; el_mat(1) = 0; el_id_by_mat.set(el_mat); } } } 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(); registerFEMObject("CohesiveFEM", mesh, 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(spatial_dimension, type_ghost); Mesh::type_iterator last = mesh.lastType(spatial_dimension, type_ghost); for (; it != last; ++it) { const Array & connectivity = mesh.getConnectivity(*it, type_ghost); if (connectivity.getSize() != 0) { type = *it; ElementType type_facet = Mesh::getFacetType(type); ElementType type_cohesive = FEM::getCohesiveElementType(type_facet); mesh.addConnectivityType(type_cohesive, type_ghost); } } } AKANTU_DEBUG_ASSERT(type != _not_defined, "No elements in the mesh"); getFEM("CohesiveFEM").initShapeFunctions(_not_ghost); getFEM("CohesiveFEM").initShapeFunctions(_ghost); registerFEMObject("FacetsFEM", mesh_facets, spatial_dimension - 1); if (is_extrinsic) { getFEM("FacetsFEM").initShapeFunctions(_not_ghost); getFEM("FacetsFEM").initShapeFunctions(_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initAutomaticInsertion() { AKANTU_DEBUG_IN(); mesh_facets.initByElementTypeArray(facet_stress, 2 * spatial_dimension * spatial_dimension, spatial_dimension - 1); resizeFacetStress(); /// compute normals on facets computeNormals(); /// allocate stress_on_facet to store element stress on facets mesh.initByElementTypeArray(stress_on_facet, spatial_dimension * spatial_dimension, spatial_dimension); Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator last = mesh.lastType(spatial_dimension); for (; it != last; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type); UInt nb_facet_per_elem = Mesh::getNbFacetsPerElement(type); ElementType type_facet = Mesh::getFacetType(type); UInt nb_quad_per_facet = getFEM("FacetsFEM").getNbQuadraturePoints(type_facet); stress_on_facet(type).resize(nb_quad_per_facet * nb_facet_per_elem * nb_element); } if (stress_interpolation) 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 ByElementTypeUInt & rank_to_element = synch_parallel->getPrankToElement(); facet_stress_synchronizer->updateFacetStressSynchronizer(inserter, rank_to_element, *data_accessor); } #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initStressInterpolation() { /// compute quadrature points coordinates on facets Array & position = mesh.getNodes(); ByElementTypeReal quad_facets("quad_facets", id); mesh_facets.initByElementTypeArray(quad_facets, spatial_dimension, spatial_dimension - 1); getFEM("FacetsFEM").interpolateOnQuadraturePoints(position, quad_facets); /// compute elements quadrature point positions and build /// element-facet quadrature points data structure ByElementTypeReal elements_quad_facets("elements_quad_facets", id); mesh.initByElementTypeArray(elements_quad_facets, spatial_dimension, spatial_dimension); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType elem_gt = *gt; Mesh::type_iterator it = mesh.firstType(spatial_dimension, elem_gt); Mesh::type_iterator last = mesh.lastType(spatial_dimension, elem_gt); for (; it != last; ++it) { ElementType type = *it; 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 & facet_to_element = mesh_facets.getSubelementToElement(type, elem_gt); UInt nb_facet_per_elem = facet_to_element.getNbComponent(); Array & el_q_facet = elements_quad_facets(type, elem_gt); ElementType facet_type = Mesh::getFacetType(type); UInt nb_quad_per_facet = getFEM("FacetsFEM").getNbQuadraturePoints(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 & quad_f = quad_facets(facet_type, facet_gt); for (UInt q = 0; q < nb_quad_per_facet; ++q) { for (UInt s = 0; s < spatial_dimension; ++s) { el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, s) = quad_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(*materials[m]); } catch(std::bad_cast&) { /// initialize the interpolation function materials[m]->initElementalFieldInterpolation(elements_quad_facets); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::updateResidual(bool need_initialize) { AKANTU_DEBUG_IN(); if (need_initialize) initializeUpdateResidualData(); // f -= fint std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { try { MaterialCohesive & mat = dynamic_cast(**mat_it); mat.computeTraction(_not_ghost); } catch (std::bad_cast & bce) { } } SolidMechanicsModel::updateResidual(false); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { try { MaterialCohesive & mat = dynamic_cast(**mat_it); mat.computeEnergies(); } catch (std::bad_cast & bce) { } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::computeNormals() { AKANTU_DEBUG_IN(); getFEM("FacetsFEM").computeNormalsOnControlPoints(_not_ghost); /** * @todo store tangents while computing normals instead of * recomputing them as follows: */ /* ------------------------------------------------------------------------ */ UInt tangent_components = spatial_dimension * (spatial_dimension - 1); mesh_facets.initByElementTypeArray(tangents, tangent_components, spatial_dimension - 1); 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 facet_type = *it; const Array & normals = getFEM("FacetsFEM").getNormalsOnQuadPoints(facet_type); UInt nb_quad = normals.getSize(); Array & tang = tangents(facet_type); tang.resize(nb_quad); Real * normal_it = normals.storage(); Real * tangent_it = tang.storage(); /// compute first tangent for (UInt q = 0; q < nb_quad; ++q) { /// if normal is orthogonal to xy plane, arbitrarly define tangent if ( Math::are_float_equal(Math::norm2(normal_it), 0) ) tangent_it[0] = 1; else Math::normal2(normal_it, tangent_it); normal_it += spatial_dimension; tangent_it += tangent_components; } /// compute second tangent (3D case) if (spatial_dimension == 3) { normal_it = normals.storage(); tangent_it = tang.storage(); for (UInt q = 0; q < nb_quad; ++q) { Math::normal3(normal_it, tangent_it, tangent_it + spatial_dimension); normal_it += spatial_dimension; tangent_it += tangent_components; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::averageStressOnFacets(UInt material_index) { AKANTU_DEBUG_IN(); Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator last = mesh.lastType(spatial_dimension); /// loop over element type for (; it != last; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type); UInt nb_quad_per_element = getFEM().getNbQuadraturePoints(type); const Array & stress = materials[material_index]->getStress(type); Array & s_on_facet = stress_on_facet(type); UInt nb_facet_per_elem = Mesh::getNbFacetsPerElement(type); ElementType type_facet = Mesh::getFacetType(type); UInt nb_quad_per_facet = getFEM("FacetsFEM").getNbQuadraturePoints(type_facet); UInt nb_facet_quad_per_elem = nb_quad_per_facet * nb_facet_per_elem; Array::const_iterator > stress_it = stress.begin(spatial_dimension, spatial_dimension); Array::iterator > s_on_facet_it = s_on_facet.begin(spatial_dimension, spatial_dimension); Matrix average_stress(spatial_dimension, spatial_dimension); for (UInt el = 0; el < nb_element; ++el) { /// compute average stress average_stress.clear(); for (UInt q = 0; q < nb_quad_per_element; ++q, ++stress_it) average_stress += *stress_it; average_stress /= nb_quad_per_element; /// store average stress for (UInt q = 0; q < nb_facet_quad_per_elem; ++q, ++s_on_facet_it) *s_on_facet_it = average_stress; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::fillStressOnFacet() { AKANTU_DEBUG_IN(); UInt sp2 = spatial_dimension * spatial_dimension; UInt sp4 = sp2 * 2; /// loop over materials for (UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat __attribute__((unused)) = dynamic_cast(*materials[m]); } catch(std::bad_cast&) { if (stress_interpolation) /// interpolate stress on facet quadrature points positions materials[m]->interpolateStress(stress_on_facet); else averageStressOnFacets(m); GhostType ghost_type = _not_ghost; Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last = mesh.lastType(spatial_dimension, ghost_type); /// loop over element type for (; it != last; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type, ghost_type); if (nb_element == 0) continue; Array & stress_on_f = stress_on_facet(type, ghost_type); /// store the interpolated stresses on the facet_stress vector Array & facet_to_element = mesh_facets.getSubelementToElement(type, ghost_type); UInt nb_facet_per_elem = facet_to_element.getNbComponent(); Array::iterator > facet_to_el_it = facet_to_element.begin(nb_facet_per_elem); Array::iterator< Matrix > stress_on_f_it = stress_on_f.begin(spatial_dimension, spatial_dimension); ElementType facet_type = _not_defined; GhostType facet_gt = _casper; Array > * element_to_facet = NULL; Array * f_stress = NULL; Array * f_check = NULL; UInt nb_quad_per_facet = 0; UInt element_rank = 0; Element current_el(type, 0, ghost_type); for (UInt el = 0; el < nb_element; ++el, ++facet_to_el_it) { current_el.element = el; for (UInt f = 0; f < nb_facet_per_elem; ++f) { Element global_facet_elem = (*facet_to_el_it)(f); UInt global_facet = global_facet_elem.element; if (facet_type != global_facet_elem.type || facet_gt != global_facet_elem.ghost_type) { facet_type = global_facet_elem.type; facet_gt = global_facet_elem.ghost_type; element_to_facet = &( mesh_facets.getElementToSubelement(facet_type, facet_gt) ); f_stress = &( facet_stress(facet_type, facet_gt) ); nb_quad_per_facet = getFEM("FacetsFEM").getNbQuadraturePoints(facet_type, facet_gt); f_check = &( inserter.getCheckFacets(facet_type, facet_gt) ); } if (!(*f_check)(global_facet)) { stress_on_f_it += nb_quad_per_facet; continue; } for (UInt q = 0; q < nb_quad_per_facet; ++q, ++stress_on_f_it) { element_rank = (*element_to_facet)(global_facet)[0] != current_el; Matrix facet_stress_local(f_stress->storage() + (global_facet * nb_quad_per_facet + q) * sp4 + element_rank * sp2, spatial_dimension, spatial_dimension); facet_stress_local = *stress_on_f_it; } } } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::checkCohesiveStress() { AKANTU_DEBUG_IN(); fillStressOnFacet(); #if defined(AKANTU_DEBUG_TOOLS) debug::element_manager.printData(debug::_dm_model_cohesive, "Interpolated stresses before", facet_stress); #endif synch_registry->synchronize(_gst_smmc_facets_stress); #if defined(AKANTU_DEBUG_TOOLS) debug::element_manager.printData(debug::_dm_model_cohesive, "Interpolated stresses", facet_stress); #endif for (UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat_cohesive = dynamic_cast(*materials[m]); /// check which not ghost cohesive elements are to be created mat_cohesive.checkInsertion(); } catch(std::bad_cast&) { } } /// communicate data among processors synch_registry->synchronize(_gst_smmc_facets); /// insert cohesive elements inserter.insertExtrinsicElements(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onElementsAdded(const Array & element_list, const NewElementsEvent & event) { AKANTU_DEBUG_IN(); SolidMechanicsModel::onElementsAdded(element_list, event); /// update shape functions getFEM("CohesiveFEM").initShapeFunctions(_not_ghost); getFEM("CohesiveFEM").initShapeFunctions(_ghost); if(is_extrinsic) { getFEM("FacetsFEM").initShapeFunctions(_not_ghost); getFEM("FacetsFEM").initShapeFunctions(_ghost); } #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) updateFacetSynchronizers(); #endif resizeFacetStress(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onNodesAdded(const Array & doubled_nodes, __attribute__((unused)) const NewNodesEvent & event) { AKANTU_DEBUG_IN(); UInt nb_new_nodes = doubled_nodes.getSize(); Array 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 < 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); (*boundary) (new_node, dim) = (*boundary) (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::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(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, ghost_type); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, ghost_type); for(; it != end; ++it) { ElementType type = *it; UInt nb_facet = mesh_facets.getNbElement(type, ghost_type); UInt nb_quadrature_points = getFEM("FacetsFEM").getNbQuadraturePoints(type, ghost_type); UInt new_size = nb_facet * nb_quadrature_points; facet_stress(type, ghost_type).resize(new_size); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::addDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id) { AKANTU_DEBUG_IN(); if (dumper_name == "cohesive elements") { if (field_id == "damage") { internalAddDumpFieldToDumper ("cohesive elements", field_id, new DumperIOHelper:: HomogenizedField(*this, field_id, spatial_dimension, _not_ghost, _ek_cohesive)); } } else { SolidMechanicsModel::addDumpFieldToDumper(dumper_name, field_id); } AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh index a815c4d6e..9889a092e 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh @@ -1,282 +1,281 @@ /** * @file solid_mechanics_model_cohesive.hh * * @author Marco Vocialta * * @date Tue May 08 13:01:18 2012 * * @brief Solid mechanics model for cohesive elements * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ #define __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ #include "solid_mechanics_model.hh" #include "cohesive_element_inserter.hh" #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) # include "facet_synchronizer.hh" # include "facet_stress_synchronizer.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ struct SolidMechanicsModelCohesiveOptions : public SolidMechanicsModelOptions { SolidMechanicsModelCohesiveOptions(AnalysisMethod analysis_method = _explicit_lumped_mass, bool extrinsic = false, bool no_init_materials = false, bool init_facet_filter = true, bool stress_interpolation = true) : SolidMechanicsModelOptions(analysis_method, no_init_materials), extrinsic(extrinsic), init_facet_filter(init_facet_filter), stress_interpolation(stress_interpolation) {} bool extrinsic; bool init_facet_filter; bool stress_interpolation; }; extern const SolidMechanicsModelCohesiveOptions default_solid_mechanics_model_cohesive_options; /* -------------------------------------------------------------------------- */ /* Solid Mechanics Model for Cohesive elements */ /* -------------------------------------------------------------------------- */ class SolidMechanicsModelCohesive : public SolidMechanicsModel { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: class NewCohesiveNodesEvent : public NewNodesEvent { public: AKANTU_GET_MACRO_NOT_CONST(OldNodesList, old_nodes, Array &); AKANTU_GET_MACRO(OldNodesList, old_nodes, const Array &); protected: Array old_nodes; }; typedef FEMTemplate MyFEMCohesiveType; 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 updateResidual(bool need_initialize = true); /// 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 void checkCohesiveStress(); /// initialize the cohesive model - void initFull(std::string material_file, - const ModelOptions & options = default_solid_mechanics_model_cohesive_options); + void initFull(const ModelOptions & options = default_solid_mechanics_model_cohesive_options); /// 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 enableFacetsCheckOnArea(const Array & limits); /// update automatic insertion after a change in the element inserter void updateAutomaticInsertion(); private: /// initialize completely the model for extrinsic elements void initAutomaticInsertion(); /// initialize stress interpolation void initStressInterpolation(); /// compute facets' normals void computeNormals(); /// resize facet stress void resizeFacetStress(); /// init facets_check array void initFacetsCheck(); /// fill stress_on_facet void fillStressOnFacet(); /// compute average stress on elements void averageStressOnFacets(UInt material_index); /* ------------------------------------------------------------------------ */ /* Mesh Event Handler inherited members */ /* ------------------------------------------------------------------------ */ protected: virtual void onNodesAdded (const Array & nodes_list, const NewNodesEvent & event); virtual void onElementsAdded (const Array & nodes_list, const NewElementsEvent & event); /* ------------------------------------------------------------------------ */ /* Dumpable interface */ /* ------------------------------------------------------------------------ */ public: virtual void addDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get facet mesh AKANTU_GET_MACRO(MeshFacets, mesh_facets, 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 ByElementTypeArray &); /// @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 &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// mesh containing facets and their data structures Mesh & mesh_facets; /// @todo store tangents when normals are computed: ByElementTypeReal tangents; /// list of stresses on facet quadrature points for every element ByElementTypeReal stress_on_facet; /// stress on facets on the two sides by quadrature point ByElementTypeReal facet_stress; /// flag to know if facets have been generated bool facet_generated; /// material to use if a cohesive element is created on a facet ByElementTypeUInt facet_material; /// stress interpolation flag bool stress_interpolation; bool is_extrinsic; /// cohesive element inserter CohesiveElementInserter inserter; #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) #include "solid_mechanics_model_cohesive_parallel.hh" #endif }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined (AKANTU_PARALLEL_COHESIVE_ELEMENT) # include "solid_mechanics_model_cohesive_inline_impl.cc" #endif /* -------------------------------------------------------------------------- */ class DefaultMaterialCohesiveSelector : public DefaultMaterialSelector { public: DefaultMaterialCohesiveSelector(const SolidMechanicsModelCohesive & model) : DefaultMaterialSelector(model.getElementIndexByMaterial()), facet_material(model.getFacetMaterial()), mesh(model.getMesh()), mesh_facets(model.getMeshFacets()) { } inline virtual UInt operator()(const Element & element) { if(Mesh::getKind(element.type) == _ek_cohesive) { try { const Array & cohesive_el_to_facet = mesh_facets.getSubelementToElement(element.type, element.ghost_type); bool third_dimension = (mesh.getSpatialDimension() == 3); const Element & facet = cohesive_el_to_facet(element.element, third_dimension); return facet_material(facet.type, facet.ghost_type)(facet.element); } catch(...) { return MaterialSelector::operator()(element); } } else if (Mesh::getSpatialDimension(element.type) == mesh.getSpatialDimension() - 1) { return facet_material(element.type, element.ghost_type)(element.element); } else { return DefaultMaterialSelector::operator()(element); } } private: const ByElementTypeUInt & facet_material; const Mesh & mesh; const Mesh & mesh_facets; }; /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const SolidMechanicsModelCohesive & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_material.cc b/src/model/solid_mechanics/solid_mechanics_model_material.cc index 2c31bce26..bfacd9504 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_material.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_material.cc @@ -1,216 +1,216 @@ /** * @file solid_mechanics_model_material.cc * * @author Guillaume Anciaux * @author Nicolas Richart * * @date Fri Nov 26 00:17:56 2010 * * @brief instatiation of materials * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "material_list.hh" #include "aka_math.hh" /* -------------------------------------------------------------------------- */ __BEGIN_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); \ } #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); \ } #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(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; } \ } #define AKANTU_INTANTIATE_MATERIAL_IF(elem) \ if (mat_type == BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(0, elem))) { \ AKANTU_INTANTIATE_MATERIAL(elem); \ } #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(Parser::parser_permissive) \ + 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) /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::instantiateMaterials() { std::pair - sub_sect = parser.getSubSections(_st_material); + sub_sect = getStaticParser().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(); } are_materials_instantiated = true; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initMaterials() { AKANTU_DEBUG_ASSERT(materials.size() != 0, "No material to initialize !"); if(!are_materials_instantiated) instantiateMaterials(); Material ** mat_val = &(materials.at(0)); Element element; element.ghost_type = _not_ghost; Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(spatial_dimension, _not_ghost, _ek_not_defined); // Fill the element material array from the material selector for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, _not_ghost); element.type = *it; Array & el_id_by_mat = element_index_by_material(*it, _not_ghost); for (UInt el = 0; el < nb_element; ++el) { 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"); el_id_by_mat(el, 0) = mat_index; } } // synchronize the element material arrays synch_registry->synchronize(_gst_material_id); /// fill the element filters of the materials using the element_material arrays for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; it = mesh.firstType(spatial_dimension, gt, _ek_not_defined); end = mesh.lastType(spatial_dimension, gt, _ek_not_defined); for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, gt); Array & el_id_by_mat = element_index_by_material(*it, gt); for (UInt el = 0; el < nb_element; ++el) { UInt mat_index = el_id_by_mat(el, 0); UInt index = mat_val[mat_index]->addElement(*it, el, gt); el_id_by_mat(el, 1) = index; } } } std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { /// init internals properties (*mat_it)->initMaterial(); } synch_registry->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 (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; if (mat.isFiniteDeformation() || mat.isInelasticDeformation()) { initArraysPreviousDisplacment(); break; } } } /* -------------------------------------------------------------------------- */ Int SolidMechanicsModel::getInternalIndexFromID(const ID & id) const { AKANTU_DEBUG_IN(); std::vector::const_iterator first = materials.begin(); std::vector::const_iterator last = materials.end(); for (; first != last; ++first) if ((*first)->getID() == id) { AKANTU_DEBUG_OUT(); return (first - materials.begin()); } AKANTU_DEBUG_OUT(); return -1; } __END_AKANTU__ diff --git a/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh b/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh index 0b4718e4e..2e14a4779 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh +++ b/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh @@ -1,103 +1,103 @@ /** * @file solid_mechanics_model_tmpl.hh * * @author Guillaume Anciaux * @author Nicolas Richart * @author Dana Christen * * @date Thu Nov 24 09:36:33 2011 * * @brief template part of solid mechanics model * * @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 . * */ /* -------------------------------------------------------------------------- */ template 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(); Material * material; material = new M(*this, mat_id); materials.push_back(material); material->parseSection(section); return *material; } /* -------------------------------------------------------------------------- */ template 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"); 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(); Material * material; material = new M(*this, mat_id); materials.push_back(material); return *material; } /* -------------------------------------------------------------------------- */ template void SolidMechanicsModel::registerNewCustomMaterials(const ID & mat_type) { std::pair - sub_sect = parser.getSubSections(_st_material); + 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(*it); } } } diff --git a/test/test_io/test_parser/test_parser.cc b/test/test_io/test_parser/test_parser.cc index 84ffc9d68..df1a20156 100644 --- a/test/test_io/test_parser/test_parser.cc +++ b/test/test_io/test_parser/test_parser.cc @@ -1,78 +1,75 @@ /** * @file test_parser.cc * * @author Nicolas Richart * * @date Fri Aug 2 12:02:29 2013 * * @brief test the input file parser * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "parser.hh" #include "aka_random_generator.hh" #include using namespace akantu; int main(int argc, char *argv[]) { - debug::setDebugLevel(dblInfo); + initialize("input_file.dat", argc, argv); - initialize(argc, argv); + const Parser & p = getStaticParser(); - Parser p; - - p.parse("input_file.dat"); std::cout << RandGenerator::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::epsilon()) { std::cout << "!=" << ref << std::endl; return 1; } std::cout << "==" << ref << std::endl; Vector vect = p.getParameter("vect"); std::cout << vect << std::endl; Matrix mat = p.getParameter("mat"); std::cout << mat << std::endl; RandomParameter rand1 = p.getParameter("rand1"); std::cout << rand1 << std::endl; RandomParameter rand2 = p.getParameter("rand2"); std::cout << rand2 << std::endl; RandomParameter rand3 = p.getParameter("rand3"); std::cout << rand3 << std::endl; finalize(); return 0; } diff --git a/test/test_io/test_parser/test_parser.verified b/test/test_io/test_parser/test_parser.verified index 14ef0e7d5..805f7a0d0 100644 --- a/test/test_io/test_parser/test_parser.verified +++ b/test/test_io/test_parser/test_parser.verified @@ -1,41 +1,41 @@ 123456==123456 Section(_st_global) global [ Parameters [ + debug_level: 1 (input_file.dat:2:1) + general: 50 (input_file.dat:22:1) + mat: [[ 1, 23+2, 5, toto ],vect ] (input_file.dat:27:1) + rand1: 10 uniform [0.2, 0.5 ] (input_file.dat:30:1) + rand2: 10 weibull [0.2, 0.5 ] (input_file.dat:31:1) + rand3: 10 (input_file.dat:32:1) + seed: 123456 (input_file.dat:1:1) + toto: 2*pi + max(2, general) (input_file.dat:24:1) + vect: [ 1, 23+2, 5, toto ] (input_file.dat:26:1) ] Subsections [ Section(_st_material) elastic opt1 [ Parameters [ + E: 1 (input_file.dat:5:6) + X135: 1 + 3* debug_level (input_file.dat:6:6) + a: c (input_file.dat:11:6) + name: toto (input_file.dat:4:6) + yop: yop (input_file.dat:9:6) ] Subsections [ Section(_st_rules) material [ Parameters [ + E: 1 (input_file.dat:15:11) + X135: 1 + 1 (input_file.dat:16:11) + name: toto (input_file.dat:14:11) + yop: yop (input_file.dat:18:11) ] ] ] ] ] ] 56.2832==56.2832 Vector(4) : [1, 25, 5, 56.2832] Matrix(2,4) :[[1, 25, 5, 56.2832], [1, 25, 5, 56.2832]] 10 Uniform [ min=0.2, max=0.5 ] -10 Weibull [ shape=0.2, scale=0.5] +10 Weibull [ shape=0.5, scale=0.2] 10 diff --git a/test/test_mesh_utils/test_pbc_tweak/test_pbc_tweak.cc b/test/test_mesh_utils/test_pbc_tweak/test_pbc_tweak.cc index 8c4ef9241..8e00d9b9c 100644 --- a/test/test_mesh_utils/test_pbc_tweak/test_pbc_tweak.cc +++ b/test/test_mesh_utils/test_pbc_tweak/test_pbc_tweak.cc @@ -1,69 +1,69 @@ /** * @file test_pbc_tweak.cc * * @author Guillaume Anciaux * * @date Wed Feb 09 13:28:38 2011 * * @brief test of internal facet extraction * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { int dim = 3; - initialize(argc, argv); + initialize("material.dat", argc, argv); debug::setDebugLevel(akantu::dblInfo); Mesh mesh(dim); MeshIOMSH mesh_io; mesh_io.read("cube.msh", mesh); SolidMechanicsModel model(mesh); /* -------------------------------------------------------------------------- */ - model.initFull("material.dat"); + model.initFull(); /* -------------------------------------------------------------------------- */ model.setPBC(1,1,1); model.initPBC(); model.assembleMassLumped(); /* -------------------------------------------------------------------------- */ model.setBaseName("test-pbc-tweak"); model.addDumpField("mass"); model.dump(); finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d.cc b/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d.cc index 95119cc47..9d7e296c1 100644 --- a/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d.cc +++ b/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d.cc @@ -1,124 +1,124 @@ /** * @file test_heat_transfer_model_cube3d.cc * * @author Rui Wang * @author Srinivasa Babu Ramisetti * * @date Sun May 01 19:14:43 2011 * * @brief test of the class HeatTransferModel on the 3d cube * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "heat_transfer_model.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; UInt spatial_dimension = 3; ElementType type = _tetrahedron_4; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { - initialize(argc, argv); + initialize("material.dat", argc, argv); Mesh mesh(spatial_dimension); MeshIOMSH mesh_io; mesh_io.read("cube1.msh", mesh); HeatTransferModel model(mesh); //initialize everything - model.initFull("material.dat"); + model.initFull(); //assemble the lumped capacity model.assembleCapacityLumped(); //get and set stable time step Real time_step = model.getStableTimeStep()*0.8; std::cout << "time step is:" << time_step << std::endl; model.setTimeStep(time_step); /// boundary conditions const Array & nodes = mesh.getNodes(); Array & boundary = model.getBoundary(); Array & temperature = model.getTemperature(); UInt nb_nodes = mesh.getNbNodes(); //double t1, t2; double length; // t1 = 300.; // t2 = 100.; length = 1.; for (UInt i = 0; i < nb_nodes; ++i) { //temperature(i) = t1 - (t1 - t2) * sin(nodes(i, 0) * M_PI / length); temperature(i) = 100.; //to insert a heat source Real dx = nodes(i,0) - length/2.; Real dy = nodes(i,1) - length/2.; Real dz = nodes(i,2) - length/2.; Real d = sqrt(dx*dx + dy*dy + dz*dz); if(d < 0.1){ boundary(i) = true; temperature(i) = 300.; } } model.updateResidual(); model.setBaseName("heat_transfer_cube3d"); model.addDumpField("temperature" ); model.addDumpField("temperature_rate"); model.addDumpField("residual" ); model.addDumpField("capacity_lumped" ); model.dump(); // //for testing int max_steps = 1000; for(int i=0; i * * @date Sun May 01 19:14:43 2011 * * @brief test of the class HeatTransferModel on the 3d cube * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "heat_transfer_model.hh" #include #include #include using namespace std; /* -------------------------------------------------------------------------- */ akantu::UInt spatial_dimension = 3; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); akantu::Mesh mesh(spatial_dimension); akantu::MeshIOMSH mesh_io; mesh_io.read("cube1.msh", mesh); akantu::HeatTransferModel model(mesh); //initialize everything - model.initFull("material.dat"); + model.initFull(); //assemble the lumped capacity model.assembleCapacityLumped(); //get stable time step akantu::Real time_step = model.getStableTimeStep()*0.8; cout<<"time step is:"< & nodes = model.getFEM().getMesh().getNodes(); akantu::Array & boundary = model.getBoundary(); akantu::Array & temperature = model.getTemperature(); akantu::Real eps = 1e-15; double length = 1.; akantu::UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); for (akantu::UInt i = 0; i < nb_nodes; ++i) { //temperature(i) = t1 - (t1 - t2) * sin(nodes(i, 0) * M_PI / length); temperature(i) = 100.; if(nodes(i,0) < eps) { boundary(i) = true; temperature(i) = 300.; } //set the second boundary condition if(std::abs(nodes(i,0) - length) < eps) { boundary(i) = true; temperature(i) = 300.; } // //to insert a heat source // if(std::abs(nodes(i,0) - length/2.) < 0.025 && std::abs(nodes(i,1) - length/2.) < 0.025 && std::abs(nodes(i,2) - length/2.) < 0.025) { // boundary(i) = true; // temperature(i) = 300.; // } } model.updateResidual(); model.setBaseName("heat_transfer_cube3d_istropic_conductivity"); model.addDumpField("temperature" ); model.addDumpField("temperature_rate"); model.addDumpField("residual" ); model.addDumpField("capacity_lumped" ); model.dump(); // //for testing int max_steps = 1000; for(int i=0; i * @author Rui Wang * @author Srinivasa Babu Ramisetti * * @date Sun May 01 19:14:43 2011 * * @brief test of the class HeatTransferModel on the 3d cube * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "heat_transfer_model.hh" /* -------------------------------------------------------------------------- */ #include #include using namespace std; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); akantu::UInt spatial_dimension = 3; //create mesh akantu::Mesh mesh(spatial_dimension); mesh.read("cube_tet4.msh"); akantu::HeatTransferModel model(mesh); //initialize everything - model.initFull("material.dat"); + model.initFull(); //initialize PBC model.setPBC(1,1,1); model.initPBC(); //assemble the lumped capacity model.assembleCapacityLumped(); //get stable time step akantu::Real time_step = model.getStableTimeStep()*0.8; cout<<"time step is:"< & nodes = model.getFEM().getMesh().getNodes(); akantu::Array & boundary = model.getBoundary(); akantu::Array & temperature = model.getTemperature(); // double t1, t2; double length; // t1 = 300.; // t2 = 100.; length = 1.; akantu::UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); for (akantu::UInt i = 0; i < nb_nodes; ++i) { temperature(i) = 100.; akantu::Real dx = nodes(i,0) - length/4.; akantu::Real dy = nodes(i,1) - length/4.; akantu::Real dz = nodes(i,2) - length/4.; akantu::Real d = sqrt(dx*dx + dy*dy + dz*dz); if(d < 0.1){ boundary(i) = true; temperature(i) = 300.; } } model.updateResidual(); model.setBaseName("heat_transfer_cube3d_pbc"); model.addDumpField("temperature" ); model.addDumpField("temperature_rate"); model.addDumpField("residual" ); model.addDumpField("capacity_lumped" ); model.dump(); /* ------------------------------------------------------------------------ */ // //for testing int max_steps = 1000; /* ------------------------------------------------------------------------ */ for(int i=0; i. * */ /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" #include "heat_transfer_model.hh" #include "pbc_synchronizer.hh" /* -------------------------------------------------------------------------- */ #include #include #include using namespace std; /* -------------------------------------------------------------------------- */ akantu::UInt spatial_dimension = 2; std::string base_name; int main(int argc, char *argv[]) { - akantu::debug::setDebugLevel(akantu::dblWarning); - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); //create mesh akantu::Mesh mesh(spatial_dimension); - akantu::MeshIOMSH mesh_io; - mesh_io.read("square_tri3.msh", mesh); + mesh.read("square_tri3.msh"); akantu::HeatTransferModel model(mesh); //initialize everything - model.initFull("material.dat"); + model.initFull(); //assemble the lumped capacity model.assembleCapacityLumped(); //get stable time step akantu::Real time_step = model.getStableTimeStep()*0.8; cout<<"time step is:" << time_step << endl; model.setTimeStep(time_step); //boundary conditions const akantu::Array & nodes = model.getFEM().getMesh().getNodes(); akantu::Array & boundary = model.getBoundary(); akantu::Array & temperature = model.getTemperature(); double length; length = 1.; akantu::UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); for (akantu::UInt i = 0; i < nb_nodes; ++i) { temperature(i) = 100.; akantu::Real dx = nodes(i,0) - length/4.; akantu::Real dy = 0.0; akantu::Real dz = 0.0; if (spatial_dimension > 1) dy = nodes(i,1) - length/4.; if (spatial_dimension == 3) dz = nodes(i,2) - length/4.; akantu::Real d = sqrt(dx*dx + dy*dy + dz*dz); // if(dx < 0.0){ if(d < 0.1){ boundary(i) = true; temperature(i) = 300.; } } model.updateResidual(); model.setBaseName("heat_transfer_square2d"); model.addDumpField("temperature" ); model.addDumpField("temperature_rate"); model.addDumpField("residual" ); model.addDumpField("capacity_lumped" ); model.dump(); //main loop int max_steps = 1500; for(int i=0; i * * @date Sun May 01 19:14:43 2011 * * @brief test of the class HeatTransferModel on the 3d cube * * @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 . * */ /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" #include "heat_transfer_model.hh" -#include "pbc_synchronizer.hh" /* -------------------------------------------------------------------------- */ #include #include #include using namespace std; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::UInt spatial_dimension = 2; - akantu::debug::setDebugLevel(akantu::dblWarning); - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); //create mesh akantu::Mesh mesh(spatial_dimension); - akantu::MeshIOMSH mesh_io; - mesh_io.read("square_tri3.msh", mesh); + mesh.read("square_tri3.msh"); akantu::HeatTransferModel model(mesh); //initialize everything - model.initFull("material.dat"); + model.initFull(); //initialize PBC model.setPBC(1,1,1); model.initPBC(); //assemble the lumped capacity model.assembleCapacityLumped(); //get stable time step akantu::Real time_step = model.getStableTimeStep()*0.8; cout<<"time step is:" << time_step << endl; model.setTimeStep(time_step); //boundary conditions const akantu::Array & nodes = model.getFEM().getMesh().getNodes(); akantu::Array & boundary = model.getBoundary(); akantu::Array & temperature = model.getTemperature(); double length; length = 1.; akantu::UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); for (akantu::UInt i = 0; i < nb_nodes; ++i) { temperature(i) = 100.; akantu::Real dx = nodes(i,0) - length/4.; akantu::Real dy = 0.0; akantu::Real dz = 0.0; if (spatial_dimension > 1) dy = nodes(i,1) - length/4.; if (spatial_dimension == 3) dz = nodes(i,2) - length/4.; akantu::Real d = sqrt(dx*dx + dy*dy + dz*dz); // if(dx < 0.0){ if(d < 0.1){ boundary(i) = true; temperature(i) = 300.; } } model.updateResidual(); model.setBaseName("heat_transfer_square_2d_pbc"); model.addDumpField("temperature" ); model.addDumpField("temperature_rate"); model.addDumpField("residual" ); model.addDumpField("capacity_lumped" ); model.dump(); //main loop int max_steps = 1000; for(int i=0; i * @author Alodie Schneuwly * * @date Fri Jul 15 19:41:58 2011 * * @brief column test * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "aka_array.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" /* -------------------------------------------------------------------------- */ + using namespace akantu; int main(int argc, char *argv[]) { // chose if you use hexahedron elements bool use_hexa = false; std::stringstream mesh_file; std::stringstream output; std::stringstream energy_file; akantu::ElementType type; UInt vel_damping_interval; if (use_hexa) { type = akantu::_hexahedron_8; mesh_file << "colone_hexa.msh"; output << "paraview/test_weight_hexa"; energy_file << "energy_hexa.csv"; vel_damping_interval =4; } else { type = akantu::_tetrahedron_4; mesh_file << "colone_tetra.msh"; output << "paraview/test_weight_tetra"; energy_file << "energy_tetra.csv"; vel_damping_interval = 8; } akantu::UInt spatial_dimension = 3; akantu::UInt max_steps = 2000; akantu::Real time_factor = 0.8; - akantu::initialize(argc, argv); + akantu::initialize("material_colone.dat", argc, argv); // akantu::Real epot, ekin; akantu::Mesh mesh(spatial_dimension); mesh.read(mesh_file.str().c_str()); akantu::SolidMechanicsModel model(mesh); akantu::UInt nb_nodes = mesh.getNbNodes(); akantu::UInt nb_element = mesh.getNbElement(type); std::cout << "Nb nodes : " << nb_nodes << " - nb elements : " << nb_element << std::endl; /// model initialization - model.initFull("material_colone.dat"); + model.initFull(); std::cout << model.getMaterial(0) << std::endl; model.assembleMassLumped(); /// boundary conditions const akantu::Array & position = model.getFEM().getMesh().getNodes(); akantu::Array & boundary = model.getBoundary(); akantu::Array & force = model.getForce(); const akantu::Array & mass = model.getMass(); akantu::Real z_min = position(0, 2); for (unsigned int i = 0; i < nb_nodes; ++i) { if(position(i, 2) < z_min) z_min = position(i, 2); } akantu::Real eps = 1e-13; for (akantu::UInt i = 0; i < nb_nodes; ++i) { if(fabs(position(i, 2) - z_min) <= eps) boundary(i,2) = true; else force(i,2) = -mass(i,0) * 9.81; } akantu::Real time_step = model.getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model.setTimeStep(time_step); model.updateResidual(); model.setBaseName("colonne_weight"); model.addDumpField("displacement"); model.addDumpField("mass" ); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); model.addDumpField("damage" ); model.addDumpField("stress" ); model.addDumpField("strain" ); model.dump(); akantu::Array & velocity = model.getVelocity(); std::ofstream energy; energy.open(energy_file.str().c_str()); energy << "id,epot,ekin,tot" << std::endl; for(akantu::UInt s = 1; s <= max_steps; ++s) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); akantu::Real epot = model.getPotentialEnergy(); akantu::Real ekin = model.getKineticEnergy(); energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; if (s % vel_damping_interval == 0) { for (akantu::UInt i = 0; i < nb_nodes; ++i) { velocity(i, 0) *= 0.9; velocity(i, 1) *= 0.9; velocity(i, 2) *= 0.9; } } if(s % 1 == 0) model.dump(); if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } akantu::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 0ba703325..bed1348a2 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,283 +1,279 @@ /** * @file patch_test_explicit.cc * * @author David Simon Kammer * @author Nicolas Richart * @author Cyprien Wolff * * @date Thu Feb 17 16:05:48 2011 * * @brief patch test for elastic material in solid mechanics model * * @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 . * */ /* -------------------------------------------------------------------------- */ #include -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -#include "element_class.hh" using namespace akantu; Real alpha [3][4] = { { 0.01, 0.02, 0.03, 0.04 }, { 0.05, 0.06, 0.07, 0.08 }, { 0.09, 0.10, 0.11, 0.12 } }; /* -------------------------------------------------------------------------- */ template static Matrix prescribed_strain() { UInt spatial_dimension = ElementClass::getSpatialDimension(); Matrix 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 static Matrix prescribed_stress() { UInt spatial_dimension = ElementClass::getSpatialDimension(); Matrix stress(spatial_dimension, spatial_dimension); //plane strain in 2d Matrix strain(spatial_dimension, spatial_dimension); Matrix pstrain; pstrain = prescribed_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[]) { - initialize(argc, 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::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); - MeshIOMSH mesh_io; std::stringstream filename; filename << TYPE << ".msh"; - mesh_io.read(filename.str(), my_mesh); + my_mesh.read(filename.str()); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization - if(PLANE_STRAIN) - my_model.initFull("material_check_stress_plane_strain.dat"); - else - my_model.initFull("material_check_stress_plane_stress.dat"); + my_model.initFull(); std::cout << my_model.getMaterial(0) << std::endl; Real time_step = my_model.getStableTimeStep()/5.; 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 & coordinates = my_mesh.getNodes(); Array & displacement = my_model.getDisplacement(); Array & boundary = my_model.getBoundary(); 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 & 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.; /* ------------------------------------------------------------------------ */ /* 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)" < & stress_vect = const_cast &>(my_model.getMaterial(0).getStress(element_type)); Array & strain_vect = const_cast &>(my_model.getMaterial(0).getStrain(element_type)); Array::matrix_iterator stress_it = stress_vect.begin(dim, dim); Array::matrix_iterator strain_it = strain_vect.begin(dim, dim); Matrix presc_stress; presc_stress = prescribed_stress(); Matrix presc_strain; presc_strain = prescribed_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 & stress = *stress_it; Matrix & strain = *strain_it; Matrix diff(dim, dim); diff = strain; diff -= presc_strain; Real strain_error = diff.norm() / strain.norm(); 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() / stress.norm(); 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 3d04862da..b0e96f81d 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,310 +1,302 @@ /** * @file patch_test_explicit.cc * * @author David Simon Kammer * @author Nicolas Richart * @author Cyprien Wolff * * @date Thu Feb 17 16:05:48 2011 * * @brief patch test for elastic material in solid mechanics model * * @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 . * */ /* -------------------------------------------------------------------------- */ #include -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -#include "element_class.hh" using namespace akantu; Real alpha [3][4] = { { 0.01, 0.02, 0.03, 0.04 }, { 0.05, 0.06, 0.07, 0.08 }, { 0.09, 0.10, 0.11, 0.12 } }; //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 static Matrix prescribed_grad_u() { UInt spatial_dimension = ElementClass::getSpatialDimension(); Matrix 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 static Matrix prescribed_stress() { UInt spatial_dimension = ElementClass::getSpatialDimension(); Matrix stress(spatial_dimension, spatial_dimension); //plane strain in 2d Matrix strain(spatial_dimension, spatial_dimension); Matrix pstrain; pstrain = prescribed_grad_u(); 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(argc, argv); + initialize("material_anisotropic.dat", argc, argv); - debug::setDebugLevel(dblWarning); UInt dim = ElementClass::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); - MeshIOMSH mesh_io; std::stringstream filename; filename << TYPE << ".msh"; - mesh_io.read(filename.str(), my_mesh); + my_mesh.read(filename.str()); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization - my_model.initFull("material_anisotropic.dat", SolidMechanicsModelOptions(_explicit_lumped_mass)); + my_model.initFull(SolidMechanicsModelOptions(_explicit_lumped_mass)); std::cout << my_model.getMaterial(0) << std::endl; Real time_step = my_model.getStableTimeStep()/5.; 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 & coordinates = my_mesh.getNodes(); Array & displacement = my_model.getDisplacement(); Array & boundary = my_model.getBoundary(); 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 & 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.; /* ------------------------------------------------------------------------ */ /* 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)" < & stress_vect = const_cast &>(my_model.getMaterial(0).getStress(element_type)); Array & strain_vect = const_cast &>(my_model.getMaterial(0).getStrain(element_type)); Array::iterator< Matrix > stress_it = stress_vect.begin(dim, dim); Array::iterator< Matrix > strain_it = strain_vect.begin(dim, dim); Matrix presc_stress; presc_stress = prescribed_stress(); Matrix presc_strain; presc_strain = prescribed_grad_u(); UInt nb_element = my_mesh.getNbElement(TYPE); Real strain_tolerance = 1e-9; Real stress_tolerance = 1e-2; if(s > max_steps) { stress_tolerance = 1e-4; strain_tolerance = 1e-7; } for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quadrature_points; ++q) { Matrix & stress = *stress_it; Matrix & strain = *strain_it; for (UInt i = 0; i < dim; ++i) { for (UInt j = 0; j < dim; ++j) { if(!(std::abs(strain(i, j) - presc_strain(i, j)) < strain_tolerance)) { std::cerr << "strain[" << i << "," << j << "] = " << strain(i, j) << " but should be = " << presc_strain(i, j) << " (-" << std::abs(strain(i, j) - presc_strain(i, j)) << ") [el : " << el<< " - q : " << q << "]" << std::endl; std::cerr << strain << presc_strain << 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; ++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/implicit/patch_test_implicit.cc b/test/test_model/test_solid_mechanics_model/patch_tests/implicit/patch_test_implicit.cc index 143ed3323..02ab32bcb 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/implicit/patch_test_implicit.cc +++ b/test/test_model/test_solid_mechanics_model/patch_tests/implicit/patch_test_implicit.cc @@ -1,234 +1,230 @@ /** * @file patch_test_implicit.cc * * @author Nicolas Richart * * @date Thu Feb 17 16:05:48 2011 * * @brief patch test for elastic material in solid mechanics model * * @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 . * */ /* -------------------------------------------------------------------------- */ - -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -#include "element_class.hh" +/* -------------------------------------------------------------------------- */ using namespace akantu; Real alpha [3][4] = { { 0.01, 0.02, 0.03, 0.04 }, { 0.05, 0.06, 0.07, 0.08 }, { 0.09, 0.10, 0.11, 0.12 } }; /* -------------------------------------------------------------------------- */ template static Matrix prescribed_strain() { UInt spatial_dimension = ElementClass::getSpatialDimension(); Matrix 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 static Matrix prescribed_stress() { UInt spatial_dimension = ElementClass::getSpatialDimension(); Matrix stress(spatial_dimension, spatial_dimension); //plane strain in 2d Matrix strain(spatial_dimension, spatial_dimension); Matrix pstrain; pstrain = prescribed_strain(); Real nu = 0.3; Real E = 2.1e11; Real trace = 0; /// symetric part of the strain tensor for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) strain(i,j) = 0.5 * (pstrain(i, j) + pstrain(j, i)); for (UInt i = 0; i < spatial_dimension; ++i) trace += strain(i,i); Real lambda = nu * E / ((1 + nu) * (1 - 2*nu)); Real mu = E / (2 * (1 + nu)); if(!is_plane_strain) { std::cout << "toto" << std::endl; lambda = nu * E / (1 - nu*nu); } if(spatial_dimension == 1) { stress(0, 0) = E * strain(0, 0); } else { for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) { stress(i, j) = (i == j)*lambda*trace + 2*mu*strain(i, j); } } return stress; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { - initialize(argc, argv); + std::string input_file; + if(PLANE_STRAIN) + input_file = "material_check_stress_plane_strain.dat"; + else + input_file = "material_check_stress_plane_stress.dat"; + + initialize(input_file, argc, argv); UInt dim = ElementClass::getSpatialDimension(); const ElementType element_type = TYPE; /// load mesh Mesh my_mesh(dim); - MeshIOMSH mesh_io; std::stringstream filename; filename << TYPE << ".msh"; - mesh_io.read(filename.str(), my_mesh); + my_mesh.read(filename.str()); // MeshUtils::purifyMesh(my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization - if(PLANE_STRAIN) - my_model.initFull("material_check_stress_plane_strain.dat", SolidMechanicsModelOptions(_static)); - else - my_model.initFull("material_check_stress_plane_stress.dat", SolidMechanicsModelOptions(_static)); + my_model.initFull(SolidMechanicsModelOptions(_static)); const Array & coordinates = my_mesh.getNodes(); Array & displacement = my_model.getDisplacement(); Array & boundary = my_model.getBoundary(); MeshUtils::buildFacets(my_mesh); my_mesh.createBoundaryGroupFromGeometry(); // 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; } } } /* ------------------------------------------------------------------------ */ /* Static solve */ /* ------------------------------------------------------------------------ */ my_model.solveStep<_scm_newton_raphson_tangent_modified, _scc_residual>(2e-4, 2); my_model.getStiffnessMatrix().saveMatrix("clown_matrix.mtx"); /* ------------------------------------------------------------------------ */ /* Checks */ /* ------------------------------------------------------------------------ */ UInt nb_quadrature_points = my_model.getFEM().getNbQuadraturePoints(element_type); Array & stress_vect = const_cast &>(my_model.getMaterial(0).getStress(element_type)); Array & strain_vect = const_cast &>(my_model.getMaterial(0).getStrain(element_type)); Array::matrix_iterator stress_it = stress_vect.begin(dim, dim); Array::matrix_iterator strain_it = strain_vect.begin(dim, dim); Matrix presc_stress; presc_stress = prescribed_stress(); Matrix presc_strain; presc_strain = prescribed_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 & stress = *stress_it; Matrix & strain = *strain_it; Matrix diff(dim, dim); diff = strain; diff -= presc_strain; Real strain_error = diff.norm() / strain.norm(); 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() / stress.norm(); if(stress_error > stress_tolerance) { std::cerr << "stress error: " << stress_error << " > " << stress_tolerance << std::endl; std::cerr << "stress: " << stress << std::endl << "prescribed stress: " << presc_stress << std::endl; return EXIT_FAILURE; } else { std::cerr << "stress error: " << stress_error << " < " << stress_tolerance << std::endl; } ++stress_it; ++strain_it; } } for (UInt n = 0; n < nb_nodes; ++n) { for (UInt i = 0; i < dim; ++i) { Real disp = alpha[i][0]; for (UInt j = 0; j < dim; ++j) { disp += alpha[i][j + 1] * coordinates(n, j); } if(!(std::abs(displacement(n,i) - disp) < 2e-15)) { std::cerr << "displacement(" << n << ", " << i <<")=" << displacement(n,i) << " should be equal to " << disp << std::endl; return EXIT_FAILURE; } } } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/lumped_mass/test_lumped_mass.cc b/test/test_model/test_solid_mechanics_model/patch_tests/lumped_mass/test_lumped_mass.cc index 110b5e527..6941c4f0f 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/lumped_mass/test_lumped_mass.cc +++ b/test/test_model/test_solid_mechanics_model/patch_tests/lumped_mass/test_lumped_mass.cc @@ -1,89 +1,89 @@ /** * @file test_solid_mechanics_model_lumped_mass.cc * * @author Daniel Pino Muñoz * * @date Thu Mar 27 18:07:14 2014 * * @brief test the lumping of the mass matrix * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { UInt spatial_dimension = ElementClass::getSpatialDimension(); const ElementType type = TYPE; - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); Mesh mesh(spatial_dimension); std::stringstream filename; filename << TYPE << ".msh"; mesh.read(filename.str()); SolidMechanicsModel model(mesh); /// model initialization - model.initFull("material.dat"); + model.initFull(); model.assembleMassLumped(); Real rho = model.getMaterial(0).getRho(); FEM & fem = model.getFEM(); UInt nb_element = mesh.getNbElement(type); UInt nb_quadrature_points = fem.getNbQuadraturePoints(type) * nb_element; Array rho_on_quad(nb_quadrature_points, 1, rho, "rho_on_quad"); Real mass = fem.integrate(rho_on_quad, type); Array::const_vector_iterator mass_it = model.getMass().begin(spatial_dimension); Array::const_vector_iterator mass_end = model.getMass().end(spatial_dimension); Vector sum(spatial_dimension, 0.); for(; mass_it != mass_end; ++mass_it) { sum += *mass_it; } std::cout << mass << std::endl << sum << std::endl; if(!(std::abs((mass - sum[0])/mass) < 1e-15)) { std::cerr << "total mass is not correct" << std::endl; return EXIT_FAILURE; } for(UInt i = 1; i < spatial_dimension; ++i) if(!(std::abs((sum[0] - sum[i])/mass) < 1e-15)) { std::cerr << "total mass is not correct" << std::endl; return EXIT_FAILURE; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_1d_element/test_cohesive_1d_element.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_1d_element/test_cohesive_1d_element.cc index ee367a89e..dd55cca21 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_1d_element/test_cohesive_1d_element.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_1d_element/test_cohesive_1d_element.cc @@ -1,135 +1,134 @@ /** * @file test_cohesive_1d_element.cc * @author Marco Vocialta * @date Mon Jun 10 11:54:01 2013 * * @brief Test for 1D cohesive elements * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { - initialize(argc, argv); - debug::setDebugLevel(dblWarning); + initialize("material.dat", argc, argv); const UInt max_steps = 2000; const Real strain_rate = 4; UInt spatial_dimension = 1; Mesh mesh(spatial_dimension, "mesh"); mesh.read("bar.msh"); SolidMechanicsModelCohesive model(mesh); - model.initFull("material.dat", SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); + model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); Real time_step = model.getStableTimeStep()*0.01; model.setTimeStep(time_step); std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); mesh.computeBoundingBox(); Real posx_max = mesh.getXMax(); Real posx_min = mesh.getXMin(); /// initial conditions Array & velocity = model.getVelocity(); const Array & position = mesh.getNodes(); UInt nb_nodes = mesh.getNbNodes(); for (UInt n = 0; n < nb_nodes; ++n) velocity(n) = strain_rate * (position(n) - (posx_max + posx_min) /2.); /// boundary conditions Array & boundary = model.getBoundary(); Array & displacement = model.getDisplacement(); Real disp_increment = strain_rate * (posx_max - posx_min) / 2. * time_step; for(UInt node = 0; node < mesh.getNbNodes(); ++node) { if(Math::are_float_equal(position(node), posx_min)) { // left side boundary(node) = true; } if(Math::are_float_equal(position(node), posx_max)) { // right side boundary(node) = true; } } model.synchronizeBoundaries(); model.updateResidual(); // model.setBaseName("extrinsic_parallel"); // model.addDumpFieldVector("displacement"); // model.addDumpField("velocity" ); // model.addDumpField("acceleration"); // model.addDumpField("residual" ); // model.addDumpField("stress"); // model.addDumpField("strain"); // model.dump(); for (UInt s = 1; s <= max_steps; ++s) { model.checkCohesiveStress(); model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); UInt nb_cohesive_elements = mesh.getNbElement(_cohesive_1d_2); if (s % 10 == 0) { std::cout << "passing step " << s << "/" << max_steps << ", number of cohesive elemets:" << nb_cohesive_elements << std::endl; // model.dump(); } /// update external work and boundary conditions for (UInt n = 0; n < mesh.getNbNodes(); ++n) { if(Math::are_float_equal(position(n), posx_min)) // left side displacement(n) -= disp_increment; if(Math::are_float_equal(position(n), posx_max)) // right side displacement(n) += disp_increment; } } Real Ed = model.getEnergy("dissipated"); Real Edt = 100 * 3; std::cout << Ed << std::endl; if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; finalize(); return EXIT_FAILURE; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfragments/test_cohesive_buildfragments.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfragments/test_cohesive_buildfragments.cc index 85f84a0e0..2c0ab4fa5 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfragments/test_cohesive_buildfragments.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfragments/test_cohesive_buildfragments.cc @@ -1,205 +1,198 @@ /** * @file test_cohesive_buildfragments.cc * * @author Marco Vocialta * * @date Wed Jun 13 11:29:49 2012 * * @brief Test for cohesive elements * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" #include "material_cohesive.hh" #include "fragment_manager.hh" - -//#include "io_helper.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { - initialize(argc, argv); + initialize("material.dat",argc, argv); - debug::setDebugLevel(dblWarning); + Math::setTolerance(1e-14); const UInt spatial_dimension = 2; const UInt max_steps = 200; Real strain_rate = 1.e5; ElementType type = _quadrangle_4; Real L = 0.03; Real theoretical_mass = L * L/20. * 2500; ElementType type_facet = Mesh::getFacetType(type); ElementType type_cohesive = FEM::getCohesiveElementType(type_facet); Mesh mesh(spatial_dimension); mesh.read("mesh.msh"); mesh.createGroupsFromMeshData("physical_names"); SolidMechanicsModelCohesive model(mesh); /// model initialization - model.initFull("material.dat", - SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); + model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); Real time_step = model.getStableTimeStep()*0.05; model.setTimeStep(time_step); // std::cout << "Time step: " << time_step << std::endl; Real disp_increment = strain_rate * L / 2. * time_step; model.assembleMassLumped(); Array & velocity = model.getVelocity(); const Array & position = mesh.getNodes(); UInt nb_nodes = mesh.getNbNodes(); /// initial conditions for (UInt n = 0; n < nb_nodes; ++n) velocity(n, 0) = strain_rate * position(n, 0); /// boundary conditions model.applyBC(BC::Dirichlet::FixedValue(0, BC::_x), "Left_side"); model.applyBC(BC::Dirichlet::FixedValue(0, BC::_x), "Right_side"); model.updateResidual(); - // model.setBaseName("extrinsic"); - // model.addDumpFieldVector("displacement"); - // model.addDumpField("velocity" ); - // model.addDumpField("acceleration"); - // model.addDumpField("residual" ); - // model.addDumpField("stress"); - // model.addDumpField("strain"); - // model.dump(); + model.setBaseName("extrinsic"); + model.addDumpFieldVector("displacement"); + model.addDumpField("velocity" ); + model.addDumpField("acceleration"); + model.addDumpField("residual" ); + model.addDumpField("stress"); + model.addDumpField("strain"); + model.dump(); UInt cohesive_index = 1; UInt nb_quad_per_facet = model.getFEM("FacetsFEM").getNbQuadraturePoints(type_facet); MaterialCohesive & mat_cohesive = dynamic_cast(model.getMaterial(cohesive_index)); const Array & damage = mat_cohesive.getDamage(type_cohesive); FragmentManager fragment_manager(model, false); const Array & fragment_mass = fragment_manager.getMass(); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { model.checkCohesiveStress(); model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); /// apply boundary conditions model.applyBC(BC::Dirichlet::IncrementValue(-disp_increment, BC::_x), "Left_side"); model.applyBC(BC::Dirichlet::IncrementValue( disp_increment, BC::_x), "Right_side"); if(s % 1 == 0) { - // model.dump(); - + model.dump(); std::cout << "passing step " << s << "/" << max_steps << std::endl; fragment_manager.computeAllData(); /// check number of fragments UInt nb_fragment_num = fragment_manager.getNbFragment(); UInt nb_cohesive_elements = mesh.getNbElement(type_cohesive); UInt nb_fragment = 1; for (UInt el = 0; el < nb_cohesive_elements; ++el) { UInt q = 0; while (q < nb_quad_per_facet && Math::are_float_equal(damage(el*nb_quad_per_facet + q), 1)) ++q; if (q == nb_quad_per_facet) { ++nb_fragment; } } if (nb_fragment != nb_fragment_num) { std::cout << "The number of fragments is wrong!" << std::endl; return EXIT_FAILURE; } /// check mass computation Real total_mass = 0.; for (UInt frag = 0; frag < nb_fragment_num; ++frag) { total_mass += fragment_mass(frag); } if (!Math::are_float_equal(theoretical_mass, total_mass)) { std::cout << "The fragments' mass is wrong!" << std::endl; return EXIT_FAILURE; } } } /// check velocities UInt nb_fragment = fragment_manager.getNbFragment(); const Array & fragment_velocity = fragment_manager.getVelocity(); const Array & fragment_center = fragment_manager.getCenterOfMass(); Real fragment_length = L / nb_fragment; Real initial_position = -L / 2. + fragment_length / 2.; for (UInt frag = 0; frag < nb_fragment; ++frag) { Real theoretical_center = initial_position + fragment_length * frag; if (!Math::are_float_equal(fragment_center(frag, 0), theoretical_center)) { std::cout << "The fragments' center is wrong!" << std::endl; return EXIT_FAILURE; } Real initial_vel = fragment_center(frag, 0) * strain_rate; Math::setTolerance(100); if (!Math::are_float_equal(fragment_velocity(frag), initial_vel)) { std::cout << "The fragments' velocity is wrong!" << std::endl; return EXIT_FAILURE; } } finalize(); std::cout << "OK: test_cohesive_buildfragments was passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic.cc index a957eb4e2..10c3fc9c5 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic.cc @@ -1,186 +1,176 @@ /** * @file test_cohesive_extrinsic.cc * * @author Marco Vocialta * * @date Tue May 08 13:01:18 2012 * * @brief Test for cohesive elements * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include - /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" -#include "material.hh" -// #if defined(AKANTU_USE_IOHELPER) -// # include "io_helper.hh" -// #endif /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { - initialize(argc, argv); + initialize("material.dat", argc, argv); debug::setDebugLevel(dblWarning); const UInt spatial_dimension = 2; const UInt max_steps = 1000; Mesh mesh(spatial_dimension); mesh.read("triangle.msh"); SolidMechanicsModelCohesive model(mesh); /// model initialization - model.initFull("material.dat", SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); + model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); Real time_step = model.getStableTimeStep()*0.05; model.setTimeStep(time_step); std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); /* ------------------------------------------------------------------------ */ /* Facet part */ /* ------------------------------------------------------------------------ */ CohesiveElementInserter & inserter = model.getElementInserter(); inserter.setLimit('y', -0.30, -0.20); model.updateAutomaticInsertion(); /* ------------------------------------------------------------------------ */ /* End of facet part */ /* ------------------------------------------------------------------------ */ Array & position = mesh.getNodes(); Array & velocity = model.getVelocity(); Array & boundary = model.getBoundary(); Array & displacement = model.getDisplacement(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); /// boundary conditions for (UInt n = 0; n < nb_nodes; ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) boundary(n, 1) = true; if (position(n, 0) > 0.99 || position(n, 0) < -0.99) boundary(n, 0) = true; } /// initial conditions Real loading_rate = 0.5; Real disp_update = loading_rate * time_step; for (UInt n = 0; n < nb_nodes; ++n) { velocity(n, 1) = loading_rate * position(n, 1); } model.updateResidual(); model.setBaseName("extrinsic"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("residual" ); model.addDumpField("stress"); model.addDumpField("strain"); model.dump(); // std::ofstream edis("edis.txt"); // std::ofstream erev("erev.txt"); // Array & residual = model.getResidual(); // const Array & stress = model.getMaterial(0).getStress(type); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { /// update displacement on extreme nodes for (UInt n = 0; n < mesh.getNbNodes(); ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) displacement(n, 1) += disp_update * position(n, 1); } model.checkCohesiveStress(); model.solveStep(); if(s % 1 == 0) { model.dump(); std::cout << "passing step " << s << "/" << max_steps << std::endl; } // Real Ed = dynamic_cast (model.getMaterial(1)).getDissipatedEnergy(); // Real Er = dynamic_cast (model.getMaterial(1)).getReversibleEnergy(); // edis << s << " " // << Ed << std::endl; // erev << s << " " // << Er << std::endl; } // edis.close(); // erev.close(); // mesh.write("mesh_final.msh"); Real Ed = model.getEnergy("dissipated"); Real Edt = 200 * std::sqrt(2); std::cout << Ed << " " << Edt << std::endl; if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; finalize(); return EXIT_FAILURE; } // for (UInt n = 0; n < position.getSize(); ++n) { // for (UInt s = 0; s < spatial_dimension; ++s) { // position(n, s) += displacement(n, s); // } // } finalize(); std::cout << "OK: test_cohesive_extrinsic was passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_quadrangle.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_quadrangle.cc index 3e1ddc736..bb2329e0f 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_quadrangle.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_quadrangle.cc @@ -1,223 +1,212 @@ /** * @file test_cohesive_extrinsic_quadrangle.cc * * @author Marco Vocialta * * @date Wed Oct 03 10:20:53 2012 * * @brief Test for extrinsic cohesive elements and quadrangles * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" -#include "material.hh" -#if defined(AKANTU_USE_IOHELPER) -# include "io_helper.hh" -#endif /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { - initialize(argc, argv); - - debug::setDebugLevel(dblWarning); + initialize("material.dat", argc, argv); const UInt spatial_dimension = 2; const UInt max_steps = 1000; Mesh mesh(spatial_dimension); mesh.read("quadrangle.msh"); SolidMechanicsModelCohesive model(mesh); /// model initialization - model.initFull("material.dat", SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); + model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); Real time_step = model.getStableTimeStep()*0.05; model.setTimeStep(time_step); // std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); /* ------------------------------------------------------------------------ */ /* Facet part */ /* ------------------------------------------------------------------------ */ CohesiveElementInserter & inserter = model.getElementInserter(); inserter.setLimit('y', -0.05, 0.05); model.updateAutomaticInsertion(); /* ------------------------------------------------------------------------ */ /* End of facet part */ /* ------------------------------------------------------------------------ */ const Array & position = mesh.getNodes(); Array & velocity = model.getVelocity(); Array & boundary = model.getBoundary(); Array & displacement = model.getDisplacement(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); /// boundary conditions for (UInt n = 0; n < nb_nodes; ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) boundary(n, 1) = true; if (position(n, 0) > 0.99 || position(n, 0) < -0.99) boundary(n, 0) = true; } model.updateResidual(); // iohelper::ElemType paraview_type = iohelper::QUAD2; // UInt nb_element = mesh.getNbElement(type); // /// initialize the paraview output // iohelper::DumperParaview dumper; // dumper.SetMode(iohelper::TEXT); // dumper.SetPoints(mesh.getNodes().storage(), // spatial_dimension, mesh.getNbNodes(), "explicit"); // dumper.SetConnectivity((int *)mesh.getConnectivity(type).storage(), // paraview_type, nb_element, iohelper::C_MODE); // dumper.AddNodeDataField(model.getDisplacement().storage(), // spatial_dimension, "displacements"); // dumper.AddNodeDataField(model.getVelocity().storage(), // spatial_dimension, "velocity"); // dumper.AddNodeDataField(model.getAcceleration().storage(), // spatial_dimension, "acceleration"); // dumper.AddNodeDataField(model.getResidual().storage(), // spatial_dimension, "forces"); // dumper.AddElemDataField(model.getMaterial(0).getStrain(type).storage(), // spatial_dimension*spatial_dimension, "strain"); // dumper.AddElemDataField(model.getMaterial(0).getStress(type).storage(), // spatial_dimension*spatial_dimension, "stress"); // dumper.SetEmbeddedValue("displacements", 1); // dumper.SetEmbeddedValue("forces", 1); // dumper.SetPrefix("paraview/"); // dumper.Init(); // dumper.Dump(); /// initial conditions Real loading_rate = 0.2; Real disp_update = loading_rate * time_step; for (UInt n = 0; n < nb_nodes; ++n) { velocity(n, 1) = loading_rate * position(n, 1); } // std::ofstream edis("edis.txt"); // std::ofstream erev("erev.txt"); // Array & residual = model.getResidual(); // const Array & stress = model.getMaterial(0).getStress(type); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { /// update displacement on extreme nodes for (UInt n = 0; n < nb_nodes; ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) displacement(n, 1) += disp_update * position(n, 1); } model.checkCohesiveStress(); model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); if(s % 1 == 0) { // dumper.SetPoints(mesh.getNodes().storage(), // spatial_dimension, mesh.getNbNodes(), "explicit"); // dumper.SetConnectivity((int *)mesh.getConnectivity(type).storage(), // paraview_type, nb_element, iohelper::C_MODE); // dumper.AddNodeDataField(model.getDisplacement().storage(), // spatial_dimension, "displacements"); // dumper.AddNodeDataField(model.getVelocity().storage(), // spatial_dimension, "velocity"); // dumper.AddNodeDataField(model.getAcceleration().storage(), // spatial_dimension, "acceleration"); // dumper.AddNodeDataField(model.getResidual().storage(), // spatial_dimension, "forces"); // dumper.AddElemDataField(model.getMaterial(0).getStrain(type).storage(), // spatial_dimension*spatial_dimension, "strain"); // dumper.AddElemDataField(model.getMaterial(0).getStress(type).storage(), // spatial_dimension*spatial_dimension, "stress"); // dumper.SetEmbeddedValue("displacements", 1); // dumper.SetEmbeddedValue("forces", 1); // dumper.SetPrefix("paraview/"); // dumper.Init(); // dumper.Dump(); std::cout << "passing step " << s << "/" << max_steps << std::endl; } // Real Ed = dynamic_cast (model.getMaterial(1)).getDissipatedEnergy(); // Real Er = dynamic_cast (model.getMaterial(1)).getReversibleEnergy(); // edis << s << " " // << Ed << std::endl; // erev << s << " " // << Er << std::endl; } // edis.close(); // erev.close(); mesh.write("mesh_final.msh"); Real Ed = model.getEnergy("dissipated"); Real Edt = 200; std::cout << Ed << " " << Edt << std::endl; if (Ed < Edt * 0.99 || Ed > Edt * 1.01 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; return EXIT_FAILURE; } finalize(); std::cout << "OK: test_cohesive_extrinsic_quadrangle was passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_tetrahedron.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_tetrahedron.cc index ef738c5a0..be6fec17f 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_tetrahedron.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_tetrahedron.cc @@ -1,243 +1,235 @@ /** * @file test_cohesive_extrinsic_tetrahedron.cc * @author Marco Vocialta * @date Thu Sep 12 11:50:14 2013 * * @brief Test for serial extrinsic cohesive elements for tetrahedron * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" -#include "material.hh" #include "material_cohesive_linear.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; Real function(Real constant, Real x, Real y, Real z) { return constant + 2. * x + 3. * y + 4 * z; } int main(int argc, char *argv[]) { - initialize(argc, argv); - - debug::setDebugLevel(dblWarning); + initialize("material.dat", argc, argv); // const UInt max_steps = 1000; // Real increment = 0.005; const UInt spatial_dimension = 3; Math::setTolerance(1.e-12); ElementType type = _tetrahedron_10; ElementType type_facet = Mesh::getFacetType(type); ElementType type_cohesive = FEM::getCohesiveElementType(type_facet); Mesh mesh(spatial_dimension); mesh.read("tetrahedron.msh"); SolidMechanicsModelCohesive model(mesh); /// model initialization - model.initFull("material.dat", SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); + model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); const MaterialCohesiveLinear<3> & mat_cohesive = dynamic_cast < const MaterialCohesiveLinear<3> & > (model.getMaterial(1)); const Real sigma_c = mat_cohesive.getParam< RandomInternalField >("sigma_c"); const Real beta = mat_cohesive.getParam("beta"); // const Real G_cI = mat_cohesive.getParam("G_cI"); Array & position = mesh.getNodes(); /* ------------------------------------------------------------------------ */ /* Facet part */ /* ------------------------------------------------------------------------ */ /// compute quadrature points positions on facets const Mesh & mesh_facets = model.getMeshFacets(); UInt nb_facet = mesh_facets.getNbElement(type_facet); UInt nb_quad_per_facet = model.getFEM("FacetsFEM").getNbQuadraturePoints(type_facet); UInt nb_tot_quad = nb_quad_per_facet * nb_facet; Array quad_facets(nb_tot_quad, spatial_dimension); model.getFEM("FacetsFEM").interpolateOnQuadraturePoints(position, quad_facets, spatial_dimension, type_facet); /* ------------------------------------------------------------------------ */ /* End of facet part */ /* ------------------------------------------------------------------------ */ /// compute quadrature points position of the elements UInt nb_quad_per_element = model.getFEM().getNbQuadraturePoints(type); UInt nb_element = mesh.getNbElement(type); UInt nb_tot_quad_el = nb_quad_per_element * nb_element; Array quad_elements(nb_tot_quad_el, spatial_dimension); model.getFEM().interpolateOnQuadraturePoints(position, quad_elements, spatial_dimension, type); /// assign some values to stresses Array & stress = const_cast&>(model.getMaterial(0).getStress(type)); Array::iterator > stress_it = stress.begin(spatial_dimension, spatial_dimension); for (UInt q = 0; q < nb_tot_quad_el; ++q, ++stress_it) { /// compute values for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = i; j < spatial_dimension; ++j) { UInt index = i * spatial_dimension + j; (*stress_it)(i, j) = index * function(sigma_c * 5, quad_elements(q, 0), quad_elements(q, 1), quad_elements(q, 2)); } } /// fill symmetrical part for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < i; ++j) { (*stress_it)(i, j) = (*stress_it)(j, i); } } } /// compute stress on facet quads Array stress_facets(nb_tot_quad, spatial_dimension * spatial_dimension); Array::iterator > stress_facets_it = stress_facets.begin(spatial_dimension, spatial_dimension); for (UInt q = 0; q < nb_tot_quad; ++q, ++stress_facets_it) { /// compute values for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = i; j < spatial_dimension; ++j) { UInt index = i * spatial_dimension + j; (*stress_facets_it)(i, j) = index * function(sigma_c * 5, quad_facets(q, 0), quad_facets(q, 1), quad_facets(q, 2)); } } /// fill symmetrical part for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < i; ++j) { (*stress_facets_it)(i, j) = (*stress_facets_it)(j, i); } } } /// insert cohesive elements model.checkCohesiveStress(); /// check insertion stress const Array & normals = model.getFEM("FacetsFEM").getNormalsOnQuadPoints(type_facet); const Array & tangents = model.getTangents(type_facet); const Array & sigma_c_eff = mat_cohesive.getInsertionTraction(type_cohesive); Vector normal_stress(spatial_dimension); const Array > & coh_element_to_facet = mesh_facets.getElementToSubelement(type_facet); Array::iterator > quad_facet_stress = stress_facets.begin(spatial_dimension, spatial_dimension); Array::const_iterator > quad_normal = normals.begin(spatial_dimension); Array::const_iterator > quad_tangents = tangents.begin(tangents.getNbComponent()); for (UInt f = 0; f < nb_facet; ++f) { const Element & cohesive_element = coh_element_to_facet(f)[1]; for (UInt q = 0; q < nb_quad_per_facet; ++q, ++quad_facet_stress, ++quad_normal, ++quad_tangents) { if (cohesive_element == ElementNull) continue; normal_stress.mul(*quad_facet_stress, *quad_normal); Real normal_contrib = normal_stress.dot(*quad_normal); Real first_tangent_contrib = 0; for (UInt dim = 0; dim < spatial_dimension; ++dim) first_tangent_contrib += normal_stress(dim) * (*quad_tangents)(dim); Real second_tangent_contrib = 0; for (UInt dim = 0; dim < spatial_dimension; ++dim) second_tangent_contrib += normal_stress(dim) * (*quad_tangents)(dim + spatial_dimension); Real tangent_contrib = std::sqrt(first_tangent_contrib * first_tangent_contrib + second_tangent_contrib * second_tangent_contrib); normal_contrib = std::max(0., normal_contrib); Real effective_norm = std::sqrt(normal_contrib * normal_contrib + tangent_contrib * tangent_contrib / beta / beta); if (effective_norm < sigma_c) continue; if (!Math::are_float_equal(effective_norm, sigma_c_eff(cohesive_element.element * nb_quad_per_facet + q))) { std::cout << "Insertion tractions do not match" << std::endl; finalize(); return EXIT_FAILURE; } } } finalize(); std::cout << "OK: test_cohesive_extrinsic was passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic.cc index 39626fdd9..03fe6cc2c 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic.cc @@ -1,205 +1,205 @@ /** * @file test_cohesive_intrinsic.cc * * @author Marco Vocialta * * @date Tue May 08 13:01:18 2012 * * @brief Test for cohesive elements * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" #include "material.hh" #include "dumper_paraview.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; static void updateDisplacement(SolidMechanicsModelCohesive &, Array &, ElementType, Real); int main(int argc, char *argv[]) { - initialize(argc, argv); + initialize("material.dat", argc, argv); debug::setDebugLevel(dblWarning); const UInt spatial_dimension = 2; const UInt max_steps = 350; const ElementType type = _triangle_6; Mesh mesh(spatial_dimension); mesh.read("triangle.msh"); /* ------------------------------------------------------------------------ */ /* Facet part */ /* ------------------------------------------------------------------------ */ std::cout << mesh << std::endl; CohesiveElementInserter inserter(mesh); inserter.setLimit('x', -0.26, -0.24); inserter.insertIntrinsicElements(); mesh.write("mesh_cohesive.msh"); // std::cout << mesh << std::endl; /* ------------------------------------------------------------------------ */ /* End of facet part */ /* ------------------------------------------------------------------------ */ SolidMechanicsModelCohesive model(mesh); /// model initialization - model.initFull("material.dat"); + model.initFull(); Real time_step = model.getStableTimeStep()*0.8; model.setTimeStep(time_step); // std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); Array & boundary = model.getBoundary(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_element = mesh.getNbElement(type); /// boundary conditions for (UInt dim = 0; dim < spatial_dimension; ++dim) { for (UInt n = 0; n < nb_nodes; ++n) { boundary(n, dim) = true; } } model.updateResidual(); model.setBaseName("intrinsic"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("residual" ); model.addDumpField("stress"); model.addDumpField("strain"); model.addDumpField("force"); model.dump(); DumperParaview dumper("cohesive_elements_triangle"); dumper.registerMesh(mesh, spatial_dimension, _not_ghost, _ek_cohesive); DumperIOHelper::Field * cohesive_displacement = new DumperIOHelper::NodalField(model.getDisplacement()); cohesive_displacement->setPadding(3); dumper.registerField("displacement", cohesive_displacement); dumper.dump(); /// update displacement Array elements; Real * bary = new Real[spatial_dimension]; for (UInt el = 0; el < nb_element; ++el) { mesh.getBarycenter(el, type, bary); if (bary[0] > -0.25) elements.push_back(el); } delete[] bary; Real increment = 0.01; updateDisplacement(model, elements, type, increment); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); updateDisplacement(model, elements, type, increment); if(s % 1 == 0) { model.dump(); dumper.dump(); std::cout << "passing step " << s << "/" << max_steps << std::endl; } } Real Ed = model.getEnergy("dissipated"); Real Edt = 2 * sqrt(2); std::cout << Ed << " " << Edt << std::endl; if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; return EXIT_FAILURE; } finalize(); std::cout << "OK: test_cohesive_intrinsic was passed!" << std::endl; return EXIT_SUCCESS; } static void updateDisplacement(SolidMechanicsModelCohesive & model, Array & elements, ElementType type, Real increment) { Mesh & mesh = model.getFEM().getMesh(); UInt nb_element = elements.getSize(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); const Array & connectivity = mesh.getConnectivity(type); Array & displacement = model.getDisplacement(); Array update(nb_nodes); update.clear(); for (UInt el = 0; el < nb_element; ++el) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity(elements(el), n); if (!update(node)) { displacement(node, 0) += increment; // displacement(node, 1) += increment; update(node) = true; } } } } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_quadrangle.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_quadrangle.cc index a004a5c4d..32477d180 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_quadrangle.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_quadrangle.cc @@ -1,239 +1,235 @@ /** * @file test_cohesive_intrinsic_quadrangle.cc * * @author Marco Vocialta * * @date Wed Oct 03 10:20:53 2012 * * @brief Intrinsic cohesive elements' test for quadrangles * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" -#include "material.hh" #include "dumper_paraview.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; static void updateDisplacement(SolidMechanicsModelCohesive &, Array &, ElementType, Real); int main(int argc, char *argv[]) { - initialize(argc, argv); + initialize("material.dat", argc, argv); const UInt spatial_dimension = 2; const UInt max_steps = 350; const ElementType type = _quadrangle_4; Mesh mesh(spatial_dimension); mesh.read("quadrangle.msh"); /* ------------------------------------------------------------------------ */ /* Facet part */ /* ------------------------------------------------------------------------ */ debug::setDebugLevel(dblDump); std::cout << mesh << std::endl; debug::setDebugLevel(dblWarning); CohesiveElementInserter inserter(mesh); inserter.setLimit('x', -0.01, 0.01); inserter.insertIntrinsicElements(); mesh.write("mesh_cohesive_quadrangle.msh"); debug::setDebugLevel(dblDump); std::cout << mesh << std::endl; debug::setDebugLevel(dblWarning); /* ------------------------------------------------------------------------ */ /* End of facet part */ /* ------------------------------------------------------------------------ */ SolidMechanicsModelCohesive model(mesh); /// model initialization - model.initFull("material.dat"); + model.initFull(); Real time_step = model.getStableTimeStep()*0.8; model.setTimeStep(time_step); // std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); Array & boundary = model.getBoundary(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_element = mesh.getNbElement(type); /// boundary conditions for (UInt dim = 0; dim < spatial_dimension; ++dim) { for (UInt n = 0; n < nb_nodes; ++n) { boundary(n, dim) = true; } } model.updateResidual(); model.setBaseName("intrinsic_quadrangle"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("residual" ); model.addDumpField("stress"); model.addDumpField("strain"); model.addDumpField("force"); model.dump(); DumperParaview dumper("cohesive_elements_quadrangle"); dumper.registerMesh(mesh, spatial_dimension, _not_ghost, _ek_cohesive); DumperIOHelper::Field * cohesive_displacement = new DumperIOHelper::NodalField(model.getDisplacement()); cohesive_displacement->setPadding(3); dumper.registerField("displacement", cohesive_displacement); dumper.dump(); /// update displacement Array elements; Real * bary = new Real[spatial_dimension]; for (UInt el = 0; el < nb_element; ++el) { mesh.getBarycenter(el, type, bary); if (bary[0] > 0.) elements.push_back(el); } delete[] bary; Real increment = 0.01; updateDisplacement(model, elements, type, increment); // for (UInt n = 0; n < nb_nodes; ++n) { // if (position(n, 1) + displacement(n, 1) > 0) { // if (position(n, 0) == 0) { // displacement(n, 1) -= 0.25; // } // if (position(n, 0) == 1) { // displacement(n, 1) += 0.25; // } // } // } // std::ofstream edis("edis.txt"); // std::ofstream erev("erev.txt"); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); updateDisplacement(model, elements, type, increment); if(s % 1 == 0) { model.dump(); dumper.dump(); std::cout << "passing step " << s << "/" << max_steps << std::endl; } // // update displacement // for (UInt n = 0; n < nb_nodes; ++n) { // if (position(n, 1) + displacement(n, 1) > 0) { // displacement(n, 0) -= 0.01; // } // } // Real Ed = dynamic_cast (model.getMaterial(1)).getDissipatedEnergy(); // Real Er = dynamic_cast (model.getMaterial(1)).getReversibleEnergy(); // edis << s << " " // << Ed << std::endl; // erev << s << " " // << Er << std::endl; } // edis.close(); // erev.close(); Real Ed = model.getEnergy("dissipated"); Real Edt = 1; std::cout << Ed << " " << Edt << std::endl; if (Ed < Edt * 0.999 || Ed > Edt * 1.001) { std::cout << "The dissipated energy is incorrect" << std::endl; return EXIT_FAILURE; } finalize(); std::cout << "OK: test_cohesive_intrinsic_quadrangle was passed!" << std::endl; return EXIT_SUCCESS; } static void updateDisplacement(SolidMechanicsModelCohesive & model, Array & elements, ElementType type, Real increment) { Mesh & mesh = model.getFEM().getMesh(); UInt nb_element = elements.getSize(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); const Array & connectivity = mesh.getConnectivity(type); Array & displacement = model.getDisplacement(); Array update(nb_nodes); update.clear(); for (UInt el = 0; el < nb_element; ++el) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity(elements(el), n); if (!update(node)) { displacement(node, 0) += increment; // displacement(node, 1) += increment; update(node) = true; } } } } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron.cc index b5b51d505..8144376f5 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron.cc @@ -1,458 +1,449 @@ /** * @file test_cohesive_intrinsic_tetrahedron.cc * * @author Marco Vocialta * * @date Tue Aug 20 14:37:18 2013 * * @brief Test for cohesive elements * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" -#include "material.hh" #include "material_cohesive.hh" - /* -------------------------------------------------------------------------- */ using namespace akantu; void updateDisplacement(SolidMechanicsModelCohesive &, Array &, ElementType, Vector &); bool checkTractions(SolidMechanicsModelCohesive & model, ElementType type, Vector & opening, Vector & theoretical_traction, Matrix & rotation); void findNodesToCheck(const Mesh & mesh, const Array & elements, ElementType type, Array & nodes_to_check); bool checkEquilibrium(const Array & residual); bool checkResidual(const Array & residual, const Vector & traction, const Array & nodes_to_check, const Matrix & rotation); int main(int argc, char *argv[]) { - initialize(argc, argv); + initialize("material_tetrahedron.dat", argc, argv); // debug::setDebugLevel(dblDump); const UInt spatial_dimension = 3; const UInt max_steps = 60; const Real increment_constant = 0.01; Math::setTolerance(1.e-12); const ElementType type = _tetrahedron_10; Mesh mesh(spatial_dimension); mesh.read("tetrahedron.msh"); /* ------------------------------------------------------------------------ */ /* Facet part */ /* ------------------------------------------------------------------------ */ CohesiveElementInserter inserter(mesh); Array limits(spatial_dimension, 2); inserter.setLimit('x', -0.01, 0.01); inserter.insertIntrinsicElements(); // std::cout << mesh << std::endl; /* ------------------------------------------------------------------------ */ /* End of facet part */ /* ------------------------------------------------------------------------ */ - - SolidMechanicsModelCohesive model(mesh); /// model initialization - model.initFull("material_tetrahedron.dat"); + model.initFull(); Array & boundary = model.getBoundary(); boundary.set(true); UInt nb_element = mesh.getNbElement(type); model.updateResidual(); model.setBaseName("intrinsic_tetrahedron"); model.addDumpFieldVector("displacement"); model.addDumpField("residual"); model.dump(); model.setBaseNameToDumper("cohesive elements", "cohesive_elements_tetrahedron"); model.addDumpFieldVectorToDumper("cohesive elements", "displacement"); model.addDumpFieldToDumper("cohesive elements", "damage"); model.dump("cohesive elements"); /// find elements to displace Array elements; Real * bary = new Real[spatial_dimension]; for (UInt el = 0; el < nb_element; ++el) { mesh.getBarycenter(el, type, bary); if (bary[0] > 0.01) elements.push_back(el); } delete[] bary; /// find nodes to check Array nodes_to_check; findNodesToCheck(mesh, elements, type, nodes_to_check); /// rotate mesh Real angle = 1.; Matrix rotation(spatial_dimension, spatial_dimension); rotation.clear(); rotation(0, 0) = std::cos(angle); rotation(0, 1) = std::sin(angle) * -1.; rotation(1, 0) = std::sin(angle); rotation(1, 1) = std::cos(angle); rotation(2, 2) = 1.; Vector increment_tmp(spatial_dimension); for (UInt dim = 0; dim < spatial_dimension; ++dim) { increment_tmp(dim) = (dim + 1) * increment_constant; } Vector increment(spatial_dimension); increment.mul(rotation, increment_tmp); Array & position = mesh.getNodes(); Array position_tmp(position); Array::iterator > position_it = position.begin(spatial_dimension); Array::iterator > position_end = position.end(spatial_dimension); Array::iterator > position_tmp_it = position_tmp.begin(spatial_dimension); for (; position_it != position_end; ++position_it, ++position_tmp_it) position_it->mul(rotation, *position_tmp_it); model.dump(); model.dump("cohesive elements"); updateDisplacement(model, elements, type, increment); Real theoretical_Ed = 0; Vector opening(spatial_dimension); Vector traction(spatial_dimension); Vector opening_old(spatial_dimension); Vector traction_old(spatial_dimension); opening.clear(); traction.clear(); opening_old.clear(); traction_old.clear(); Vector Dt(spatial_dimension); Vector Do(spatial_dimension); const Array & residual = model.getResidual(); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { model.updateResidual(); opening += increment_tmp; if (checkTractions(model, type, opening, traction, rotation) || checkEquilibrium(residual) || checkResidual(residual, traction, nodes_to_check, rotation)) { finalize(); return EXIT_FAILURE; } /// compute energy Do = opening; Do -= opening_old; Dt = traction_old; Dt += traction; theoretical_Ed += .5 * Do.dot(Dt); opening_old = opening; traction_old = traction; updateDisplacement(model, elements, type, increment); if(s % 10 == 0) { std::cout << "passing step " << s << "/" << max_steps << std::endl; model.dump(); model.dump("cohesive elements"); } } model.dump(); model.dump("cohesive elements"); Real Ed = model.getEnergy("dissipated"); theoretical_Ed *= 4.; std::cout << Ed << " " << theoretical_Ed << std::endl; if (!Math::are_float_equal(Ed, theoretical_Ed) || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; finalize(); return EXIT_FAILURE; } finalize(); std::cout << "OK: test_cohesive_intrinsic_tetrahedron was passed!" << std::endl; return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ void updateDisplacement(SolidMechanicsModelCohesive & model, Array & elements, ElementType type, Vector & increment) { UInt spatial_dimension = model.getSpatialDimension(); Mesh & mesh = model.getFEM().getMesh(); UInt nb_element = elements.getSize(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); const Array & connectivity = mesh.getConnectivity(type); Array & displacement = model.getDisplacement(); Array update(nb_nodes); update.clear(); for (UInt el = 0; el < nb_element; ++el) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity(elements(el), n); if (!update(node)) { Vector node_disp(displacement.storage() + node * spatial_dimension, spatial_dimension); node_disp += increment; update(node) = true; } } } } /* -------------------------------------------------------------------------- */ bool checkTractions(SolidMechanicsModelCohesive & model, ElementType type, Vector & opening, Vector & theoretical_traction, Matrix & rotation) { UInt spatial_dimension = model.getSpatialDimension(); const MaterialCohesive & mat_cohesive = dynamic_cast < const MaterialCohesive & > (model.getMaterial(1)); const Real sigma_c = mat_cohesive.getParam< RandomInternalField >("sigma_c"); const Real beta = mat_cohesive.getParam("beta"); // const Real G_cI = mat_cohesive.getParam("G_cI"); // Real G_cII = mat_cohesive.getParam("G_cII"); const Real delta_0 = mat_cohesive.getParam("delta_0"); const Real kappa = mat_cohesive.getParam("kappa"); Real delta_c = delta_0 * sigma_c / (sigma_c - 1.); ElementType type_facet = Mesh::getFacetType(type); ElementType type_cohesive = FEM::getCohesiveElementType(type_facet); const Array & traction = mat_cohesive.getTraction(type_cohesive); const Array & damage = mat_cohesive.getDamage(type_cohesive); UInt nb_quad_per_el = model.getFEM("CohesiveFEM").getNbQuadraturePoints(type_cohesive); UInt nb_element = model.getMesh().getNbElement(type_cohesive); UInt tot_nb_quad = nb_element * nb_quad_per_el; Vector normal_opening(spatial_dimension); normal_opening.clear(); normal_opening(0) = opening(0); Real normal_opening_norm = normal_opening.norm(); Vector tangential_opening(spatial_dimension); tangential_opening.clear(); for (UInt dim = 1; dim < spatial_dimension; ++dim) tangential_opening(dim) = opening(dim); Real tangential_opening_norm = tangential_opening.norm(); Real beta2_kappa2 = beta * beta/kappa/kappa; Real beta2_kappa = beta * beta/kappa; Real delta = std::sqrt(tangential_opening_norm * tangential_opening_norm * beta2_kappa2 + normal_opening_norm * normal_opening_norm); delta = std::max(delta, delta_0); Real theoretical_damage = std::min(delta / delta_c, 1.); if (Math::are_float_equal(theoretical_damage, 1.)) theoretical_traction.clear(); else { theoretical_traction = tangential_opening; theoretical_traction *= beta2_kappa; theoretical_traction += normal_opening; theoretical_traction *= sigma_c / delta * (1. - theoretical_damage); } Vector theoretical_traction_rotated(spatial_dimension); theoretical_traction_rotated.mul(rotation, theoretical_traction); for (UInt q = 0; q < tot_nb_quad; ++q) { for (UInt dim = 0; dim < spatial_dimension; ++dim) { if (!Math::are_float_equal(theoretical_traction_rotated(dim), traction(q, dim))) { std::cout << "Tractions are incorrect" << std::endl; return 1; } } if (!Math::are_float_equal(theoretical_damage, damage(q))) { std::cout << "Damage is incorrect" << std::endl; return 1; } } return 0; } /* -------------------------------------------------------------------------- */ void findNodesToCheck(const Mesh & mesh, const Array & elements, ElementType type, Array & nodes_to_check) { const Array & connectivity = mesh.getConnectivity(type); const Array & position = mesh.getNodes(); UInt nb_nodes = position.getSize(); UInt nb_nodes_per_elem = connectivity.getNbComponent(); Array checked_nodes(nb_nodes); checked_nodes.clear(); for (UInt el = 0; el < elements.getSize(); ++el) { UInt element = elements(el); Vector conn_el(connectivity.storage() + nb_nodes_per_elem * element, nb_nodes_per_elem); for (UInt n = 0; n < nb_nodes_per_elem; ++n) { UInt node = conn_el(n); if (Math::are_float_equal(position(node, 0), 0.) && checked_nodes(node) == false) { checked_nodes(node) = true; nodes_to_check.push_back(node); } } } } /* -------------------------------------------------------------------------- */ bool checkEquilibrium(const Array & residual) { UInt spatial_dimension = residual.getNbComponent(); Vector residual_sum(spatial_dimension); residual_sum.clear(); Array::const_iterator > res_it = residual.begin(spatial_dimension); Array::const_iterator > res_end = residual.end(spatial_dimension); for (; res_it != res_end; ++res_it) residual_sum += *res_it; for (UInt s = 0; s < spatial_dimension; ++s) { if (!Math::are_float_equal(residual_sum(s), 0.)) { std::cout << "System is not in equilibrium!" << std::endl; return 1; } } return 0; } /* -------------------------------------------------------------------------- */ bool checkResidual(const Array & residual, const Vector & traction, const Array & nodes_to_check, const Matrix & rotation) { UInt spatial_dimension = residual.getNbComponent(); Vector total_force(spatial_dimension); total_force.clear(); for (UInt n = 0; n < nodes_to_check.getSize(); ++n) { UInt node = nodes_to_check(n); Vector res(residual.storage() + node * spatial_dimension, spatial_dimension); total_force += res; } Vector theoretical_total_force(spatial_dimension); theoretical_total_force.mul(rotation, traction); theoretical_total_force *= -1 * 2 * 2; for (UInt s = 0; s < spatial_dimension; ++s) { if (!Math::are_float_equal(total_force(s), theoretical_total_force(s))) { std::cout << "Total force isn't correct!" << std::endl; return 1; } } return 0; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron_fragmentation.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron_fragmentation.cc index 61c7d9290..c24f9e7e2 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron_fragmentation.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic/test_cohesive_intrinsic_tetrahedron_fragmentation.cc @@ -1,153 +1,149 @@ /** * @file test_cohesive_intrinsic_tetrahedron.cc * * @author Marco Vocialta * * @date Tue Aug 20 14:37:18 2013 * * @brief Test for cohesive elements * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" -#include "material.hh" #include "dumper_paraview.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { - initialize(argc, argv); + initialize("material.dat", argc, argv); // debug::setDebugLevel(dblDump); ElementType type = _tetrahedron_10; const UInt spatial_dimension = 3; const UInt max_steps = 100; Mesh mesh(spatial_dimension); mesh.read("tetrahedron_full.msh"); /* ------------------------------------------------------------------------ */ /* Facet part */ /* ------------------------------------------------------------------------ */ CohesiveElementInserter inserter(mesh); inserter.insertIntrinsicElements(); /* ------------------------------------------------------------------------ */ /* End of facet part */ /* ------------------------------------------------------------------------ */ SolidMechanicsModelCohesive model(mesh); /// model initialization - model.initFull("material.dat"); + model.initFull(); Real time_step = model.getStableTimeStep()*0.8; model.setTimeStep(time_step); // std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); model.updateResidual(); model.setBaseName("intrinsic_tetrahedron_fragmentation"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("residual" ); model.addDumpField("stress"); model.addDumpField("strain"); model.dump(); DumperParaview dumper("cohesive_elements_tetrahedron_fragmentation"); dumper.registerMesh(mesh, spatial_dimension, _not_ghost, _ek_cohesive); DumperIOHelper::Field * cohesive_displacement = new DumperIOHelper::NodalField(model.getDisplacement()); cohesive_displacement->setPadding(3); dumper.registerField("displacement", cohesive_displacement); // dumper.registerField("damage", new DumperIOHelper:: // HomogenizedField(model, // "damage", // spatial_dimension, // _not_ghost, // _ek_cohesive)); dumper.dump(); /// update displacement UInt nb_element = mesh.getNbElement(type); UInt nb_nodes = mesh.getNbNodes(); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); Real * bary = new Real[spatial_dimension]; const Array & connectivity = mesh.getConnectivity(type); Array & displacement = model.getDisplacement(); Array update(nb_nodes); for (UInt s = 0; s < max_steps; ++s) { Real increment = s / 10.; update.clear(); for (UInt el = 0; el < nb_element; ++el) { mesh.getBarycenter(el, type, bary); for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity(el, n); if (!update(node)) { for (UInt dim = 0; dim < spatial_dimension; ++dim) { displacement(node, dim) = increment * bary[dim]; update(node) = true; } } } } if (s % 10 == 0) { model.dump(); dumper.dump(); } } delete[] bary; if (nb_nodes != nb_element * Mesh::getNbNodesPerElement(type)) { std::cout << "Wrong number of nodes" << std::endl; finalize(); return EXIT_FAILURE; } finalize(); std::cout << "OK: test_cohesive_intrinsic_tetrahedron was passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic_impl/test_cohesive_intrinsic_impl.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic_impl/test_cohesive_intrinsic_impl.cc index bd2358c51..556b55260 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic_impl/test_cohesive_intrinsic_impl.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_intrinsic_impl/test_cohesive_intrinsic_impl.cc @@ -1,165 +1,162 @@ /** * @file test_cohesive_intrinsic_impl.cc * * @author Seyedeh Mohadeseh Taheri Mousavi * @author Marco Vocialta * * @date Mon Jul 09 14:13:56 2012 * * @brief Test for cohesive elements * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" #include "material_cohesive.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { - initialize(argc, argv); + initialize("material.dat", argc, argv); debug::setDebugLevel(dblError); const UInt spatial_dimension = 2; const ElementType type = _triangle_6; Mesh mesh(spatial_dimension); mesh.read("implicit.msh"); CohesiveElementInserter inserter(mesh); inserter.setLimit('y', 0.9, 1.1); inserter.insertIntrinsicElements(); // mesh.write("implicit_cohesive.msh"); SolidMechanicsModelCohesive model(mesh); /// model initialization - model.initFull("material.dat", SolidMechanicsModelCohesiveOptions(_static)); + model.initFull(SolidMechanicsModelCohesiveOptions(_static)); /// boundary conditions Array & boundary = model.getBoundary(); UInt nb_nodes = mesh.getNbNodes(); Array & position = mesh.getNodes(); Array & displacement = model.getDisplacement(); const ElementType type_facet = mesh.getFacetType(type); for (UInt n = 0; n < nb_nodes; ++n) { if (std::abs(position(n,1))< Math::getTolerance()){ boundary(n, 1) = true; displacement(n,1) = 0.0; } if ((std::abs(position(n,0))< Math::getTolerance())&& (position(n,1)< 1.1)){ boundary(n, 0) = true; displacement(n,0) = 0.0; } if ((std::abs(position(n,0)-1)< Math::getTolerance())&&(std::abs(position(n,1)-1)< Math::getTolerance())){ boundary(n, 0) = true; displacement(n,0) = 0.0; } if (std::abs(position(n,1)-2)< Math::getTolerance()){ boundary(n, 1) = true; } } model.setBaseName("intrinsic_impl"); model.addDumpField("displacement"); // model.addDumpField("mass" ); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); // model.addDumpField("damage" ); model.addDumpField("stress" ); model.addDumpField("strain" ); model.dump(); const MaterialCohesive & mat_coh = dynamic_cast< const MaterialCohesive &> (model.getMaterial(1)); ElementType type_cohesive = FEM::getCohesiveElementType(type_facet); const Array & opening = mat_coh.getOpening(type_cohesive); //const Array & traction = mat_coh.getTraction(type_cohesive); model.updateResidual(); const Array & residual = model.getResidual(); UInt max_step = 1000; Real increment = 3./max_step; Real error_tol = 10e-6; std::ofstream fout; fout.open("output"); /// Main loop for ( UInt nstep = 0; nstep < max_step; ++nstep){ for (UInt n = 0; n < nb_nodes; ++n) { if (std::abs(position(n,1)-2)< Math::getTolerance()){ displacement(n,1) += increment; } } bool converged = model.solveStep<_scm_newton_raphson_tangent, _scc_residual>(1e-5, 100); AKANTU_DEBUG_ASSERT(converged, "Did not converge"); model.dump(); Real resid = 0; for (UInt n = 0; n < nb_nodes; ++n) { if (std::abs(position(n, 1) - 2.)/2. < Math::getTolerance()){ resid += residual(n, 1); } } Real analytical = exp(1) * std::abs(opening(0, 1)) * exp (-std::abs(opening(0, 1))/0.5)/0.5; //the residual force is comparing with the theoretical value of the cohesive law error_tol = std::abs((std::abs(resid) - analytical)/analytical); fout << nstep << " " << -resid << " " << analytical << " " << error_tol << std::endl; if (error_tol > 1e-3) { std::cout << "Relative error: " << error_tol << std::endl; std::cout << "Test failed!" << std::endl; return EXIT_FAILURE; } } fout.close(); finalize(); std::cout << "Test passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_facet_stress_synchronizer/test_cohesive_facet_stress_synchronizer.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_facet_stress_synchronizer/test_cohesive_facet_stress_synchronizer.cc index 9ea97c332..e2dd5df79 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_facet_stress_synchronizer/test_cohesive_facet_stress_synchronizer.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_facet_stress_synchronizer/test_cohesive_facet_stress_synchronizer.cc @@ -1,228 +1,217 @@ /** * @file test_cohesive_facet_stress_synchronizer.cc * @author Marco Vocialta * @date Mon Oct 28 17:24:55 2013 * * @brief Test for facet stress synchronizer * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" -#include "material.hh" -// #if defined(AKANTU_USE_IOHELPER) -// # include "io_helper.hh" -// #endif /* -------------------------------------------------------------------------- */ using namespace akantu; Real function(Real constant, Real x, Real y, Real z) { return constant + 2. * x + 3. * y + 4 * z; } int main(int argc, char *argv[]) { - initialize(argc, argv); - - debug::setDebugLevel(dblWarning); + initialize("material.dat", argc, argv); const UInt spatial_dimension = 3; ElementType type = _tetrahedron_10; ElementType type_facet = Mesh::getFacetType(type); Math::setTolerance(1.e-11); Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); akantu::MeshPartition * partition = NULL; if(prank == 0) { // Read the mesh mesh.read("tetrahedron.msh"); /// partition the mesh partition = new MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); } SolidMechanicsModelCohesive model(mesh); model.initParallel(partition, NULL, true); - model.initFull("material.dat", SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); + model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); Array & position = mesh.getNodes(); /* ------------------------------------------------------------------------ */ /* Facet part */ /* ------------------------------------------------------------------------ */ /// compute quadrature points positions on facets const Mesh & mesh_facets = model.getMeshFacets(); UInt nb_facet = mesh_facets.getNbElement(type_facet); UInt nb_quad_per_facet = model.getFEM("FacetsFEM").getNbQuadraturePoints(type_facet); UInt nb_tot_quad = nb_quad_per_facet * nb_facet; Array quad_facets(nb_tot_quad, spatial_dimension); model.getFEM("FacetsFEM").interpolateOnQuadraturePoints(position, quad_facets, spatial_dimension, type_facet); /* ------------------------------------------------------------------------ */ /* End of facet part */ /* ------------------------------------------------------------------------ */ /// compute quadrature points position of the elements UInt nb_quad_per_element = model.getFEM().getNbQuadraturePoints(type); UInt nb_element = mesh.getNbElement(type); UInt nb_tot_quad_el = nb_quad_per_element * nb_element; Array quad_elements(nb_tot_quad_el, spatial_dimension); model.getFEM().interpolateOnQuadraturePoints(position, quad_elements, spatial_dimension, type); /// assign some values to stresses Array & stress = const_cast&>(model.getMaterial(0).getStress(type)); Array::iterator > stress_it = stress.begin(spatial_dimension, spatial_dimension); for (UInt q = 0; q < nb_tot_quad_el; ++q, ++stress_it) { /// compute values for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = i; j < spatial_dimension; ++j) { UInt index = i * spatial_dimension + j; (*stress_it)(i, j) = function(index, quad_elements(q, 0), quad_elements(q, 1), quad_elements(q, 2)); } } /// fill symmetrical part for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < i; ++j) { (*stress_it)(i, j) = (*stress_it)(j, i); } } // stress_it->clear(); // for (UInt i = 0; i < spatial_dimension; ++i) // (*stress_it)(i, i) = sigma_c * 5; } /// compute and communicate stress on facets model.checkCohesiveStress(); /* ------------------------------------------------------------------------ */ /* Check facet stress */ /* ------------------------------------------------------------------------ */ const Array & facet_stress = model.getStressOnFacets(type_facet); const Array & facet_check = model.getElementInserter().getCheckFacets(type_facet); const Array > & elements_to_facet = model.getMeshFacets().getElementToSubelement(type_facet); Array::iterator > quad_facet_it = quad_facets.begin(spatial_dimension); Array::const_iterator > facet_stress_it = facet_stress.begin(spatial_dimension, spatial_dimension * 2); Matrix current_stress(spatial_dimension, spatial_dimension); for (UInt f = 0; f < nb_facet; ++f) { if (!facet_check(f) || (elements_to_facet(f)[0].ghost_type == _not_ghost && elements_to_facet(f)[1].ghost_type == _not_ghost)) { quad_facet_it += nb_quad_per_facet; facet_stress_it += nb_quad_per_facet; continue; } for (UInt q = 0; q < nb_quad_per_facet; ++q, ++quad_facet_it, ++facet_stress_it) { /// compute current_stress for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = i; j < spatial_dimension; ++j) { UInt index = i * spatial_dimension + j; current_stress(i, j) = function(index, (*quad_facet_it)(0), (*quad_facet_it)(1), (*quad_facet_it)(2)); } } /// fill symmetrical part for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < i; ++j) { current_stress(i, j) = current_stress(j, i); } } /// compare it to interpolated one for (UInt s = 0; s < 2; ++s) { Matrix stress_to_check(facet_stress_it->storage() + s * spatial_dimension * spatial_dimension, spatial_dimension, spatial_dimension); for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < spatial_dimension; ++j) { if (!Math::are_float_equal(stress_to_check(i, j), current_stress(i, j))) { std::cout << "Stress doesn't match" << std::endl; finalize(); return EXIT_FAILURE; } } } } } } finalize(); if (prank == 0) std::cout << "OK: test_cohesive_facet_stress_synchronizer passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_buildfragments/test_cohesive_parallel_buildfragments.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_buildfragments/test_cohesive_parallel_buildfragments.cc index f3d69df18..c25a13cb1 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_buildfragments/test_cohesive_parallel_buildfragments.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_buildfragments/test_cohesive_parallel_buildfragments.cc @@ -1,400 +1,391 @@ /** * @file test_cohesive_parallel_buildfragments.cc * @author Marco Vocialta * @date Tue Dec 17 12:03:03 2013 * * @brief Test to build fragments in parallel * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" #include "material_cohesive.hh" #include "fragment_manager.hh" - - -//#include "io_helper.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; void verticalInsertionLimit(SolidMechanicsModelCohesive &); void displaceElements(SolidMechanicsModelCohesive &, const Real, const Real); bool isInertiaEqual(const Vector &, const Vector &); int main(int argc, char *argv[]) { - initialize(argc, argv); - - debug::setDebugLevel(dblWarning); + initialize("material.dat", argc, argv); const UInt spatial_dimension = 3; const UInt total_nb_fragment = 5; Math::setTolerance(1.e-11); Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); akantu::MeshPartition * partition = NULL; if(prank == 0) { // Read the mesh mesh.read("mesh.msh"); /// partition the mesh MeshUtils::purifyMesh(mesh); partition = new MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); } SolidMechanicsModelCohesive model(mesh); model.initParallel(partition, NULL, true); delete partition; /// model initialization - model.initFull("material.dat", - SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); + model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); mesh.computeBoundingBox(); Real L = mesh.getXMax() - mesh.getXMin(); Real h = mesh.getYMax() - mesh.getYMin(); Real rho = model.getMaterial("bulk").getParam("rho"); Real theoretical_mass = L * h * h * rho; Real frag_theo_mass = theoretical_mass / total_nb_fragment; UInt nb_element = mesh.getNbElement(spatial_dimension, _not_ghost, _ek_regular); comm.allReduce(&nb_element, 1, _so_sum); UInt nb_element_per_fragment = nb_element / total_nb_fragment; FragmentManager fragment_manager(model); fragment_manager.computeAllData(); fragment_manager.getNbBigFragments(nb_element_per_fragment + 1); model.setBaseName("extrinsic"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity"); model.addDumpField("stress"); model.addDumpField("partitions"); model.addDumpField("fragments"); model.addDumpField("fragments mass"); model.addDumpField("moments of inertia"); model.addDumpField("elements per fragment"); model.dump(); model.setBaseNameToDumper("cohesive elements", "cohesive_elements_test"); model.addDumpFieldVectorToDumper("cohesive elements", "displacement"); model.addDumpFieldToDumper("cohesive elements", "damage"); model.dump("cohesive elements"); /// set check facets verticalInsertionLimit(model); model.assembleMassLumped(); model.synchronizeBoundaries(); /// impose initial displacement Array & displacement = model.getDisplacement(); Array & velocity = model.getVelocity(); const Array & position = mesh.getNodes(); UInt nb_nodes = mesh.getNbNodes(); for (UInt n = 0; n < nb_nodes; ++n) { displacement(n, 0) = position(n, 0) * 0.1; velocity(n, 0) = position(n, 0); } model.updateResidual(); model.checkCohesiveStress(); model.dump(); model.dump("cohesive elements"); const Array & fragment_mass = fragment_manager.getMass(); const Array & fragment_center = fragment_manager.getCenterOfMass(); Real el_size = L / total_nb_fragment; Real lim = -L/2 + el_size * 0.99; /// define theoretical inertia moments Vector small_frag_inertia(spatial_dimension); small_frag_inertia(0) = frag_theo_mass * (h*h + h*h) / 12.; small_frag_inertia(1) = frag_theo_mass * (el_size*el_size + h*h) / 12.; small_frag_inertia(2) = frag_theo_mass * (el_size*el_size + h*h) / 12.; const Array & inertia_moments = fragment_manager.getMomentsOfInertia(); Array::const_iterator< Vector > inertia_moments_begin = inertia_moments.begin(spatial_dimension); /// displace one fragment each time for (UInt frag = 1; frag <= total_nb_fragment; ++frag) { if (prank == 0) std::cout << "Generating fragment: " << frag << std::endl; fragment_manager.computeAllData(); /// check number of big fragments UInt nb_big_fragment = fragment_manager.getNbBigFragments(nb_element_per_fragment + 1); if (frag < total_nb_fragment) { if (nb_big_fragment != 1) { AKANTU_DEBUG_ERROR("The number of big fragments is wrong: " << nb_big_fragment); return EXIT_FAILURE; } } else { if (nb_big_fragment != 0) { AKANTU_DEBUG_ERROR("The number of big fragments is wrong: " << nb_big_fragment); return EXIT_FAILURE; } } /// check number of fragments UInt nb_fragment_num = fragment_manager.getNbFragment(); if (nb_fragment_num != frag) { AKANTU_DEBUG_ERROR("The number of fragments is wrong! Numerical: " << nb_fragment_num << " Theoretical: " << frag); return EXIT_FAILURE; } /// check mass computation if (frag < total_nb_fragment) { Real total_mass = 0.; UInt small_fragments = 0; for (UInt f = 0; f < nb_fragment_num; ++f) { const Vector & current_inertia = inertia_moments_begin[f]; if (Math::are_float_equal(fragment_mass(f, 0), frag_theo_mass)) { /// check center of mass if (fragment_center(f, 0) > (L * frag / total_nb_fragment - L / 2)) { AKANTU_DEBUG_ERROR("Fragment center is wrong!"); return EXIT_FAILURE; } /// check moment of inertia if (!isInertiaEqual(current_inertia, small_frag_inertia)) { AKANTU_DEBUG_ERROR("Inertia moments are wrong"); return EXIT_FAILURE; } ++small_fragments; total_mass += frag_theo_mass; } else { /// check the moment of inertia for the biggest fragment Real big_frag_mass = frag_theo_mass * (total_nb_fragment - frag + 1); Real big_frag_size = el_size * (total_nb_fragment - frag + 1); Vector big_frag_inertia(spatial_dimension); big_frag_inertia(0) = big_frag_mass * (h*h + h*h) / 12.; big_frag_inertia(1) = big_frag_mass * (big_frag_size*big_frag_size + h*h) / 12.; big_frag_inertia(2) = big_frag_mass * (big_frag_size*big_frag_size + h*h) / 12.; if (!isInertiaEqual(current_inertia, big_frag_inertia)) { AKANTU_DEBUG_ERROR("Inertia moments are wrong"); return EXIT_FAILURE; } } } if (small_fragments != nb_fragment_num - 1) { AKANTU_DEBUG_ERROR("The number of small fragments is wrong!"); return EXIT_FAILURE; } if (!Math::are_float_equal(total_mass, small_fragments * frag_theo_mass)) { AKANTU_DEBUG_ERROR("The mass of small fragments is wrong!"); return EXIT_FAILURE; } } model.dump(); model.dump("cohesive elements"); /// displace fragments displaceElements(model, lim, el_size * 2); model.updateResidual(); lim += el_size; } model.dump(); model.dump("cohesive elements"); /// check centers const Array & fragment_velocity = fragment_manager.getVelocity(); Real initial_position = -L / 2. + el_size / 2.; for (UInt frag = 0; frag < total_nb_fragment; ++frag) { Real theoretical_center = initial_position + el_size * frag; UInt f_index = 0; while (f_index < total_nb_fragment && !Math::are_float_equal(fragment_center(f_index, 0), theoretical_center)) ++f_index; if (f_index == total_nb_fragment) { AKANTU_DEBUG_ERROR("The fragments' center is wrong!"); return EXIT_FAILURE; } f_index = 0; while (f_index < total_nb_fragment && !Math::are_float_equal(fragment_velocity(f_index, 0), theoretical_center)) ++f_index; if (f_index == total_nb_fragment) { AKANTU_DEBUG_ERROR("The fragments' velocity is wrong!"); return EXIT_FAILURE; } } finalize(); if (prank == 0) std::cout << "OK: test_cohesive_buildfragments was passed!" << std::endl; return EXIT_SUCCESS; } void verticalInsertionLimit(SolidMechanicsModelCohesive & model) { UInt spatial_dimension = model.getSpatialDimension(); const Mesh & mesh_facets = model.getMeshFacets(); const Array & position = mesh_facets.getNodes(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, ghost_type); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, ghost_type); for(; it != end; ++it) { ElementType type = *it; Array & check_facets = model.getElementInserter().getCheckFacets(type, ghost_type); const Array & connectivity = mesh_facets.getConnectivity(type, ghost_type); UInt nb_nodes_per_facet = connectivity.getNbComponent(); for (UInt f = 0; f < check_facets.getSize(); ++f) { if (!check_facets(f)) continue; UInt nb_aligned_nodes = 1; Real first_node_pos = position(connectivity(f, 0), 0); for (; nb_aligned_nodes < nb_nodes_per_facet; ++nb_aligned_nodes) { Real other_node_pos = position(connectivity(f, nb_aligned_nodes), 0); if (std::abs(first_node_pos - other_node_pos) > 1.e-10) break; } if (nb_aligned_nodes != nb_nodes_per_facet) { Vector barycenter(spatial_dimension); mesh_facets.getBarycenter(f, type, barycenter.storage(), ghost_type); check_facets(f) = false; } } } } } void displaceElements(SolidMechanicsModelCohesive & model, const Real lim, const Real amount) { UInt spatial_dimension = model.getSpatialDimension(); Array & displacement = model.getDisplacement(); Mesh & mesh = model.getMesh(); UInt nb_nodes = mesh.getNbNodes(); Array displaced(nb_nodes); displaced.clear(); Vector barycenter(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 end = mesh.lastType(spatial_dimension, ghost_type); for(; it != end; ++it) { ElementType type = *it; const Array & connectivity = mesh.getConnectivity(type, ghost_type); UInt nb_element = connectivity.getSize(); UInt nb_nodes_per_element = connectivity.getNbComponent(); Array::const_iterator > conn_el = connectivity.begin(nb_nodes_per_element); for (UInt el = 0; el < nb_element; ++el) { mesh.getBarycenter(el, type, barycenter.storage(), ghost_type); if (barycenter(0) < lim) { const Vector & conn = conn_el[el]; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = conn(n); if (!displaced(node)) { displacement(node, 0) -= amount; displaced(node) = true; } } } } } } } bool isInertiaEqual(const Vector & a, const Vector & b) { UInt nb_terms = a.size(); UInt equal_terms = 0; Real tolerance = 1.e-2; while (equal_terms < nb_terms && std::abs(a(equal_terms) - b(equal_terms)) / a(equal_terms) < tolerance) ++equal_terms; return equal_terms == nb_terms; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic.cc index 286253661..dc5671929 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic.cc @@ -1,212 +1,206 @@ /** * @file test_cohesive_parallel.cc * @author Marco Vocialta * @date Wed Nov 28 16:59:11 2012 * * @brief parallel test for cohesive elements * * @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 . * */ /* -------------------------------------------------------------------------- */ -#include "mesh_io.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" #include "dumper_paraview.hh" -#include "static_communicator.hh" -#include "dof_synchronizer.hh" - /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { - initialize(argc, argv); - debug::setDebugLevel(dblWarning); + initialize("material.dat", argc, argv); const UInt max_steps = 500; UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); akantu::MeshPartition * partition = NULL; if(prank == 0) { // Read the mesh mesh.read("mesh.msh"); /// partition the mesh partition = new MeshPartitionScotch(mesh, spatial_dimension); // debug::setDebugLevel(dblDump); partition->partitionate(psize); // debug::setDebugLevel(dblWarning); } SolidMechanicsModelCohesive model(mesh); model.initParallel(partition, NULL, true); // debug::setDebugLevel(dblDump); // std::cout << mesh << std::endl; // debug::setDebugLevel(dblWarning); - model.initFull("material.dat", SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); + model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); /* ------------------------------------------------------------------------ */ /* Facet part */ /* ------------------------------------------------------------------------ */ CohesiveElementInserter & inserter = model.getElementInserter(); inserter.setLimit('y', -0.30, -0.20); model.updateAutomaticInsertion(); /* ------------------------------------------------------------------------ */ /* End of facet part */ /* ------------------------------------------------------------------------ */ // debug::setDebugLevel(dblDump); // std::cout << mesh_facets << std::endl; // debug::setDebugLevel(dblWarning); Real time_step = model.getStableTimeStep()*0.1; model.setTimeStep(time_step); std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); Array & position = mesh.getNodes(); Array & velocity = model.getVelocity(); Array & boundary = model.getBoundary(); Array & displacement = model.getDisplacement(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); /// boundary conditions for (UInt n = 0; n < nb_nodes; ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) boundary(n, 1) = true; if (position(n, 0) > 0.99 || position(n, 0) < -0.99) boundary(n, 0) = true; } /// initial conditions Real loading_rate = 0.5; Real disp_update = loading_rate * time_step; for (UInt n = 0; n < nb_nodes; ++n) { velocity(n, 1) = loading_rate * position(n, 1); } model.synchronizeBoundaries(); model.updateResidual(); model.setBaseName("extrinsic_parallel"); model.addDumpFieldVector("displacement"); model.addDumpFieldVector("velocity" ); model.addDumpFieldVector("acceleration"); model.addDumpFieldVector("residual" ); model.addDumpFieldTensor("stress"); model.addDumpFieldTensor("strain"); model.addDumpField("partitions"); // model.getDumper().getDumper().setMode(iohelper::BASE64); model.dump(); DumperParaview dumper("cohesive_elements"); dumper.registerMesh(mesh, spatial_dimension, _not_ghost, _ek_cohesive); DumperIOHelper::Field * cohesive_displacement = new DumperIOHelper::NodalField(model.getDisplacement()); cohesive_displacement->setPadding(3); dumper.registerField("displacement", cohesive_displacement); // dumper.registerField("damage", new DumperIOHelper:: // HomogenizedField(model, // "damage", // spatial_dimension, // _not_ghost, // _ek_cohesive)); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { /// update displacement on extreme nodes for (UInt n = 0; n < nb_nodes; ++n) { if (position(n, 1) > 0.99 || position(n, 1) < -0.99) displacement(n, 1) += disp_update * position(n, 1); } model.checkCohesiveStress(); model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); // model.dump(); if(s % 10 == 0) { if(prank == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } // // update displacement // for (UInt n = 0; n < nb_nodes; ++n) { // if (position(n, 1) + displacement(n, 1) > 0) { // displacement(n, 0) -= 0.01; // } // } // Real Ed = dynamic_cast (model.getMaterial(1)).getDissipatedEnergy(); // Real Er = dynamic_cast (model.getMaterial(1)).getReversibleEnergy(); // edis << s << " " // << Ed << std::endl; // erev << s << " " // << Er << std::endl; } dumper.dump(); // edis.close(); // erev.close(); Real Ed = model.getEnergy("dissipated"); Real Edt = 200 * sqrt(2); if(prank == 0) { std::cout << Ed << " " << Edt << std::endl; if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; finalize(); return EXIT_FAILURE; } } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron.cc index 621110df5..82b422ff5 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron.cc @@ -1,247 +1,242 @@ /** * @file test_cohesive_parallel_extrinsic_tetrahedron.cc * @author Marco Vocialta * @date Fri Sep 20 16:53:10 2013 * * @brief 3D extrinsic cohesive elements test * * @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 . * */ /* -------------------------------------------------------------------------- */ -#include "mesh_io.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" -#include "dumper_paraview.hh" -#include "static_communicator.hh" -#include "dof_synchronizer.hh" #include "material_cohesive_linear.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; Real function(Real constant, Real x, Real y, Real z) { return constant + 2. * x + 3. * y + 4 * z; } int main(int argc, char *argv[]) { - initialize(argc, argv); + initialize("material.dat", argc, argv); debug::setDebugLevel(dblWarning); // const UInt max_steps = 1000; // Real increment = 0.005; const UInt spatial_dimension = 3; Math::setTolerance(1.e-12); ElementType type = _tetrahedron_10; ElementType type_facet = Mesh::getFacetType(type); ElementType type_cohesive = FEM::getCohesiveElementType(type_facet); Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); akantu::MeshPartition * partition = NULL; if(prank == 0) { // Read the mesh mesh.read("tetrahedron.msh"); /// partition the mesh partition = new MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); } SolidMechanicsModelCohesive model(mesh); /// model initialization model.initParallel(partition, NULL, true); - model.initFull("material.dat", SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); + model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); const MaterialCohesiveLinear<3> & mat_cohesive = dynamic_cast < const MaterialCohesiveLinear<3> & > (model.getMaterial(1)); const Real sigma_c = mat_cohesive.getParam< RandomInternalField >("sigma_c"); const Real beta = mat_cohesive.getParam("beta"); // const Real G_cI = mat_cohesive.getParam("G_cI"); Array & position = mesh.getNodes(); /* ------------------------------------------------------------------------ */ /* Facet part */ /* ------------------------------------------------------------------------ */ /// compute quadrature points positions on facets const Mesh & mesh_facets = model.getMeshFacets(); UInt nb_facet = mesh_facets.getNbElement(type_facet); UInt nb_quad_per_facet = model.getFEM("FacetsFEM").getNbQuadraturePoints(type_facet); UInt nb_tot_quad = nb_quad_per_facet * nb_facet; Array quad_facets(nb_tot_quad, spatial_dimension); model.getFEM("FacetsFEM").interpolateOnQuadraturePoints(position, quad_facets, spatial_dimension, type_facet); /* ------------------------------------------------------------------------ */ /* End of facet part */ /* ------------------------------------------------------------------------ */ /// compute quadrature points position of the elements UInt nb_quad_per_element = model.getFEM().getNbQuadraturePoints(type); UInt nb_element = mesh.getNbElement(type); UInt nb_tot_quad_el = nb_quad_per_element * nb_element; Array quad_elements(nb_tot_quad_el, spatial_dimension); model.getFEM().interpolateOnQuadraturePoints(position, quad_elements, spatial_dimension, type); /// assign some values to stresses Array & stress = const_cast&>(model.getMaterial(0).getStress(type)); Array::iterator > stress_it = stress.begin(spatial_dimension, spatial_dimension); for (UInt q = 0; q < nb_tot_quad_el; ++q, ++stress_it) { /// compute values for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = i; j < spatial_dimension; ++j) { UInt index = i * spatial_dimension + j; (*stress_it)(i, j) = index * function(sigma_c * 5, quad_elements(q, 0), quad_elements(q, 1), quad_elements(q, 2)); } } /// fill symmetrical part for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < i; ++j) { (*stress_it)(i, j) = (*stress_it)(j, i); } } } /// compute stress on facet quads Array stress_facets(nb_tot_quad, spatial_dimension * spatial_dimension); Array::iterator > stress_facets_it = stress_facets.begin(spatial_dimension, spatial_dimension); for (UInt q = 0; q < nb_tot_quad; ++q, ++stress_facets_it) { /// compute values for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = i; j < spatial_dimension; ++j) { UInt index = i * spatial_dimension + j; (*stress_facets_it)(i, j) = index * function(sigma_c * 5, quad_facets(q, 0), quad_facets(q, 1), quad_facets(q, 2)); } } /// fill symmetrical part for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < i; ++j) { (*stress_facets_it)(i, j) = (*stress_facets_it)(j, i); } } } /// insert cohesive elements model.checkCohesiveStress(); /// check insertion stress const Array & normals = model.getFEM("FacetsFEM").getNormalsOnQuadPoints(type_facet); const Array & tangents = model.getTangents(type_facet); const Array & sigma_c_eff = mat_cohesive.getInsertionTraction(type_cohesive); Vector normal_stress(spatial_dimension); const Array > & coh_element_to_facet = mesh_facets.getElementToSubelement(type_facet); Array::iterator > quad_facet_stress = stress_facets.begin(spatial_dimension, spatial_dimension); Array::const_iterator > quad_normal = normals.begin(spatial_dimension); Array::const_iterator > quad_tangents = tangents.begin(tangents.getNbComponent()); for (UInt f = 0; f < nb_facet; ++f) { const Element & cohesive_element = coh_element_to_facet(f)[1]; for (UInt q = 0; q < nb_quad_per_facet; ++q, ++quad_facet_stress, ++quad_normal, ++quad_tangents) { if (cohesive_element == ElementNull) continue; normal_stress.mul(*quad_facet_stress, *quad_normal); Real normal_contrib = normal_stress.dot(*quad_normal); Real first_tangent_contrib = 0; for (UInt dim = 0; dim < spatial_dimension; ++dim) first_tangent_contrib += normal_stress(dim) * (*quad_tangents)(dim); Real second_tangent_contrib = 0; for (UInt dim = 0; dim < spatial_dimension; ++dim) second_tangent_contrib += normal_stress(dim) * (*quad_tangents)(dim + spatial_dimension); Real tangent_contrib = std::sqrt(first_tangent_contrib * first_tangent_contrib + second_tangent_contrib * second_tangent_contrib); normal_contrib = std::max(0., normal_contrib); Real effective_norm = std::sqrt(normal_contrib * normal_contrib + tangent_contrib * tangent_contrib / beta / beta); if (effective_norm < sigma_c) continue; if (!Math::are_float_equal(effective_norm, sigma_c_eff(cohesive_element.element * nb_quad_per_facet + q))) { std::cout << "Insertion tractions do not match" << std::endl; finalize(); return EXIT_FAILURE; } } } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron_displacement.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron_displacement.cc index 99e40ad72..05216aec3 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron_displacement.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic/test_cohesive_parallel_extrinsic_tetrahedron_displacement.cc @@ -1,415 +1,411 @@ /** * @file test_cohesive_parallel_extrinsic_tetrahedron_displacement.cc * @author Marco Vocialta * @date Mon Nov 18 10:04:13 2013 * * @brief Displacement test for 3D cohesive elements * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -#include "mesh_io.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" #include "dumper_paraview.hh" -#include "static_communicator.hh" -#include "dof_synchronizer.hh" #include "material_cohesive_linear.hh" #ifdef AKANTU_USE_IOHELPER # include "dumper_paraview.hh" # include "dumper_iohelper_tmpl.hh" # include "dumper_iohelper_tmpl_homogenizing_field.hh" # include "dumper_iohelper_tmpl_material_internal_field.hh" #endif /* -------------------------------------------------------------------------- */ using namespace akantu; bool checkDisplacement(SolidMechanicsModelCohesive & model, ElementType type, std::ofstream & error_output, UInt step, bool barycenters); int main(int argc, char *argv[]) { - initialize(argc, argv); + initialize("material.dat", argc, argv); debug::setDebugLevel(dblWarning); const UInt max_steps = 500; Math::setTolerance(1.e-12); UInt spatial_dimension = 3; ElementType type = _tetrahedron_10; Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); akantu::MeshPartition * partition = NULL; if(prank == 0) { // Read the mesh mesh.read("tetrahedron.msh"); /// partition the mesh partition = new MeshPartitionScotch(mesh, spatial_dimension); // debug::setDebugLevel(dblDump); partition->partitionate(psize); // debug::setDebugLevel(dblWarning); } SolidMechanicsModelCohesive model(mesh); model.initParallel(partition, NULL, true); // debug::setDebugLevel(dblDump); // std::cout << mesh << std::endl; // debug::setDebugLevel(dblWarning); - model.initFull("material.dat", SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); + model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); /* ------------------------------------------------------------------------ */ /* Facet part */ /* ------------------------------------------------------------------------ */ // Array limits(spatial_dimension, 2); // limits(0, 0) = -0.01; // limits(0, 1) = 0.01; // limits(1, 0) = -100; // limits(1, 1) = 100; // limits(2, 0) = -100; // limits(2, 1) = 100; // model.enableFacetsCheckOnArea(limits); /* ------------------------------------------------------------------------ */ /* End of facet part */ /* ------------------------------------------------------------------------ */ // debug::setDebugLevel(dblDump); // std::cout << mesh_facets << std::endl; // debug::setDebugLevel(dblWarning); Real time_step = model.getStableTimeStep()*0.1; model.setTimeStep(time_step); std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); Array & position = mesh.getNodes(); Array & velocity = model.getVelocity(); Array & boundary = model.getBoundary(); Array & displacement = model.getDisplacement(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); /// boundary conditions for (UInt n = 0; n < nb_nodes; ++n) { if (position(n, 0) > 0.99 || position(n, 0) < -0.99) { for (UInt dim = 0; dim < spatial_dimension; ++dim) { boundary(n, dim) = true; } } if (position(n, 0) > 0.99 || position(n, 0) < -0.99) { for (UInt dim = 0; dim < spatial_dimension; ++dim) { boundary(n, dim) = true; } } } // #if defined (AKANTU_DEBUG_TOOLS) // Vector facet_center(spatial_dimension); // facet_center(0) = 0; // facet_center(1) = -0.16666667; // facet_center(2) = 0.5; // debug::element_manager.setMesh(mesh); // debug::element_manager.addModule(debug::_dm_material_cohesive); // debug::element_manager.addModule(debug::_dm_debug_tools); // //debug::element_manager.addModule(debug::_dm_integrator); // #endif /// initial conditions Real loading_rate = 1; Real disp_update = loading_rate * time_step; for (UInt n = 0; n < nb_nodes; ++n) { velocity(n, 0) = loading_rate * position(n, 0); velocity(n, 1) = loading_rate * position(n, 0); } model.synchronizeBoundaries(); model.updateResidual(); std::stringstream paraview_output; paraview_output << "extrinsic_parallel_tetrahedron_" << psize; model.setBaseName(paraview_output.str()); model.addDumpFieldVector("displacement"); model.addDumpFieldVector("velocity" ); model.addDumpFieldVector("acceleration"); model.addDumpFieldVector("residual" ); model.addDumpFieldTensor("stress"); model.addDumpFieldTensor("strain"); model.addDumpField("partitions"); // model.getDumper().getDumper().setMode(iohelper::BASE64); model.dump(); model.addDumpFieldVectorToDumper("cohesive elements", "displacement"); model.addDumpFieldVectorToDumper("cohesive elements", "damage"); model.dump("cohesive elements"); std::stringstream error_stream; error_stream << "error" << ".csv"; std::ofstream error_output; error_output.open(error_stream.str().c_str()); error_output << "# Step, Average, Max, Min" << std::endl; if (checkDisplacement(model, type, error_output, 0, true)) {} /// Main loop for (UInt s = 1; s <= max_steps; ++s) { /// update displacement on extreme nodes for (UInt n = 0; n < mesh.getNbNodes(); ++n) { if (position(n, 0) > 0.99 || position(n, 0) < -0.99) { displacement(n, 0) += disp_update * position(n, 0); displacement(n, 1) += disp_update * position(n, 0); } } model.checkCohesiveStress(); model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); if(s % 100 == 0) { if(prank == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } } model.dump(); model.dump("cohesive elements"); if (!checkDisplacement(model, type, error_output, max_steps, false)) { finalize(); return EXIT_FAILURE; } finalize(); return EXIT_SUCCESS; } bool checkDisplacement(SolidMechanicsModelCohesive & model, ElementType type, std::ofstream & error_output, UInt step, bool barycenters) { Mesh & mesh = model.getMesh(); UInt spatial_dimension = mesh.getSpatialDimension(); const Array & connectivity = mesh.getConnectivity(type); const Array & displacement = model.getDisplacement(); UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_elem = Mesh::getNbNodesPerElement(type); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); if (psize == 1) { std::stringstream displacement_file; displacement_file << "displacement/displacement_" << std::setfill('0') << std::setw(6) << step; std::ofstream displacement_output; displacement_output.open(displacement_file.str().c_str()); for (UInt el = 0; el < nb_element; ++el) { for (UInt n = 0; n < nb_nodes_per_elem; ++n) { UInt node = connectivity(el, n); for (UInt dim = 0; dim < spatial_dimension; ++dim) { displacement_output << std::setprecision(15) << displacement(node, dim) << " "; } displacement_output << std::endl; } } displacement_output.close(); if (barycenters) { std::stringstream barycenter_file; barycenter_file << "displacement/barycenters"; std::ofstream barycenter_output; barycenter_output.open(barycenter_file.str().c_str()); Element element(type, 0); Vector bary(spatial_dimension); for (UInt el = 0; el < nb_element; ++el) { element.element = el; mesh.getBarycenter(element, bary); for (UInt dim = 0; dim < spatial_dimension; ++dim) { barycenter_output << std::setprecision(15) << bary(dim) << " "; } barycenter_output << std::endl; } barycenter_output.close(); } } else { if (barycenters) return true; /// read data std::stringstream displacement_file; displacement_file << "displacement/displacement_" << std::setfill('0') << std::setw(6) << step; std::ifstream displacement_input; displacement_input.open(displacement_file.str().c_str()); Array displacement_serial(0, spatial_dimension); Vector disp_tmp(spatial_dimension); while (displacement_input.good()) { for (UInt i = 0; i < spatial_dimension; ++i) displacement_input >> disp_tmp(i); displacement_serial.push_back(disp_tmp); } std::stringstream barycenter_file; barycenter_file << "displacement/barycenters"; std::ifstream barycenter_input; barycenter_input.open(barycenter_file.str().c_str()); Array barycenter_serial(0, spatial_dimension); while (barycenter_input.good()) { for (UInt dim = 0; dim < spatial_dimension; ++dim) barycenter_input >> disp_tmp(dim); barycenter_serial.push_back(disp_tmp); } Element element(type, 0); Vector bary(spatial_dimension); Array::iterator > it; Array::iterator > begin = barycenter_serial.begin(spatial_dimension); Array::iterator > end = barycenter_serial.end(spatial_dimension); Array::const_iterator > disp_it; Array::iterator > disp_serial_it; Vector difference(spatial_dimension); Array error; /// compute error for (UInt el = 0; el < nb_element; ++el) { element.element = el; mesh.getBarycenter(element, bary); /// find element for (it = begin; it != end; ++it) { UInt matched_dim = 0; while (matched_dim < spatial_dimension && Math::are_float_equal(bary(matched_dim), (*it)(matched_dim))) ++matched_dim; if (matched_dim == spatial_dimension) break; } if (it == end) { std::cout << "Element barycenter not found!" << std::endl; return false; } UInt matched_el = it - begin; disp_serial_it = displacement_serial.begin(spatial_dimension) + matched_el * nb_nodes_per_elem; for (UInt n = 0; n < nb_nodes_per_elem; ++n, ++disp_serial_it) { UInt node = connectivity(el, n); if (!mesh.isLocalOrMasterNode(node)) continue; disp_it = displacement.begin(spatial_dimension) + node; difference = *disp_it; difference -= *disp_serial_it; error.push_back(difference.norm()); } } /// compute average error Real average_error = std::accumulate(error.begin(), error.end(), 0.); comm.allReduce(&average_error, 1, _so_sum); UInt error_size = error.getSize(); comm.allReduce(&error_size, 1, _so_sum); average_error /= error_size; /// compute maximum and minimum Real max_error = *std::max_element(error.begin(), error.end()); comm.allReduce(&max_error, 1, _so_max); Real min_error = *std::min_element(error.begin(), error.end()); comm.allReduce(&min_error, 1, _so_min); /// output data if (prank == 0) { error_output << step << ", " << average_error << ", " << max_error << ", " << min_error << std::endl; } if (max_error > 1.e-9) { std::cout << "Displacement error is too big!" << std::endl; return false; } } return true; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic_IG_TG/test_cohesive_parallel_extrinsic_IG_TG.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic_IG_TG/test_cohesive_parallel_extrinsic_IG_TG.cc index 894239f21..4cd4ed2cf 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic_IG_TG/test_cohesive_parallel_extrinsic_IG_TG.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_extrinsic_IG_TG/test_cohesive_parallel_extrinsic_IG_TG.cc @@ -1,277 +1,271 @@ /** * @file test_cohesive_extrinsic_IG_TG.cc * * @author Seyedeh Mohadeseh Taheri Mousavi * @author Marco Vocialta * * @date Thu April 18 13:31:00 2013 * * @brief Test for considering different cohesive properties for * intergranular (IG) and transgranular (TG) fractures in extrinsic * cohesive elements * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model_cohesive.hh" -#include "material.hh" #include "material_cohesive_linear.hh" #if defined(AKANTU_USE_IOHELPER) # include "dumper_paraview.hh" #endif /* -------------------------------------------------------------------------- */ using namespace akantu; class MultiGrainMaterialSelector : public DefaultMaterialCohesiveSelector { public: MultiGrainMaterialSelector(const SolidMechanicsModelCohesive & model, const ID & transgranular_id, const ID & intergranular_id) : DefaultMaterialCohesiveSelector(model), transgranular_id(transgranular_id), intergranular_id(intergranular_id), model(model), mesh(model.getMesh()), mesh_facets(model.getMeshFacets()), spatial_dimension(model.getSpatialDimension()), nb_IG(0), nb_TG(0) { } UInt operator()(const Element & element) { if(mesh_facets.getSpatialDimension(element.type) == (spatial_dimension - 1)) { const std::vector & element_to_subelement = mesh_facets.getElementToSubelement(element.type, element.ghost_type)(element.element); const Element & el1 = element_to_subelement[0]; const Element & el2 = element_to_subelement[1]; UInt grain_id1 = mesh.getData("tag_0", el1.type, el1.ghost_type)(el1.element); if(el2 != ElementNull) { UInt grain_id2 = mesh.getData("tag_0", el2.type, el2.ghost_type)(el2.element); if (grain_id1 == grain_id2){ //transgranular = 0 indicator nb_TG++; return model.getMaterialIndex(transgranular_id); } else { //intergranular = 1 indicator nb_IG++; return model.getMaterialIndex(intergranular_id); } } else { //transgranular = 0 indicator nb_TG++; return model.getMaterialIndex(transgranular_id); } } else { return DefaultMaterialCohesiveSelector::operator()(element); } } private: ID transgranular_id, intergranular_id; const SolidMechanicsModelCohesive & model; const Mesh & mesh; const Mesh & mesh_facets; UInt spatial_dimension; UInt nb_IG; UInt nb_TG; }; int main(int argc, char *argv[]) { - initialize(argc, argv); + initialize("material.dat", argc, argv); debug::setDebugLevel(dblWarning); const UInt spatial_dimension = 2; const UInt max_steps = 500; Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); akantu::MeshPartition * partition = NULL; if(prank == 0) { mesh.read("square.msh"); partition = new MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); } SolidMechanicsModelCohesive model(mesh); /// model initialization model.initParallel(partition, NULL, true); delete partition; MultiGrainMaterialSelector material_selector(model, "TG_cohesive", "IG_cohesive"); model.setMaterialSelector(material_selector); - model.initFull("material.dat", SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true, false)); + model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true, false)); Real time_step = model.getStableTimeStep()*0.1; model.setTimeStep(time_step); // std::cout << "Time step: " << time_step << std::endl; // std::cout << mesh << std::endl; Array & position = mesh.getNodes(); Array & velocity = model.getVelocity(); Array & boundary = model.getBoundary(); Array & displacement = model.getDisplacement(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); /// boundary conditions for (UInt n = 0; n < nb_nodes; ++n) { if (position(n, 1) > 0.99|| position(n, 1) < -0.99) boundary(n, 1) = true; if (position(n, 0) > 0.99 || position(n, 0) < -0.99) boundary(n, 0) = true; } model.synchronizeBoundaries(); model.updateResidual(); model.setBaseName("extrinsic"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("residual" ); model.addDumpField("stress"); model.addDumpField("strain"); model.addDumpField("partitions"); DumperParaview dumper("cohesive_elements"); dumper.registerMesh(mesh, spatial_dimension, _not_ghost, _ek_cohesive); DumperIOHelper::Field * cohesive_displacement = new DumperIOHelper::NodalField(model.getDisplacement()); cohesive_displacement->setPadding(3); dumper.registerField("displacement", cohesive_displacement); dumper.dump(); /// initial conditions Real loading_rate = 0.1; // bar_height = 2 Real VI = loading_rate * 2* 0.5; for (UInt n = 0; n < nb_nodes; ++n) { velocity(n, 1) = loading_rate * position(n, 1); velocity(n, 0) = loading_rate * position(n, 0); } // std::ofstream edis("edis.txt"); // std::ofstream erev("erev.txt"); // Array & residual = model.getResidual(); model.dump(); // const Array & stress = model.getMaterial(0).getStress(type); Real dispy = 0; // UInt nb_coh_elem = 0; /// Main loop for (UInt s = 1; s <= max_steps; ++s) { dispy += VI * time_step; /// update displacement on extreme nodes for (UInt n = 0; n < mesh.getNbNodes(); ++n) { if (position(n, 1) > 0.99){ displacement(n, 1) = dispy; velocity(n,1) = VI;} if (position(n, 1) < -0.99){ displacement(n, 1) = -dispy; velocity(n,1) = -VI;} if (position(n, 0) > 0.99){ displacement(n, 0) = dispy; velocity(n,0) = VI;} if (position(n, 0) < -0.99){ displacement(n, 0) = -dispy; velocity(n,0) = -VI;} } model.checkCohesiveStress(); model.solveStep(); if(s % 10 == 0) { if(prank == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } // Real Ed = model.getEnergy("dissipated"); // edis << s << " " // << Ed << std::endl; // erev << s << " " // << Er << std::endl; } model.dump(); dumper.dump(); // edis.close(); // erev.close(); // mesh.write("mesh_final.msh"); Real Ed = model.getEnergy("dissipated"); Real Edt = 40; if(prank == 0) std::cout << Ed << " " << Edt << std::endl; if (Ed < Edt * 0.99 || Ed > Edt * 1.01 || std::isnan(Ed)) { if(prank == 0) std::cout << "The dissipated energy is incorrect" << std::endl; finalize(); return EXIT_FAILURE; } // for (UInt n = 0; n < position.getSize(); ++n) { // for (UInt s = 0; s < spatial_dimension; ++s) { // position(n, s) += displacement(n, s); // } // } finalize(); if(prank == 0) std::cout << "OK: test_cohesive_extrinsic_IG_TG was passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic.cc index c302078b8..bfaf04a76 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic.cc @@ -1,174 +1,166 @@ /** * @file test_cohesive_parallel_intrinsic.cc * @author Marco Vocialta * @date Wed Nov 28 16:59:11 2012 * * @brief parallel test for intrinsic cohesive elements * * @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 . * */ /* -------------------------------------------------------------------------- */ -#include "mesh_io.hh" -#include "mesh_utils.hh" -#include "model.hh" #include "solid_mechanics_model_cohesive.hh" -#include "dumper_paraview.hh" -#include "static_communicator.hh" -#include "dof_synchronizer.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { - initialize(argc, argv); - debug::setDebugLevel(dblWarning); + initialize("material.dat", argc, argv); const UInt max_steps = 350; UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); akantu::MeshPartition * partition = NULL; if(prank == 0) { // Read the mesh mesh.read("mesh.msh"); /// insert cohesive elements CohesiveElementInserter inserter(mesh); inserter.setLimit('x', -0.26, -0.24); inserter.insertIntrinsicElements(); /// partition the mesh partition = new MeshPartitionScotch(mesh, spatial_dimension); // debug::setDebugLevel(dblDump); partition->partitionate(psize); // debug::setDebugLevel(dblWarning); } SolidMechanicsModelCohesive model(mesh); model.initParallel(partition); debug::setDebugLevel(dblDump); std::cout << mesh << std::endl; debug::setDebugLevel(dblWarning); - model.initFull("material.dat"); + model.initFull(); Real time_step = model.getStableTimeStep()*0.8; model.setTimeStep(time_step); // std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); Array & position = mesh.getNodes(); Array & velocity = model.getVelocity(); Array & boundary = model.getBoundary(); // Array & displacement = model.getDisplacement(); // const Array & residual = model.getResidual(); UInt nb_nodes = mesh.getNbNodes(); Real epsilon = std::numeric_limits::epsilon(); for (UInt n = 0; n < nb_nodes; ++n) { if (std::abs(position(n, 0) - 1.) < epsilon) boundary(n, 0) = true; } model.synchronizeBoundaries(); model.updateResidual(); model.setBaseName("intrinsic_parallel"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("residual" ); model.addDumpField("stress"); model.addDumpField("strain"); //model.addDumpField("partitions"); model.addDumpField("force"); - model.getDumper().getDumper().setMode(iohelper::BASE64); model.dump(); /// initial conditions Real loading_rate = .2; for (UInt n = 0; n < nb_nodes; ++n) { velocity(n, 0) = loading_rate * position(n, 0); } /// Main loop for (UInt s = 1; s <= max_steps; ++s) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); if(s % 1 == 0) { model.dump(); if(prank == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } // // update displacement // for (UInt n = 0; n < nb_nodes; ++n) { // if (position(n, 1) + displacement(n, 1) > 0) { // displacement(n, 0) -= 0.01; // } // } // Real Ed = dynamic_cast (model.getMaterial(1)).getDissipatedEnergy(); // Real Er = dynamic_cast (model.getMaterial(1)).getReversibleEnergy(); // edis << s << " " // << Ed << std::endl; // erev << s << " " // << Er << std::endl; } // edis.close(); // erev.close(); Real Ed = model.getEnergy("dissipated"); Real Edt = 2 * sqrt(2); if(prank == 0) { std::cout << Ed << " " << Edt << std::endl; if (std::abs((Ed - Edt) / Edt) > 0.01 || std::isnan(Ed)) { std::cout << "The dissipated energy is incorrect" << std::endl; return EXIT_FAILURE; } } finalize(); if(prank == 0) std::cout << "OK: Test passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic_tetrahedron.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic_tetrahedron.cc index 50c9dbdb0..4b708dc1f 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic_tetrahedron.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_parallel_cohesive/test_cohesive_parallel_intrinsic/test_cohesive_parallel_intrinsic_tetrahedron.cc @@ -1,742 +1,736 @@ /** * @file test_cohesive_parallel_intrinsic_tetrahedron.cc * @author Marco Vocialta * @date Fri Sep 20 15:59:40 2013 * * @brief Test for 3D intrinsic cohesive elements simulation in parallel * * @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 . * */ /* -------------------------------------------------------------------------- */ -#include "mesh_io.hh" -#include "mesh_utils.hh" -#include "model.hh" #include "solid_mechanics_model_cohesive.hh" #include "dumper_paraview.hh" -#include "static_communicator.hh" -#include "dof_synchronizer.hh" #include "material_cohesive.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; void updateDisplacement(SolidMechanicsModelCohesive & model, const ByElementTypeUInt & elements, Vector & increment); bool checkTractions(SolidMechanicsModelCohesive & model, Vector & opening, Vector & theoretical_traction, Matrix & rotation); void findNodesToCheck(const Mesh & mesh, const ByElementTypeUInt & elements, Array & nodes_to_check, Int psize); bool checkEquilibrium(const Mesh & mesh, const Array & residual); bool checkResidual(const Array & residual, const Vector & traction, const Array & nodes_to_check, const Matrix & rotation); void findElementsToDisplace(const Mesh & mesh, ByElementTypeUInt & elements); int main(int argc, char *argv[]) { - initialize(argc, argv); - debug::setDebugLevel(dblInfo); + initialize("material_tetrahedron.dat", argc, argv); const UInt spatial_dimension = 3; const UInt max_steps = 60; const Real increment_constant = 0.01; ElementType type = _tetrahedron_10; Math::setTolerance(1.e-12); Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); UInt nb_nodes_to_check_serial = 0; UInt total_nb_nodes = 0; UInt nb_elements_check_serial = 0; Array nodes_to_check_serial; akantu::MeshPartition * partition = NULL; if(prank == 0) { // Read the mesh mesh.read("tetrahedron.msh"); /// count nodes with zero position const Array & position = mesh.getNodes(); for (UInt n = 0; n < position.getSize(); ++n) { if (Math::are_float_equal(position(n, 0), 0.)) ++nb_nodes_to_check_serial; } /// insert cohesive elements CohesiveElementInserter inserter(mesh); inserter.setLimit('x', -0.01, 0.01); inserter.insertIntrinsicElements(); total_nb_nodes = mesh.getNbNodes(); /// find nodes to check in serial ByElementTypeUInt elements_serial("elements_serial", ""); findElementsToDisplace(mesh, elements_serial); nb_elements_check_serial = elements_serial(type).getSize(); findNodesToCheck(mesh, elements_serial, nodes_to_check_serial, 1); /// partition the mesh partition = new MeshPartitionScotch(mesh, spatial_dimension); debug::setDebugLevel(dblDump); partition->partitionate(psize); debug::setDebugLevel(dblInfo); } comm.broadcast(&nb_nodes_to_check_serial, 1, 0); comm.broadcast(&nb_elements_check_serial, 1, 0); SolidMechanicsModelCohesive model(mesh); model.initParallel(partition); - model.initFull("material_tetrahedron.dat"); + model.initFull(); { comm.broadcast(&total_nb_nodes, 1, 0); Array nb_local_nodes(psize); nb_local_nodes.clear(); for (UInt n = 0; n < mesh.getNbNodes(); ++n) { if (mesh.isLocalOrMasterNode(n)) ++nb_local_nodes(prank); } comm.allGather(nb_local_nodes.storage(), 1); UInt total_nb_nodes_parallel = std::accumulate(nb_local_nodes.begin(), nb_local_nodes.end(), 0); Array global_nodes_list(total_nb_nodes_parallel); UInt first_global_node = std::accumulate(nb_local_nodes.begin(), nb_local_nodes.begin() + prank, 0); for (UInt n = 0; n < mesh.getNbNodes(); ++n) { if (mesh.isLocalOrMasterNode(n)) { global_nodes_list(first_global_node) = mesh.getNodeGlobalId(n); ++first_global_node; } } comm.allGatherV(global_nodes_list.storage(), nb_local_nodes.storage()); if (prank == 0) std::cout << "Maximum node index: " << *(std::max_element(global_nodes_list.begin(), global_nodes_list.end())) << std::endl; Array repeated_nodes; repeated_nodes.resize(0); for (UInt n = 0; n < total_nb_nodes_parallel; ++n) { UInt appearances = std::count(global_nodes_list.begin() + n, global_nodes_list.end(), global_nodes_list(n)); if (appearances > 1) { std::cout << "Node " << global_nodes_list(n) << " appears " << appearances << " times" << std::endl; std::cout << " in position: " << n; repeated_nodes.push_back(global_nodes_list(n)); UInt * node_position = global_nodes_list.storage() + n; for (UInt i = 1; i < appearances; ++i) { node_position = std::find(node_position + 1, global_nodes_list.storage() + total_nb_nodes_parallel, global_nodes_list(n)); UInt current_index = node_position - global_nodes_list.storage(); std::cout << ", " << current_index; } std::cout << std::endl << std::endl; } } for (UInt n = 0; n < mesh.getNbNodes(); ++n) { UInt global_node = mesh.getNodeGlobalId(n); if (std::find(repeated_nodes.begin(), repeated_nodes.end(), global_node) != repeated_nodes.end()) { std::cout << "Repeated global node " << global_node << " corresponds to local node " << n << std::endl; } } if (total_nb_nodes != total_nb_nodes_parallel) { if (prank == 0) { std::cout << "Error: total number of nodes is wrong in parallel" << std::endl; std::cout << "Serial: " << total_nb_nodes << " Parallel: " << total_nb_nodes_parallel << std::endl; } finalize(); return EXIT_FAILURE; } } model.updateResidual(); model.setBaseName("intrinsic_parallel_tetrahedron"); model.addDumpFieldVector("displacement"); model.addDumpField("residual"); model.addDumpField("partitions"); model.dump(); DumperParaview dumper("cohesive_elements_parallel_tetrahedron"); dumper.registerMesh(mesh, spatial_dimension, _not_ghost, _ek_cohesive); DumperIOHelper::Field * cohesive_displacement = new DumperIOHelper::NodalField(model.getDisplacement()); cohesive_displacement->setPadding(3); dumper.registerField("displacement", cohesive_displacement); dumper.dump(); /// find elements to displace ByElementTypeUInt elements("elements", ""); findElementsToDisplace(mesh, elements); UInt nb_elements_check = elements(type).getSize(); comm.allReduce(&nb_elements_check, 1, _so_sum); if (nb_elements_check != nb_elements_check_serial) { if (prank == 0) { std::cout << "Error: number of elements to check is wrong" << std::endl; std::cout << "Serial: " << nb_elements_check_serial << " Parallel: " << nb_elements_check << std::endl; } finalize(); return EXIT_FAILURE; } /// find nodes to check Array nodes_to_check; findNodesToCheck(mesh, elements, nodes_to_check, psize); Vector nodes_to_check_size(psize); nodes_to_check_size(prank) = nodes_to_check.getSize(); comm.allGather(nodes_to_check_size.storage(), 1); UInt nodes_to_check_global_size = std::accumulate(nodes_to_check_size.storage(), nodes_to_check_size.storage() + psize, 0); Array nodes_to_check_global(nodes_to_check_global_size); UInt begin_index = std::accumulate(nodes_to_check_size.storage(), nodes_to_check_size.storage() + prank, 0); for (UInt i = begin_index; i < begin_index + nodes_to_check_size(prank); ++i) { UInt node = nodes_to_check(i - begin_index); nodes_to_check_global(i) = mesh.getNodeGlobalId(node); } comm.allGatherV(nodes_to_check_global.storage(), nodes_to_check_size.storage()); if (nodes_to_check_global_size != nb_nodes_to_check_serial) { if (prank == 0) { std::cout << "Error: number of nodes to check is wrong in parallel" << std::endl; std::cout << "Serial: " << nb_nodes_to_check_serial << " Parallel: " << nodes_to_check_global_size << std::endl; for (UInt n = 0; n < nodes_to_check_serial.getSize(); ++n) { if (std::find(nodes_to_check_global.begin(), nodes_to_check_global.end(), nodes_to_check_serial(n)) == nodes_to_check_global.end()) { std::cout << "Node number " << nodes_to_check_serial(n) << " not found in parallel" << std::endl; } } } finalize(); return EXIT_FAILURE; } /// rotate mesh Real angle = 1.; Matrix rotation(spatial_dimension, spatial_dimension); rotation.clear(); rotation(0, 0) = std::cos(angle); rotation(0, 1) = std::sin(angle) * -1.; rotation(1, 0) = std::sin(angle); rotation(1, 1) = std::cos(angle); rotation(2, 2) = 1.; Vector increment_tmp(spatial_dimension); for (UInt dim = 0; dim < spatial_dimension; ++dim) { increment_tmp(dim) = (dim + 1) * increment_constant; } Vector increment(spatial_dimension); increment.mul(rotation, increment_tmp); Array & position = mesh.getNodes(); Array position_tmp(position); Array::iterator > position_it = position.begin(spatial_dimension); Array::iterator > position_end = position.end(spatial_dimension); Array::iterator > position_tmp_it = position_tmp.begin(spatial_dimension); for (; position_it != position_end; ++position_it, ++position_tmp_it) position_it->mul(rotation, *position_tmp_it); model.dump(); dumper.dump(); updateDisplacement(model, elements, increment); Real theoretical_Ed = 0; Vector opening(spatial_dimension); Vector traction(spatial_dimension); Vector opening_old(spatial_dimension); Vector traction_old(spatial_dimension); opening.clear(); traction.clear(); opening_old.clear(); traction_old.clear(); Vector Dt(spatial_dimension); Vector Do(spatial_dimension); const Array & residual = model.getResidual(); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { model.updateResidual(); opening += increment_tmp; if (checkTractions(model, opening, traction, rotation) || checkEquilibrium(mesh, residual) || checkResidual(residual, traction, nodes_to_check, rotation)) { finalize(); return EXIT_FAILURE; } /// compute energy Do = opening; Do -= opening_old; Dt = traction_old; Dt += traction; theoretical_Ed += .5 * Do.dot(Dt); opening_old = opening; traction_old = traction; updateDisplacement(model, elements, increment); if(s % 10 == 0) { if (prank == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; model.dump(); dumper.dump(); } } model.dump(); dumper.dump(); Real Ed = model.getEnergy("dissipated"); theoretical_Ed *= 4.; if (prank == 0) std::cout << "Dissipated energy: " << Ed << ", theoretical value: " << theoretical_Ed << std::endl; if (!Math::are_float_equal(Ed, theoretical_Ed) || std::isnan(Ed)) { if (prank == 0) std::cout << "Error: the dissipated energy is incorrect" << std::endl; finalize(); return EXIT_FAILURE; } finalize(); if(prank == 0) std::cout << "OK: Test passed!" << std::endl; return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ void updateDisplacement(SolidMechanicsModelCohesive & model, const ByElementTypeUInt & elements, Vector & increment) { UInt spatial_dimension = model.getSpatialDimension(); Mesh & mesh = model.getFEM().getMesh(); UInt nb_nodes = mesh.getNbNodes(); Array & displacement = model.getDisplacement(); Array update(nb_nodes); update.clear(); 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 = mesh.lastType(spatial_dimension, ghost_type); for (; it != last; ++it) { ElementType type = *it; const Array & elem = elements(type, ghost_type); const Array & connectivity = mesh.getConnectivity(type, ghost_type); UInt nb_nodes_per_element = connectivity.getNbComponent(); for (UInt el = 0; el < elem.getSize(); ++el) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity(elem(el), n); if (!update(node)) { Vector node_disp(displacement.storage() + node * spatial_dimension, spatial_dimension); node_disp += increment; update(node) = true; } } } } } } /* -------------------------------------------------------------------------- */ bool checkTractions(SolidMechanicsModelCohesive & model, Vector & opening, Vector & theoretical_traction, Matrix & rotation) { UInt spatial_dimension = model.getSpatialDimension(); const Mesh & mesh = model.getMesh(); const MaterialCohesive & mat_cohesive = dynamic_cast < const MaterialCohesive & > (model.getMaterial(1)); const Real sigma_c = mat_cohesive.getParam< RandomInternalField >("sigma_c"); const Real beta = mat_cohesive.getParam("beta"); // const Real G_cI = mat_cohesive.getParam("G_cI"); // Real G_cII = mat_cohesive.getParam("G_cII"); const Real delta_0 = mat_cohesive.getParam("delta_0"); const Real kappa = mat_cohesive.getParam("kappa"); Real delta_c = delta_0 * sigma_c / (sigma_c - 1.); Vector normal_opening(spatial_dimension); normal_opening.clear(); normal_opening(0) = opening(0); Real normal_opening_norm = normal_opening.norm(); Vector tangential_opening(spatial_dimension); tangential_opening.clear(); for (UInt dim = 1; dim < spatial_dimension; ++dim) tangential_opening(dim) = opening(dim); Real tangential_opening_norm = tangential_opening.norm(); Real beta2_kappa2 = beta * beta/kappa/kappa; Real beta2_kappa = beta * beta/kappa; Real delta = std::sqrt(tangential_opening_norm * tangential_opening_norm * beta2_kappa2 + normal_opening_norm * normal_opening_norm); delta = std::max(delta, delta_0); Real theoretical_damage = std::min(delta / delta_c, 1.); if (Math::are_float_equal(theoretical_damage, 1.)) theoretical_traction.clear(); else { theoretical_traction = tangential_opening; theoretical_traction *= beta2_kappa; theoretical_traction += normal_opening; theoretical_traction *= sigma_c / delta * (1. - theoretical_damage); } Vector theoretical_traction_rotated(spatial_dimension); theoretical_traction_rotated.mul(rotation, theoretical_traction); 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, _ek_cohesive); Mesh::type_iterator last = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); for (; it != last; ++it) { ElementType type = *it; const Array & traction = mat_cohesive.getTraction(type, ghost_type); const Array & damage = mat_cohesive.getDamage(type, ghost_type); UInt nb_quad_per_el = model.getFEM("CohesiveFEM").getNbQuadraturePoints(type); UInt nb_element = model.getMesh().getNbElement(type, ghost_type); UInt tot_nb_quad = nb_element * nb_quad_per_el; for (UInt q = 0; q < tot_nb_quad; ++q) { for (UInt dim = 0; dim < spatial_dimension; ++dim) { if (!Math::are_float_equal(theoretical_traction_rotated(dim), traction(q, dim))) { std::cout << "Error: tractions are incorrect" << std::endl; return 1; } } if (ghost_type == _not_ghost) if (!Math::are_float_equal(theoretical_damage, damage(q))) { std::cout << "Error: damage is incorrect" << std::endl; return 1; } } } } return 0; } /* -------------------------------------------------------------------------- */ void findNodesToCheck(const Mesh & mesh, const ByElementTypeUInt & elements, Array & nodes_to_check, Int psize) { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int prank = comm.whoAmI(); nodes_to_check.resize(0); Array global_nodes_to_check; UInt spatial_dimension = mesh.getSpatialDimension(); const Array & position = mesh.getNodes(); UInt nb_nodes = position.getSize(); Array checked_nodes(nb_nodes); checked_nodes.clear(); Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator last = mesh.lastType(spatial_dimension); for (; it != last; ++it) { ElementType type = *it; const Array & elem = elements(type); const Array & connectivity = mesh.getConnectivity(type); UInt nb_nodes_per_elem = connectivity.getNbComponent(); for (UInt el = 0; el < elem.getSize(); ++el) { UInt element = elem(el); Vector conn_el(connectivity.storage() + nb_nodes_per_elem * element, nb_nodes_per_elem); for (UInt n = 0; n < nb_nodes_per_elem; ++n) { UInt node = conn_el(n); if (Math::are_float_equal(position(node, 0), 0.) && !checked_nodes(node)) { checked_nodes(node) = true; nodes_to_check.push_back(node); global_nodes_to_check.push_back(mesh.getNodeGlobalId(node)); } } } } std::vector requests; for (Int p = prank + 1; p < psize; ++p) { requests.push_back(comm.asyncSend(global_nodes_to_check.storage(), global_nodes_to_check.getSize(), p, prank)); } Array recv_nodes; for (Int p = 0; p < prank; ++p) { CommunicationStatus status; comm.probe(p, p, status); UInt recv_nodes_size = recv_nodes.getSize(); recv_nodes.resize(recv_nodes_size + status.getSize()); comm.receive(recv_nodes.storage() + recv_nodes_size, status.getSize(), p, p); } comm.waitAll(requests); comm.freeCommunicationRequest(requests); for (UInt i = 0; i < recv_nodes.getSize(); ++i) { Array::iterator node_position = std::find(global_nodes_to_check.begin(), global_nodes_to_check.end(), recv_nodes(i)); if (node_position != global_nodes_to_check.end()) { UInt index = node_position - global_nodes_to_check.begin(); nodes_to_check.erase(index); global_nodes_to_check.erase(index); } } } /* -------------------------------------------------------------------------- */ bool checkEquilibrium(const Mesh & mesh, const Array & residual) { UInt spatial_dimension = residual.getNbComponent(); Vector residual_sum(spatial_dimension); residual_sum.clear(); Array::const_iterator > res_it = residual.begin(spatial_dimension); for (UInt n = 0; n < residual.getSize(); ++n, ++res_it) { if (mesh.isLocalOrMasterNode(n)) residual_sum += *res_it; } StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); comm.allReduce(residual_sum.storage(), spatial_dimension, _so_sum); for (UInt s = 0; s < spatial_dimension; ++s) { if (!Math::are_float_equal(residual_sum(s), 0.)) { if (comm.whoAmI() == 0) std::cout << "Error: system is not in equilibrium!" << std::endl; return 1; } } return 0; } /* -------------------------------------------------------------------------- */ bool checkResidual(const Array & residual, const Vector & traction, const Array & nodes_to_check, const Matrix & rotation) { UInt spatial_dimension = residual.getNbComponent(); Vector total_force(spatial_dimension); total_force.clear(); for (UInt n = 0; n < nodes_to_check.getSize(); ++n) { UInt node = nodes_to_check(n); Vector res(residual.storage() + node * spatial_dimension, spatial_dimension); total_force += res; } StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); comm.allReduce(total_force.storage(), spatial_dimension, _so_sum); Vector theoretical_total_force(spatial_dimension); theoretical_total_force.mul(rotation, traction); theoretical_total_force *= -1 * 2 * 2; for (UInt s = 0; s < spatial_dimension; ++s) { if (!Math::are_float_equal(total_force(s), theoretical_total_force(s))) { if (comm.whoAmI() == 0) std::cout << "Error: total force isn't correct!" << std::endl; return 1; } } return 0; } /* -------------------------------------------------------------------------- */ void findElementsToDisplace(const Mesh & mesh, ByElementTypeUInt & elements) { UInt spatial_dimension = mesh.getSpatialDimension(); mesh.initByElementTypeArray(elements, 1, spatial_dimension); Vector bary(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 = mesh.lastType(spatial_dimension, ghost_type); for (; it != last; ++it) { ElementType type = *it; Array & elem = elements(type, ghost_type); UInt nb_element = mesh.getNbElement(type, ghost_type); for (UInt el = 0; el < nb_element; ++el) { mesh.getBarycenter(el, type, bary.storage(), ghost_type); if (bary(0) > 0.0001) elem.push_back(el); } } } } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_interpolate_stress.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_interpolate_stress.cc index db2d13ce2..fccd6e1b7 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_interpolate_stress.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_interpolate_stress.cc @@ -1,188 +1,182 @@ /** * @file test_interpolate_stress.cc * * @author Marco Vocialta * * @date Thu Jun 07 10:10:01 2012 * * @brief Test for the stress interpolation function * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model.hh" -#include "material.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; Real function(Real x, Real y, Real z) { return 100. + 2. * x + 3. * y + 4 * z; } int main(int argc, char *argv[]) { - initialize(argc, argv); + initialize("../material.dat", argc, argv); debug::setDebugLevel(dblWarning); const UInt spatial_dimension = 3; const ElementType type = _tetrahedron_10; Mesh mesh(spatial_dimension); mesh.read("interpolation.msh"); const ElementType type_facet = mesh.getFacetType(type); Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); MeshUtils::buildAllFacets(mesh, mesh_facets); SolidMechanicsModel model(mesh); /// model initialization - model.initFull("../material.dat"); + model.initFull(); Array & position = mesh.getNodes(); UInt nb_facet = mesh_facets.getNbElement(type_facet); UInt nb_element = mesh.getNbElement(type); /// compute quadrature points positions on facets typedef FEMTemplate MyFEMType; model.registerFEMObject("FacetsFEM", mesh_facets, spatial_dimension-1); model.getFEM("FacetsFEM").initShapeFunctions(); UInt nb_quad_per_facet = model.getFEM("FacetsFEM").getNbQuadraturePoints(type_facet); UInt nb_tot_quad = nb_quad_per_facet * nb_facet; Array quad_facets(nb_tot_quad, spatial_dimension); model.getFEM("FacetsFEM").interpolateOnQuadraturePoints(position, quad_facets, spatial_dimension, type_facet); Array & facet_to_element = mesh_facets.getSubelementToElement(type); UInt nb_facet_per_elem = facet_to_element.getNbComponent(); ByElementTypeReal element_quad_facet; element_quad_facet.alloc(nb_element * nb_facet_per_elem * nb_quad_per_facet, spatial_dimension, type); ByElementTypeReal interpolated_stress("interpolated_stress", ""); mesh.initByElementTypeArray(interpolated_stress, spatial_dimension * spatial_dimension, spatial_dimension); Array & interp_stress = interpolated_stress(type); interp_stress.resize(nb_element * nb_facet_per_elem * nb_quad_per_facet); Array & el_q_facet = element_quad_facet(type); for (UInt el = 0; el < nb_element; ++el) { for (UInt f = 0; f < nb_facet_per_elem; ++f) { UInt global_facet = facet_to_element(el, f).element; for (UInt q = 0; q < nb_quad_per_facet; ++q) { for (UInt s = 0; s < spatial_dimension; ++s) { el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, s) = quad_facets(global_facet * nb_quad_per_facet + q, s); } } } } /// compute quadrature points position of the elements UInt nb_quad_per_element = model.getFEM().getNbQuadraturePoints(type); UInt nb_tot_quad_el = nb_quad_per_element * nb_element; Array quad_elements(nb_tot_quad_el, spatial_dimension); model.getFEM().interpolateOnQuadraturePoints(position, quad_elements, spatial_dimension, type); /// assign some values to stresses Array & stress = const_cast&>(model.getMaterial(0).getStress(type)); for (UInt q = 0; q < nb_tot_quad_el; ++q) { for (UInt s = 0; s < spatial_dimension * spatial_dimension; ++s) { stress(q, s) = s * function(quad_elements(q, 0), quad_elements(q, 1), quad_elements(q, 2)); } } /// interpolate stresses on facets' quadrature points model.getMaterial(0).initElementalFieldInterpolation(element_quad_facet); model.getMaterial(0).interpolateStress(interpolated_stress); Real tolerance = 1.e-10; /// check results for (UInt el = 0; el < nb_element; ++el) { for (UInt f = 0; f < nb_facet_per_elem; ++f) { for (UInt q = 0; q < nb_quad_per_facet; ++q) { for (UInt s = 0; s < spatial_dimension * spatial_dimension; ++s) { Real x = el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, 0); Real y = el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, 1); Real z = el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, 2); Real theoretical = s * function(x, y, z); Real numerical = interp_stress(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, s); if (std::abs(theoretical - numerical) > tolerance) { std::cout << "Theoretical and numerical values aren't coincident!" << std::endl; return EXIT_FAILURE; } } } } } std::cout << "OK: Stress interpolation test passed." << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc index 80d55dcfc..2c73e41f6 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,93 +1,87 @@ /** * @file test_local_material.cc * * @author Guillaume Anciaux * @author Marion Estelle Chambart * * @date Fri Nov 26 00:17:56 2010 * * @brief test of the class SolidMechanicsModel * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -#include "fem.hh" #include "local_material_damage.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); UInt max_steps = 200; Real epot, ekin; const UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); - MeshIOMSH mesh_io; - mesh_io.read("barre_trou.msh", mesh); + mesh.read("barre_trou.msh"); mesh.createGroupsFromMeshData("physical_names"); SolidMechanicsModel model(mesh); /// model initialization - model.initFull("material.dat", SolidMechanicsModelOptions(_explicit_lumped_mass, true)); + model.initFull(SolidMechanicsModelOptions(_explicit_lumped_mass, true)); model.registerNewCustomMaterials("local_damage"); model.initMaterials(); Real time_step = model.getStableTimeStep(); model.setTimeStep(time_step/10.); model.assembleMassLumped(); std::cout << model << std::endl; /// Dirichlet boundary conditions model.applyBC(BC::Dirichlet::FixedValue(0.0, BC::_x), "Fixed"); model.applyBC(BC::Dirichlet::FixedValue(0.0, BC::_y), "Fixed"); // Boundary condition (Neumann) Matrix stress(2,2); stress.eye(3e6); model.applyBC(BC::Neumann::FromHigherDim(stress), "Traction"); for(UInt s = 0; s < max_steps; ++s) { model.solveStep(); epot = model.getPotentialEnergy(); ekin = model.getKineticEnergy(); std::cout << s << " " << epot << " " << ekin << " " << epot + ekin << std::endl; } akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_damage_non_local.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_damage_non_local.cc index 4eef3fac8..fded95dff 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_damage_non_local.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_non_local/test_material_damage_non_local.cc @@ -1,104 +1,95 @@ /** * @file test_material_damage_non_local.cc * * @author Nicolas Richart * * @date Tue Sep 13 13:51:05 2011 * * @brief test for non-local damage materials * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -#include "fem.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { debug::setDebugLevel(dblWarning); - akantu::initialize(argc, argv); + akantu::initialize("material_damage_non_local.dat", argc, argv); UInt max_steps = 40000; const UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); - MeshIOMSH mesh_io; - - mesh_io.read("mesh.msh", mesh); + mesh.read("mesh.msh"); mesh.createGroupsFromMeshData("physical_names"); SolidMechanicsModel model(mesh); /// model initialization - model.initFull("material_damage_non_local.dat"); + model.initFull(); Real time_step = model.getStableTimeStep(); model.setTimeStep(time_step/10.); - model.assembleMassLumped(); - std::cout << model << std::endl; model.applyBC(BC::Dirichlet::FixedValue(0.0), "Fixed"); // Boundary condition (Neumann) Matrix stress(2,2); stress.eye(3e6); model.applyBC(BC::Neumann::FromHigherDim(stress), "Traction"); model.setBaseName("damage_non_local"); model.addDumpField("displacement"); model.addDumpField("mass" ); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); model.addDumpField("damage" ); model.addDumpField("stress" ); model.addDumpField("strain" ); model.dump(); for(UInt s = 0; s < max_steps; ++s) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); if(s % 100 == 0) std::cout << "Step " << s+1 << "/" << max_steps < * * @date Wed Sep 22 13:39:02 2010 * * @brief test of the class SolidMechanicsModel * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -#include "fem.hh" + /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { debug::setDebugLevel(dblWarning); - initialize(argc, argv); + initialize("material_thermal.dat", argc, argv); Math::setTolerance(1.e-13); Mesh mesh(2); - MeshIOMSH mesh_io; - mesh_io.read("square.msh", mesh); + mesh.read("square.msh"); SolidMechanicsModel model(mesh); - model.initFull("material_thermal.dat", SolidMechanicsModelOptions(_static)); + model.initFull(SolidMechanicsModelOptions(_static)); mesh.computeBoundingBox(); Real xmin = mesh.getXMin(); Real xmax = mesh.getXMax(); Real ymin = mesh.getYMin(); Real ymax = mesh.getYMax(); Array & pos = mesh.getNodes(); Array & boundary = model.getBoundary(); Array & disp = model.getDisplacement(); for (UInt i = 0; i < mesh.getNbNodes(); ++i) { if (Math::are_float_equal(pos(i, 0), xmin)) { boundary(i, 0) = true; } if (Math::are_float_equal(pos(i, 1), ymin)) { boundary(i, 1) = true; } } model.setBaseName("test_material_thermal"); model.addDumpField("displacement"); model.addDumpField("strain"); model.addDumpField("stress"); model.addDumpField("delta_T"); model.assembleStiffnessMatrix(); model.updateResidual(); model.solveStatic(); model.updateResidual(); for (UInt i = 0; i < mesh.getNbNodes(); ++i) { if (Math::are_float_equal(pos(i, 0), xmax) && Math::are_float_equal(pos(i, 1), ymax)) { if (!Math::are_float_equal(disp(i, 0), 1.0) || !Math::are_float_equal(disp(i, 1), 1.0)) { AKANTU_DEBUG_ERROR("Test not passed"); return EXIT_FAILURE; } } } model.dump(); finalize(); std::cout << "Test passed" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation.cc index 46b0fb25b..87f690e2e 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation.cc @@ -1,170 +1,165 @@ /** * @file test_material_standard_linear_solid_deviatoric_relaxation.cc * * @author David Simon Kammer * @author Nicolas Richart * @author Vladislav Yastrebov * * @date Wed May 23 17:42:48 2012 * * @brief test of the viscoelastic material: relaxation * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" using namespace akantu; int main(int argc, char *argv[]) { - akantu::initialize(argc, argv); + akantu::initialize("material_standard_linear_solid_deviatoric_relaxation.dat", argc, argv); akantu::debug::setDebugLevel(akantu::dblWarning); // sim data Real T = 10.; Real eps = 0.001; const UInt dim = 2; Real sim_time = 25.; Real time_factor = 0.1; Real tolerance = 1e-7; Mesh mesh(dim); - MeshIOMSH mesh_io; - mesh_io.read("test_material_standard_linear_solid_deviatoric_relaxation.msh",mesh); + mesh.read("test_material_standard_linear_solid_deviatoric_relaxation.msh"); + const ElementType element_type = _quadrangle_4; SolidMechanicsModel model(mesh); /* ------------------------------------------------------------------------ */ /* Initialization */ /* ------------------------------------------------------------------------ */ - model.initFull("material_standard_linear_solid_deviatoric_relaxation.dat"); + model.initFull(); std::cout << model.getMaterial(0) << std::endl; model.assembleMassLumped(); std::stringstream filename_sstr; filename_sstr << "test_material_standard_linear_solid_deviatoric_relaxation.out"; std::ofstream output_data; output_data.open(filename_sstr.str().c_str()); output_data << "#[1]-time [2]-sigma_analytic [3+]-sigma_measurements" << std::endl; Material & mat = model.getMaterial(0); const Array & stress = mat.getStress(element_type); Real Eta = mat.getParam("Eta"); Real EV = mat.getParam("Ev"); Real Einf = mat.getParam("Einf"); Real nu = mat.getParam("nu"); Real Ginf = Einf/(2*(1+nu)); Real G = EV/(2*(1+nu)); Real G0 = G + Ginf; Real gamma = G/G0; Real tau = Eta / EV; Real gammainf = Ginf/G0; UInt nb_nodes = mesh.getNbNodes(); const Array & coordinate = mesh.getNodes(); Array & displacement = model.getDisplacement(); /// Setting time step Real time_step = model.getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model.setTimeStep(time_step); UInt max_steps = sim_time / time_step; UInt out_interval = 1; Real time = 0.; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 0; s <= max_steps; ++s) { if(s % 1000 == 0) std::cerr << "passing step " << s << "/" << max_steps << std::endl; time = s * time_step; // impose displacement Real epsilon = 0.; if (time < T) { epsilon = eps * time / T; } else { epsilon = eps; } for (UInt n=0; n::const_matrix_iterator stress_it = stress.begin(dim, dim); Array::const_matrix_iterator stress_end = stress.end(dim, dim); for(;stress_it != stress_end; ++stress_it) { output_data << " " << (*stress_it)(0,1) << " " << (*stress_it)(1,0); // test error Real rel_error_1 = std::abs(((*stress_it)(0,1) - solution) / solution); Real rel_error_2 = std::abs(((*stress_it)(1,0) - solution) / solution); if (rel_error_1 > tolerance || rel_error_2 > tolerance) { std::cerr << "Relative error: " << rel_error_1 << " " << rel_error_2 << std::endl; return EXIT_FAILURE; } } output_data << std::endl; } } finalize(); std::cout << "Test successful!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation_tension.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation_tension.cc index b12c49bd2..58dedfc77 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation_tension.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_material_viscoelastic/test_material_standard_linear_solid_deviatoric_relaxation_tension.cc @@ -1,179 +1,172 @@ /** * @file test_material_standard_linear_solid_deviatoric_relaxation_tension.cc * * @author David Simon Kammer * @author Nicolas Richart * * @date Wed May 30 17:16:16 2012 * * @brief test of the viscoelastic material: relaxation * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" using namespace akantu; int main(int argc, char *argv[]) { - akantu::initialize(argc, argv); - akantu::debug::setDebugLevel(akantu::dblWarning); + akantu::initialize("material_standard_linear_solid_deviatoric_relaxation.dat", argc, argv); // sim data Real T = 10.; Real eps = 0.001; // const UInt dim = 3; const UInt dim = 2; Real sim_time = 25.; //Real sim_time = 250.; Real time_factor = 0.1; Real tolerance = 1e-5; Mesh mesh(dim); - MeshIOMSH mesh_io; - mesh_io.read("test_material_standard_linear_solid_deviatoric_relaxation.msh",mesh); + mesh.read("test_material_standard_linear_solid_deviatoric_relaxation.msh"); // mesh_io.read("hexa_structured.msh",mesh); //const ElementType element_type = _hexahedron_8; const ElementType element_type = _quadrangle_4; SolidMechanicsModel model(mesh); /* ------------------------------------------------------------------------ */ /* Initialization */ /* ------------------------------------------------------------------------ */ - model.initFull("material_standard_linear_solid_deviatoric_relaxation.dat"); + model.initFull(); std::cout << model.getMaterial(0) << std::endl; model.assembleMassLumped(); model.updateResidual(); model.getMaterial(0).setToSteadyState(); std::stringstream filename_sstr; filename_sstr << "test_material_standard_linear_solid_deviatoric_relaxation_tension.out"; std::ofstream output_data; output_data.open(filename_sstr.str().c_str()); output_data << "#[1]-time [2]-sigma_analytic [3+]-sigma_measurements" << std::endl; Material & mat = model.getMaterial(0); const Array & stress = mat.getStress(element_type); Real Eta = mat.getParam("Eta"); Real EV = mat.getParam("Ev"); Real Einf = mat.getParam("Einf"); Real E0 = mat.getParam("E"); Real kpa = mat.getParam("kapa"); Real mu = mat.getParam("mu"); Real gamma = EV/E0; Real gammainf = Einf/E0; Real tau = Eta / EV; std::cout << "relaxation time = " << tau << std::endl; UInt nb_nodes = mesh.getNbNodes(); const Array & coordinate = mesh.getNodes(); Array & displacement = model.getDisplacement(); /// Setting time step Real time_step = model.getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model.setTimeStep(time_step); UInt max_steps = sim_time / time_step; UInt out_interval = 1; Real time = 0.; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 0; s <= max_steps; ++s) { if(s % 1000 == 0) std::cerr << "passing step " << s << "/" << max_steps << std::endl; time = s * time_step; // impose displacement Real epsilon = 0.; if (time < T) { epsilon = eps * time / T; } else { epsilon = eps; } for (UInt n=0; n::const_matrix_iterator stress_it = stress.begin(dim, dim); Array::const_matrix_iterator stress_end = stress.end(dim, dim); for(;stress_it != stress_end; ++stress_it) { output_data << " " << (*stress_it)(1,1); // test error Real rel_error_1 = std::abs(((*stress_it)(1,1) - solution) / solution); if (rel_error_1 > tolerance) { std::cerr << "Relative error: " << rel_error_1 << std::endl; return EXIT_FAILURE; } } output_data << std::endl; } } finalize(); std::cout << "Test successful!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.cc index d44cda2ef..46f84e52d 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.cc @@ -1,200 +1,200 @@ /** * @file test_solid_mechanics_model_bar_traction2d.cc * * @author Nicolas Richart * * @date Fri Sep 03 15:56:56 2010 * * @brief test of the class SolidMechanicsModel * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.hh" iohelper::ElemType paraview_type = iohelper::TRIANGLE2; #endif //AKANTU_USE_IOHELPER //#define CHECK_STRESS akantu::ElementType type = akantu::_triangle_6; akantu::SolidMechanicsModel * model; akantu::UInt spatial_dimension = 2; akantu::UInt nb_nodes; akantu::UInt nb_element; akantu::UInt nb_quadrature_points; akantu::Array * stress; akantu::Array * strain; int main(int argc, char *argv[]) { - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); akantu::UInt max_steps = 5000; akantu::Real time_factor = 0.8; // akantu::Real epot, ekin; akantu::Mesh mesh(spatial_dimension); mesh.read("bar2.msh"); akantu::SolidMechanicsModel model(mesh); nb_nodes = mesh.getNbNodes(); nb_element = mesh.getNbElement(type); /// model initialization - model.initFull("material.dat"); + model.initFull(); std::cout << model.getMaterial(0) << std::endl; model.initMaterials(); model.assembleMassLumped(); nb_quadrature_points = model.getFEM().getNbQuadraturePoints(type); stress = new akantu::Array(nb_element * nb_quadrature_points, spatial_dimension* spatial_dimension); strain = new akantu::Array(nb_element * nb_quadrature_points, spatial_dimension * spatial_dimension); /// boundary conditions akantu::Real eps = 1e-16; const akantu::Array & pos = mesh.getNodes(); akantu::Array & disp = model.getDisplacement(); akantu::Array & boun = model.getBoundary(); for (akantu::UInt i = 0; i < nb_nodes; ++i) { if(pos(i, 0) >= 9.) disp(i, 0) = (pos(i, 0) - 9) / 100.; if(pos(i) <= eps) boun(i, 0) = true; if(pos(i, 1) <= eps || pos(i, 1) >= 1 - eps ) boun(i, 1) = true; } /// set the time step akantu::Real time_step = model.getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model.setTimeStep(time_step); /// initialize the paraview output model.updateResidual(); model.setBaseName("bar_traction_2d"); model.addDumpField("displacement"); model.addDumpField("mass" ); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); model.addDumpField("stress" ); model.addDumpField("strain" ); model.dump(); #ifdef CHECK_STRESS std::ofstream outfile; outfile.open("stress"); #endif // CHECK_STRESS std::ofstream energy; energy.open("energy_bar_2d.csv"); energy << "id,rtime,epot,ekin,tot" << std::endl; for(akantu::UInt s = 1; s <= max_steps; ++s) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); akantu::Real epot = model.getPotentialEnergy(); akantu::Real ekin = model.getKineticEnergy(); energy << s << "," << (s-1)*time_step << "," << epot << "," << ekin << "," << epot + ekin << std::endl; #ifdef CHECK_STRESS /// search the position of the maximum of stress to determine the wave speed akantu::Real max_stress = std::numeric_limits::min(); akantu::Real * stress = model.getMaterial(0).getStress(type).storage(); for (akantu::UInt i = 0; i < nb_element; ++i) { if(max_stress < stress[i*spatial_dimension*spatial_dimension]) { max_stress = stress[i*spatial_dimension*spatial_dimension]; } } akantu::Real * coord = model.getFEM().getMesh().getNodes().storage(); akantu::Real * disp_val = model.getDisplacement().storage(); akantu::UInt * conn = model.getFEM().getMesh().getConnectivity(type).storage(); akantu::UInt nb_nodes_per_element = model.getFEM().getMesh().getNbNodesPerElement(type); akantu::Real * coords = new akantu::Real[spatial_dimension]; akantu::Real min_x = std::numeric_limits::max(); akantu::Real max_x = std::numeric_limits::min(); akantu::Real stress_range = 5e7; for (akantu::UInt el = 0; el < nb_element; ++el) { if(stress[el*spatial_dimension*spatial_dimension] > max_stress - stress_range) { akantu::UInt el_offset = el * nb_nodes_per_element; memset(coords, 0, spatial_dimension*sizeof(akantu::Real)); for (akantu::UInt n = 0; n < nb_nodes_per_element; ++n) { for (akantu::UInt i = 0; i < spatial_dimension; ++i) { akantu::UInt node = conn[el_offset + n] * spatial_dimension; coords[i] += (coord[node + i] + disp_val[node + i]) / ((akantu::Real) nb_nodes_per_element); } } min_x = min_x < coords[0] ? min_x : coords[0]; max_x = max_x > coords[0] ? max_x : coords[0]; } } outfile << s << " " << .5 * (min_x + max_x) << " " << min_x << " " << max_x << " " << max_x - min_x << " " << max_stress << std::endl; delete [] coords; #endif // CHECK_STRESS #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) model.dump(); #endif //AKANTU_USE_IOHELPER if(s % 100 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } energy.close(); #ifdef CHECK_STRESS outfile.close(); #endif // CHECK_STRESS akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.cc index 6c673ffe7..46ce6488f 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.cc @@ -1,173 +1,160 @@ /** * @file test_solid_mechanics_model_bar_traction2d_parallel.cc * * @author Nicolas Richart * * @date Sun Sep 12 23:37:43 2010 * * @brief test of the class SolidMechanicsModel * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include "mpi.h" /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -#include "static_communicator.hh" -#include "mesh_partition_scotch.hh" using namespace akantu; -/* -------------------------------------------------------------------------- */ -#ifdef AKANTU_USE_IOHELPER -# include "dumper_iohelper.hh" -#endif //AKANTU_USE_IOHELPER - -int main(int argc, char *argv[]) -{ +int main(int argc, char *argv[]) { akantu::UInt spatial_dimension = 2; akantu::UInt max_steps = 5000; akantu::Real time_factor = 0.8; - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); akantu::Mesh mesh(spatial_dimension); akantu::StaticCommunicator & comm = akantu::StaticCommunicator::getStaticCommunicator(); akantu::Int psize = comm.getNbProc(); akantu::Int prank = comm.whoAmI(); akantu::debug::setDebugLevel(akantu::dblWarning); akantu::MeshPartition * partition = NULL; if(prank == 0) { - akantu::MeshIOMSH mesh_io; - mesh_io.read("bar2.msh", mesh); + mesh.read("bar2.msh"); partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); } /* ------------------------------------------------------------------------ */ /* Initialization */ /* ------------------------------------------------------------------------ */ akantu::SolidMechanicsModel model(mesh); /// model initialization model.initParallel(partition); - model.initFull("material.dat"); + model.initFull(); if(prank == 0) std::cout << model.getMaterial(0) << std::endl; model.assembleMassLumped(); akantu::UInt nb_nodes = mesh.getNbNodes(); /* ------------------------------------------------------------------------ */ /* Boundary + initial conditions */ /* ------------------------------------------------------------------------ */ akantu::Real eps = 1e-16; const akantu::Array & pos = mesh.getNodes(); akantu::Array & disp = model.getDisplacement(); akantu::Array & boun = model.getBoundary(); for (akantu::UInt i = 0; i < nb_nodes; ++i) { if(pos(i, 0) >= 9.) disp(i, 0) = (pos(i, 0) - 9) / 100.; if(pos(i) <= eps) boun(i, 0) = true; if(pos(i, 1) <= eps || pos(i, 1) >= 1 - eps ) boun(i, 1) = true; } model.synchronizeBoundaries(); model.updateResidual(); model.setBaseName("bar2d_parallel"); model.addDumpField("displacement"); model.addDumpField("mass" ); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); model.addDumpField("stress" ); model.addDumpField("strain" ); model.addDumpField("partitions" ); model.dump(); std::ofstream energy; if(prank == 0) { energy.open("energy_bar_2d_para.csv"); energy << "id,rtime,epot,ekin,tot" << std::endl; } double total_time = 0.; /// Setting time step akantu::Real time_step = model.getStableTimeStep() * time_factor; if(prank == 0) std::cout << "Time Step = " << time_step << "s" << std::endl; model.setTimeStep(time_step); /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(akantu::UInt s = 1; s <= max_steps; ++s) { double start = MPI_Wtime(); model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); double end = MPI_Wtime(); akantu::Real epot = model.getPotentialEnergy(); akantu::Real ekin = model.getKineticEnergy(); total_time += end - start; if(prank == 0 && (s % 100 == 0)) { std::cerr << "passing step " << s << "/" << max_steps << std::endl; } energy << s << "," << (s-1)*time_step << "," << epot << "," << ekin << "," << epot + ekin << std::endl; if(s % 100 == 0) { model.dump(); } } if(prank == 0) std::cout << "Time : " << psize << " " << total_time / max_steps << " " << total_time << std::endl; akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured.cc index 14dd77f95..6ba0c8244 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured.cc @@ -1,112 +1,99 @@ /** * @file test_solid_mechanics_model_bar_traction2d_structured.cc * * @author Guillaume Anciaux * @author Nicolas Richart * * @date Mon Dec 13 10:46:04 2010 * * @brief test of the class SolidMechanicsModel * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -/* -------------------------------------------------------------------------- */ -#ifdef AKANTU_USE_IOHELPER -# include "io_helper.hh" -#endif //AKANTU_USE_IOHELPER -int main(int argc, char *argv[]) -{ - akantu::initialize(argc, argv); +int main(int argc, char *argv[]) { + akantu::initialize("material.dat", argc, argv); akantu::UInt spatial_dimension = 2; akantu::UInt max_steps = 10000; akantu::Real time_factor = 0.2; akantu::Real epot, ekin; akantu::Mesh mesh(spatial_dimension); - akantu::MeshIOMSH mesh_io; - - mesh_io.read("bar_structured1.msh", mesh); + mesh.read("bar_structured1.msh"); akantu::SolidMechanicsModel * model = new akantu::SolidMechanicsModel(mesh); /// model initialization - model->initFull("material.dat"); + model->initFull(); std::cout << model->getMaterial(0) << std::endl; - /// boundary conditions akantu::Real eps = 1e-16; for (akantu::UInt i = 0; i < mesh.getNbNodes(); ++i) { if(mesh.getNodes()(i) >= 9) model->getDisplacement()(i) = (model->getFEM().getMesh().getNodes()(i) - 9) / 100. ; if(mesh.getNodes()(i) <= eps) model->getBoundary()(i) = true; if(mesh.getNodes()(i, 1) <= eps || mesh.getNodes()(i, 1) >= 1 - eps ) { model->getBoundary()(i, 1) = true; } } akantu::Real time_step = model->getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); std::ofstream energy; energy.open("energy_bar_2d_structured.csv"); energy << "id,epot,ekin,tot" << std::endl; for(akantu::UInt s = 1; s <= max_steps; ++s) { model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); epot = model->getPotentialEnergy(); ekin = model->getKineticEnergy(); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; } energy.close(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured_pbc.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured_pbc.cc index 5db818aa5..27c54c968 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured_pbc.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured_pbc.cc @@ -1,131 +1,125 @@ /** * @file test_solid_mechanics_model_bar_traction2d_structured_pbc.cc * * @author David Simon Kammer * * @date Thu Dec 22 18:49:38 2011 * * @brief test of pbc class for SolidMechanicsModel * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::debug::setDebugLevel(akantu::dblWarning); - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); akantu::UInt spatial_dimension = 2; akantu::UInt max_steps = 1000; akantu::Real time_factor = 0.2; akantu::Real epot, ekin; akantu::Mesh mesh(spatial_dimension); - akantu::MeshIOMSH mesh_io; - - mesh_io.read("bar_structured1.msh", mesh); + mesh.read("bar_structured1.msh"); akantu::SolidMechanicsModel model(mesh); /// model initialization - model.initFull("material.dat"); + model.initFull(); std::cout << model.getMaterial(0) << std::endl; model.setPBC(1,0,0); model.initPBC(); model.assembleMassLumped(); model.setBaseName("bar2d_structured_pbc"); model.addDumpField("displacement"); model.addDumpField("mass" ); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); model.addDumpField("stress" ); model.addDumpField("strain" ); model.dump(); akantu::UInt nb_nodes = mesh.getNbNodes(); /// boundary conditions mesh.computeBoundingBox(); akantu::Real eps = 1e-16; akantu::Real signal_start = 0.6*mesh.getXMax(); akantu::Real signal_end = 0.7*mesh.getXMax(); akantu::Real delta_d = signal_end - signal_start; akantu::Real signal = 1.; const akantu::Array & coords = model.getFEM().getMesh().getNodes(); akantu::Array & disp = model.getDisplacement(); for (akantu::UInt i = 0; i < nb_nodes; ++i) { if(coords(i,0) >= signal_start && coords(i,0) <= signal_end) { if (coords(i,0) <= 0.5 * (signal_start + signal_end)) disp(i,0) = (coords(i,0) - signal_start) * 2 * signal / delta_d; else disp(i,0) = (signal_end - coords(i,0)) * 2 * signal / delta_d; } if(coords(i,1) <= eps || coords(i,1) >= 1 - eps ) { model.getBoundary().storage()[spatial_dimension*i + 1] = true; } } akantu::Real time_step = model.getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model.setTimeStep(time_step); std::ofstream energy; energy.open("energy_2d_pbc.csv"); energy << "id,epot,ekin,tot" << std::endl; for(akantu::UInt s = 1; s <= max_steps; ++s) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); epot = model.getPotentialEnergy(); ekin = model.getKineticEnergy(); if(s % 20 == 0) model.dump(); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; } energy.close(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_boundary_condition.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_boundary_condition.cc index 5b0236dd6..d779a6f89 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_boundary_condition.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_boundary_condition.cc @@ -1,59 +1,59 @@ #include #include #include "aka_common.hh" #include "aka_error.hh" #include "mesh.hh" #include "solid_mechanics_model.hh" #include "boundary_condition_functor.hh" using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char* argv[]) { UInt spatial_dimension(3); - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); Mesh mesh(spatial_dimension, "mesh_names"); std::cout << "Loading the mesh." << std::endl; mesh.read("./cube_physical_names.msh"); mesh.createGroupsFromMeshData("physical_names"); std::stringstream sstr; SolidMechanicsModel model(mesh); - model.initFull("material.dat"); + model.initFull(); std::cout << model.getMaterial(0) << std::endl; Vector surface_traction(3); surface_traction(0)=0.0; surface_traction(1)=0.0; surface_traction(2)=-1.0; Matrix surface_stress(3, 3, 0.0); surface_stress(0,0)=0.0; surface_stress(1,1)=0.0; surface_stress(2,2)=-1.0; model.applyBC(BC::Dirichlet::FixedValue(13.0, BC::_x), "Bottom"); model.applyBC(BC::Dirichlet::FixedValue(13.0, BC::_y), "Bottom"); model.applyBC(BC::Dirichlet::FixedValue(13.0, BC::_z), "Bottom"); //model.applyBC(BC::Neumann::FromSameDim(surface_traction), "Top"); model.applyBC(BC::Neumann::FromHigherDim(surface_stress), "Top"); debug::setDebugLevel(dblTest); std::cout << model.getDisplacement(); std::cout << model.getForce(); debug::setDebugLevel(dblInfo); akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_circle_2.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_circle_2.cc index b65c80f7e..00e833212 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_circle_2.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_circle_2.cc @@ -1,102 +1,97 @@ /** * @file test_solid_mechanics_model_circle_2.cc * * @author Nicolas Richart * * @date Tue Oct 26 10:08:10 2010 * * @brief test of the class SolidMechanicsModel * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -#include "fem.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); UInt max_steps = 10000; - Real epot, ekin; + Real epot, ekin, wext = 0; Mesh mesh(2); - MeshIOMSH mesh_io; - mesh_io.read("circle2.msh", mesh); + mesh.read("circle2.msh"); mesh.createBoundaryGroupFromGeometry(); SolidMechanicsModel model(mesh); /// model initialization - model.initFull("material.dat"); + model.initFull(); Real time_step = model.getStableTimeStep() / 10.; model.setTimeStep(time_step); std::cout << "-- Time step : " << time_step << " --" << std::endl; model.assembleMassLumped(); // Boundary condition (Neumann) Matrix stress(2,2); stress.eye(1e3); model.applyBC(BC::Neumann::FromHigherDim(stress), "boundary_0"); model.setBaseName("circle2"); model.addDumpFieldVector("displacement"); model.addDumpFieldVector("force" ); model.addDumpFieldVector("residual" ); model.addDumpField("mass" ); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("stress" ); model.addDumpField("strain" ); model.dump(); for(UInt s = 0; s < max_steps; ++s) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); - epot = model.getPotentialEnergy(); - ekin = model.getKineticEnergy(); + epot = model.getEnergy("potential"); + ekin = model.getEnergy("kinetic"); + wext += model.getEnergy("external work"); - std::cout << s << " " << epot << " " << ekin << " " << epot + ekin + std::cout << s << "," << epot << "," << ekin << "," << wext << "," << epot + ekin - wext << std::endl; if(s % 100 == 0) model.dump(); } 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 693f3bdc6..ba60ea59f 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,113 +1,109 @@ /** * @file test_solid_mechanics_model_cube3d.cc * * @author Guillaume Anciaux * * @date Fri Sep 03 15:56:56 2010 * * @brief test of the class SolidMechanicsModel on the 3d cube * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" + /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); akantu::UInt max_steps = 10000; akantu::Real epot, ekin; akantu::Mesh mesh(3); - akantu::MeshIOMSH mesh_io; - mesh_io.read("cube1.msh", mesh); + mesh.read("cube1.msh"); akantu::SolidMechanicsModel model(mesh); - model.initFull("material.dat"); + model.initFull(); akantu::Real time_step = model.getStableTimeStep(); 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.getFEM().getMesh().getNodes().storage()[3*i] / 100.; if(model.getFEM().getMesh().getNodes().storage()[3*i] <= eps) { model.getBoundary().storage()[3*i ] = true; } if(model.getFEM().getMesh().getNodes().storage()[3*i + 1] <= eps) { model.getBoundary().storage()[3*i + 1] = true; } } model.setBaseName("cube3d"); model.addDumpField("displacement"); model.addDumpField("mass" ); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); 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) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); epot = model.getPotentialEnergy(); ekin = model.getKineticEnergy(); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; 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_pbc.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_pbc.cc index d730bbd29..d8f9a98bb 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_pbc.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_pbc.cc @@ -1,114 +1,110 @@ /** * @file test_solid_mechanics_model_cube3d_pbc.cc * * @author Guillaume Anciaux * * @date Fri May 18 14:06:13 2012 * * @brief test of the class SolidMechanicsModel on the 3d cube * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" + /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); akantu::UInt max_steps = 10000; akantu::Real epot, ekin; akantu::Mesh mesh(3); - akantu::MeshIOMSH mesh_io; - mesh_io.read("cube_structured.msh", mesh); + mesh.read("cube_structured.msh"); akantu::SolidMechanicsModel model(mesh); model.setPBC(1,1,1); - model.initFull("material.dat"); + model.initFull(); akantu::Real time_step = model.getStableTimeStep(); model.setTimeStep(time_step/10.); model.assembleMassLumped(); std::cout << model << std::endl; /// boundary conditions akantu::UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); akantu::Real eps = 1e-16; for (akantu::UInt i = 0; i < nb_nodes; ++i) { model.getDisplacement().storage()[3*i] = model.getFEM().getMesh().getNodes().storage()[3*i] / 100.; if(model.getFEM().getMesh().getNodes().storage()[3*i] <= eps) { model.getBoundary().storage()[3*i ] = true; } if(model.getFEM().getMesh().getNodes().storage()[3*i + 1] <= eps) { model.getBoundary().storage()[3*i + 1] = true; } } model.setBaseName("cube3d_pbc"); model.addDumpField("displacement"); model.addDumpField("mass" ); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); 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) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); epot = model.getPotentialEnergy(); ekin = model.getKineticEnergy(); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; 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 1cc0c2dff..d074a76cf 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,115 +1,112 @@ /** * @file test_solid_mechanics_model_cube3d_tetra10.cc * * @author Guillaume Anciaux * @author Peter Spijker * * @date Mon Dec 06 14:43:53 2010 * * @brief test of the class SolidMechanicsModel on the 3d cube * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" + /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); akantu::UInt max_steps = 1000; akantu::Real epot, ekin; akantu::Mesh mesh(3); - akantu::MeshIOMSH mesh_io; - mesh_io.read("cube2.msh", mesh); + + mesh.read("cube2.msh"); akantu::SolidMechanicsModel model(mesh); /// model initialization - model.initFull("material.dat"); + model.initFull(); akantu::Real time_step = model.getStableTimeStep(); model.setTimeStep(time_step/10.); model.assembleMassLumped(); std::cout << model << std::endl; /// boundary conditions akantu::Real eps = 1e-2; akantu::UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); for (akantu::UInt i = 0; i < nb_nodes; ++i) { model.getDisplacement().storage()[3*i] = model.getFEM().getMesh().getNodes().storage()[3*i] / 100.; if(model.getFEM().getMesh().getNodes().storage()[3*i] <= eps) { model.getBoundary().storage()[3*i ] = true; } if(model.getFEM().getMesh().getNodes().storage()[3*i + 1] <= eps) { model.getBoundary().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("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); 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) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); epot = model.getPotentialEnergy(); ekin = model.getKineticEnergy(); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; 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_implicit_1d.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_1d.cc index efe049c05..261680689 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_1d.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_1d.cc @@ -1,83 +1,79 @@ /** * @file test_solid_mechanics_model_implicit_1d.cc * * @author Nicolas Richart * * @date Thu Mar 03 16:09:49 2011 * * @brief test of traction in implicit * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" + /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { - initialize(argc, argv); + initialize("material.dat", argc, argv); UInt spatial_dimension = 1; Mesh mesh(spatial_dimension); - MeshIOMSH mesh_io; - mesh_io.read("segment1.msh", mesh); + mesh.read("segment1.msh"); SolidMechanicsModel model(mesh); - model.initFull("material.dat", SolidMechanicsModelOptions(_static)); + model.initFull( SolidMechanicsModelOptions(_static)); std::cout << model.getMaterial(0) << std::endl; /// boundary conditions model.getBoundary()(0,0) = true; model.getForce()(1,0) = 1000; model.setBaseName("implicit_1d"); model.addDumpField("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); model.addDumpField("stress" ); model.addDumpField("strain" ); debug::setDebugLevel(dblInfo); model.dump(); model.solveStep<_scm_newton_raphson_tangent_modified, _scc_residual>(1e-1, 10); model.dump(); finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_2d.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_2d.cc index 59b3f7986..68e8a0980 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_2d.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_2d.cc @@ -1,123 +1,109 @@ /** * @file test_solid_mechanics_model_implicit_2d.cc * * @author Nicolas Richart * * @date Thu Mar 03 16:09:49 2011 * * @brief test of traction in implicit * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -#include "static_communicator.hh" -#include "mesh_partition_scotch.hh" - -/* -------------------------------------------------------------------------- */ - -#ifdef AKANTU_USE_SCOTCH -#include "mesh_partition_scotch.hh" -#endif #define bar_length 1 #define bar_height 1 using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { debug::setDebugLevel(dblWarning); - initialize(argc, argv); + initialize("material.dat", argc, argv); UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); MeshPartition * partition = NULL; if(prank == 0) { - MeshIOMSH mesh_io; - mesh_io.read("square_implicit2.msh", mesh); - + mesh.read("square_implicit2.msh"); partition = new MeshPartitionScotch(mesh, spatial_dimension); // partition->reorder(); partition->partitionate(psize); } SolidMechanicsModel model(mesh); /// model initialization model.initParallel(partition); delete partition; - model.initFull("material.dat", SolidMechanicsModelOptions(_static)); + model.initFull(SolidMechanicsModelOptions(_static)); if (prank == 0) std::cout << model.getMaterial("steel") << std::endl; /// boundary conditions const Array & position = mesh.getNodes(); Array & boundary = model.getBoundary(); Array & displacment = model.getDisplacement(); UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); for (UInt n = 0; n < nb_nodes; ++n) { if(position(n,0) < Math::getTolerance()) boundary(n,0) = true; if(position(n,1) < Math::getTolerance()) boundary(n,1) = true; if(std::abs(position(n,0) - bar_length) < Math::getTolerance()) { boundary(n,0) = true; displacment(n,0) = 0.1; } } model.setBaseName("implicit_2d"); model.addDumpField("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); model.addDumpField("stress" ); model.addDumpField("strain" ); model.updateResidual(); model.dump(); model.solveStep<_scm_newton_raphson_tangent_modified, _scc_increment>(1e-3, 100); model.dump(); finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_dynamic_2d.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_dynamic_2d.cc index e3d4ed610..fd6525e8e 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_dynamic_2d.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_dynamic_2d.cc @@ -1,222 +1,210 @@ /** * @file test_solid_mechanics_model_implicit_dynamic_2d.cc * * @author Nicolas Richart * * @date Wed May 11 17:26:46 2011 * * @brief test of the dynamic implicit code * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -#include "static_communicator.hh" -#include "mesh_partition_scotch.hh" - -#ifdef AKANTU_USE_SCOTCH -#include "mesh_partition_scotch.hh" -#endif using namespace akantu; /* -------------------------------------------------------------------------- */ #define bar_length 10. #define bar_height 1. #define bar_depth 1. const ElementType TYPE = _triangle_6; //const ElementType TYPE = _tetrahedron_10; const UInt spatial_dimension = 2; Real time_step = 1e-4; const Real F = 0.5e4; const Real L = bar_length; const Real I = bar_depth * bar_height * bar_height * bar_height / 12.; const Real E = 12e7; const Real rho = 1000; const Real m = rho * bar_height * bar_depth; static Real w(UInt n) { return n*n*M_PI*M_PI/(L*L)*sqrt(E*I/m); } static Real analytical_solution(Real time) { return 2*F*L*L*L/(pow(M_PI, 4)*E*I) * ((1. - cos(w(1)*time)) + (1. - cos(w(3)*time))/81. + (1. - cos(w(5)*time))/625.); } /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { debug::setDebugLevel(dblError); - initialize(argc, argv); + initialize("material_implicit_dynamic.dat", argc, argv); Mesh mesh(spatial_dimension); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); MeshPartition * partition = NULL; if(prank == 0) { - MeshIOMSH mesh_io; - mesh_io.read("beam_2d_quad.msh", mesh); - + mesh.read("beam_2d_quad.msh"); partition = new MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); } SolidMechanicsModel model(mesh); model.initParallel(partition); /// model initialization - model.initFull("material_implicit_dynamic.dat", SolidMechanicsModelOptions(_implicit_dynamic)); + model.initFull(SolidMechanicsModelOptions(_implicit_dynamic)); Material &mat = model.getMaterial(0); mat.setParam("E", E); mat.setParam("rho", rho); // boundary conditions const Array & position = mesh.getNodes(); Array & boundary = model.getBoundary(); Array & force = model.getForce(); Array & displacment = model.getDisplacement(); //initial conditions UInt node_to_print = UInt(-1); bool print_node = false; Array node_to_displace; for (UInt n = 0; n < mesh.getNbNodes(); ++n) { Real x = position(n, 0); Real y = position(n, 1); Real z = 0; if(spatial_dimension == 3) z = position(n, 2); if(Math::are_float_equal(x, 0.) && Math::are_float_equal(y, bar_height / 2.)) { boundary(n,0) = true; boundary(n,1) = true; if(spatial_dimension == 3 && Math::are_float_equal(z, bar_depth / 2.)) boundary(n,2) = true; } if(Math::are_float_equal(x, bar_length) && Math::are_float_equal(y, bar_height / 2.)) { boundary(n,1) = true; if(spatial_dimension == 3 && Math::are_float_equal(z, bar_depth / 2.)) boundary(n,2) = true; } if(Math::are_float_equal(x, bar_length / 2.) && Math::are_float_equal(y, bar_height / 2.)) { if(spatial_dimension < 3 || (spatial_dimension == 3 && Math::are_float_equal(z, bar_depth / 2.))) { force(n,1) = F; if(mesh.isLocalOrMasterNode(n)) { print_node = true; node_to_print = n; std::cout << "I, proc " << prank +1 << " handle the print of node " << n << "(" << x << ", "<< y << ", " << z << ")" << std::endl; } } } } model.setTimeStep(time_step); model.updateResidual(); std::stringstream out; out << "position-" << TYPE << "_" << std::scientific << time_step << ".csv"; model.setBaseName("implicit_dynamic"); model.addDumpField("displacement"); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); model.addDumpField("stress" ); model.addDumpField("strain" ); std::ofstream pos; if(print_node) { pos.open(out.str().c_str()); if(!pos.good()) { std::cerr << "Cannot open file " << out.str() <(1e-12, 1000); // model.implicitPred(); // /// convergence loop // do { // if(count > 0 && prank == 0) // std::cout << "passing step " << s << " " << s * time_step << "s - " << std::setw(4) << count << " : " << std::scientific << error << "\r" << std::flush; // model.updateResidual(); // model.solveDynamic(); // model.implicitCorr(); // count++; // } while(!model.testConvergenceIncrement(1e-12, error) && (count < 1000)); // count = 0; if(prank == 0) std::cout << "passing step " << s << " " << s * time_step << "s\r" << std::flush; if(print_node) pos << s << "," << s * time_step << "," << displacment(node_to_print, 1) << "," << analytical_solution(s*time_step) << std::endl; if(s % 10 == 0) { model.computeStresses (); } time += time_step; } if(print_node) pos.close(); finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_eigenstrain.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_eigenstrain.cc index 472218f49..ad6f4d40d 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_eigenstrain.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_material_eigenstrain.cc @@ -1,217 +1,208 @@ /** * @file test_solid_mechanics_model_prestrain_material.cc * * @author Nicolas Richart * @author Aurelia Cuba Ramos * * @date Mon Jan 13 16:05:48 2014 * * @brief test the internal field prestrain * * @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 . * */ /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -#include "element_class.hh" using namespace akantu; Real alpha [3][4] = { { 0.01, 0.02, 0.03, 0.04 }, { 0.05, 0.06, 0.07, 0.08 }, { 0.09, 0.10, 0.11, 0.12 } }; /* -------------------------------------------------------------------------- */ template static Matrix prescribed_strain() { UInt spatial_dimension = ElementClass::getSpatialDimension(); Matrix 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 static Matrix prescribed_stress(Matrix prescribed_eigenstrain) { UInt spatial_dimension = ElementClass::getSpatialDimension(); Matrix stress(spatial_dimension, spatial_dimension); //plane strain in 2d - Matrix strain(spatial_dimension, spatial_dimension); - Matrix pstrain; + Matrix strain(spatial_dimension, spatial_dimension); + Matrix pstrain; pstrain = prescribed_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)); // elastic strain is equal to elastic strain minus the eigenstrain strain -= prescribed_eigenstrain; for (UInt i = 0; i < spatial_dimension; ++i) trace += strain(i,i); Real lambda = nu * E / ((1 + nu) * (1 - 2*nu)); Real mu = E / (2 * (1 + nu)); if(!is_plane_strain) { std::cout << "toto" << std::endl; lambda = nu * E / (1 - nu*nu); } if(spatial_dimension == 1) { stress(0, 0) = E * strain(0, 0); } else { for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) { stress(i, j) = (i == j)*lambda*trace + 2*mu*strain(i, j); } } return stress; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { - initialize(argc, argv); - + initialize("material_elastic_plane_strain.dat", argc, argv); + UInt dim = 3; const ElementType element_type = _tetrahedron_4; const bool plane_strain = true; Matrix prescribed_eigenstrain(dim, dim); prescribed_eigenstrain.clear(); for (UInt i = 0; i < dim; ++i) { - for (UInt j = 0; j < dim; ++j) - prescribed_eigenstrain(i,j) += 0.1; + for (UInt j = 0; j < dim; ++j) + prescribed_eigenstrain(i,j) += 0.1; } /// load mesh Mesh my_mesh(dim); - MeshIOMSH mesh_io; std::stringstream filename; filename << "cube_3d_tet_4.msh"; - mesh_io.read(filename.str(), my_mesh); + my_mesh.read(filename.str()); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization - my_model.initFull("material_elastic_plane_strain.dat", SolidMechanicsModelOptions(_static)); + my_model.initFull(SolidMechanicsModelOptions(_static)); const Array & coordinates = my_mesh.getNodes(); Array & displacement = my_model.getDisplacement(); Array & boundary = my_model.getBoundary(); MeshUtils::buildFacets(my_mesh); my_mesh.createBoundaryGroupFromGeometry(); // 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) { + 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; } } } /* ------------------------------------------------------------------------ */ /* Apply eigenstrain in each element */ /* ------------------------------------------------------------------------ */ - + Array & eigenstrain_vect = const_cast &>(my_model.getMaterial(0).getInternal("eigenstrain")(element_type)); Array::iterator< Matrix > eigenstrain_it = eigenstrain_vect.begin(dim, dim); Array::iterator< Matrix > eigenstrain_end = eigenstrain_vect.end(dim, dim); for (; eigenstrain_it != eigenstrain_end; ++eigenstrain_it) { for (UInt i = 0; i < dim; ++i) for (UInt j = 0; j < dim; ++j) (*eigenstrain_it)(i,j) += prescribed_eigenstrain(i,j); } /* ------------------------------------------------------------------------ */ /* Static solve */ /* ------------------------------------------------------------------------ */ my_model.solveStep<_scm_newton_raphson_tangent_modified, _scc_residual>(2e-4, 2); /* ------------------------------------------------------------------------ */ /* Checks */ /* ------------------------------------------------------------------------ */ - + Array & stress_vect = const_cast &>(my_model.getMaterial(0).getStress(element_type)); Array::iterator< Matrix > stress_it = stress_vect.begin(dim, dim); Array::iterator< Matrix > stress_end = stress_vect.end(dim, dim); - Matrix presc_stress; + Matrix presc_stress; presc_stress = prescribed_stress(prescribed_eigenstrain); Real stress_tolerance = 1e-13; for (; stress_it != stress_end; ++stress_it) { Matrix & stress = *stress_it; Matrix diff(dim, dim); diff = stress; diff -= presc_stress; Real stress_error = diff.norm() / stress.norm(); if(stress_error > stress_tolerance) { std::cerr << "stress error: " << stress_error << " > " << stress_tolerance << std::endl; std::cerr << "stress: " << stress << std::endl << "prescribed stress: " << presc_stress << std::endl; return EXIT_FAILURE; } else { std::cerr << "stress error: " << stress_error << " < " << stress_tolerance << std::endl; } - + } finalize(); return EXIT_SUCCESS; } - - diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_reassign_material.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_reassign_material.cc index bb4f868ab..6d48dec39 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_reassign_material.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_reassign_material.cc @@ -1,216 +1,214 @@ /** * @file test_solid_mechanics_model_reassign_material.cc * @author Aurelia Cuba Ramos * @date Mon May 6 17:37:17 2013 * * @brief test the function reassign material * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "static_communicator.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "aka_grid_dynamic.hh" using namespace akantu; class StraightInterfaceMaterialSelector : public MaterialSelector { public: StraightInterfaceMaterialSelector(SolidMechanicsModel & model, const std::string & mat_1_material, const std::string & mat_2_material, bool & horizontal, Real & pos_interface) : model(model), mat_1_material(mat_1_material), mat_2_material(mat_2_material), horizontal(horizontal), pos_interface(pos_interface) { Mesh & mesh = model.getMesh(); UInt spatial_dimension = mesh.getSpatialDimension(); /// store barycenters of all elements mesh.initByElementTypeArray(barycenters, spatial_dimension, spatial_dimension); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Element e; e.ghost_type = ghost_type; 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); e.type = *it; Array & barycenter = barycenters(*it, ghost_type); barycenter.resize(nb_element); Array::iterator< Vector > bary_it = barycenter.begin(spatial_dimension); for (UInt elem = 0; elem < nb_element; ++elem) { e.element = elem; mesh.getBarycenter(e, *bary_it); ++bary_it; } } } } UInt operator()(const Element & elem) { UInt spatial_dimension = model.getSpatialDimension(); const Vector & bary = barycenters(elem.type, elem.ghost_type).begin(spatial_dimension)[elem.element]; /// check for a given element on which side of the material interface plane the bary center lies and assign corresponding material if (bary(!horizontal) < pos_interface) { return model.getMaterialIndex(mat_1_material);; } return model.getMaterialIndex(mat_2_material);; } bool isConditonVerified() { /// check if material has been (re)-assigned correctly Mesh & mesh = model.getMesh(); UInt spatial_dimension = mesh.getSpatialDimension(); GhostType ghost_type = _not_ghost; 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) { Array & el_idx_by_mat = model.getElementIndexByMaterial(*it, ghost_type); UInt nb_element = mesh.getNbElement(*it, ghost_type); Array::iterator > bary = barycenters(*it, ghost_type).begin(spatial_dimension); for (UInt elem = 0; elem < nb_element; ++elem, ++bary) { /// compare element_index_by material to material index that should be assigned due to the geometry of the interface UInt mat_index; if ((*bary)(!horizontal) < pos_interface) mat_index = model.getMaterialIndex(mat_1_material); else mat_index = model.getMaterialIndex(mat_2_material); if (el_idx_by_mat(elem,0) != mat_index) /// wrong material index, make test fail return false; } } return true; } void moveInterface(Real & pos_new, bool & horizontal_new) { /// update position and orientation of material interface plane pos_interface = pos_new; horizontal = horizontal_new; model.reassignMaterial(); } protected: SolidMechanicsModel & model; ByElementTypeReal barycenters; std::string mat_1_material; std::string mat_2_material; bool horizontal; Real pos_interface; }; /* -------------------------------------------------------------------------- */ /* Main */ /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { bool test_passed; debug::setDebugLevel(dblWarning); - initialize(argc, argv); + initialize("two_materials.dat", argc, argv); /// specify position and orientation of material interface plane bool horizontal = true; Real pos_interface = 0.; UInt spatial_dimension = 3; akantu::StaticCommunicator & comm = akantu::StaticCommunicator::getStaticCommunicator(); akantu::Int psize = comm.getNbProc(); akantu::Int prank = comm.whoAmI(); Mesh mesh(spatial_dimension); akantu::MeshPartition * partition = NULL; if(prank == 0) { /// creation mesh mesh.read("cube_two_materials.msh"); partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); } /// model creation SolidMechanicsModel model(mesh); model.initParallel(partition); delete partition; /// assign the two different materials using the StraightInterfaceMaterialSelector StraightInterfaceMaterialSelector * mat_selector; mat_selector = new StraightInterfaceMaterialSelector(model, "mat_1", "mat_2", horizontal, pos_interface); model.setMaterialSelector(*mat_selector); - model.initFull("two_materials.dat", SolidMechanicsModelOptions(_static)); + model.initFull(SolidMechanicsModelOptions(_static)); // model.setBaseName("test_reassign_material"); // model.addDumpField("element_index_by_material"); // model.addDumpField("partitions"); // model.dump(); /// check if different materials have been assigned correctly test_passed = mat_selector->isConditonVerified(); if (!test_passed) { AKANTU_DEBUG_ERROR("materials not correctly assigned"); return EXIT_FAILURE; } - - /// change orientation of material interface plane horizontal = false; mat_selector->moveInterface(pos_interface, horizontal); // model.dump(); /// test if material has been reassigned correctly test_passed = mat_selector->isConditonVerified(); if (!test_passed) { AKANTU_DEBUG_ERROR("materials not correctly reassigned"); return EXIT_FAILURE; } finalize(); if(prank == 0) std::cout << "OK: test passed!" << std::endl; return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_segment_parallel.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_segment_parallel.cc index 7676e5c55..a69d0ecc3 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_segment_parallel.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_segment_parallel.cc @@ -1,122 +1,115 @@ /** * @file test_solid_mechanics_model_segment_parallel.cc * * @author Nicolas Richart * * @date Sun Sep 26 13:39:16 2010 * * @brief test of the class SolidMechanicsModel * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -#include "static_communicator.hh" -#include "mesh_partition_scotch.hh" /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::UInt spatial_dimension = 1; akantu::UInt max_steps = 10000; akantu::Real time_factor = 0.2; - akantu::initialize(argc, argv); + akantu::initialize("material.dat", argc, argv); akantu::Mesh mesh(spatial_dimension); akantu::StaticCommunicator & comm = akantu::StaticCommunicator::getStaticCommunicator(); akantu::Int psize = comm.getNbProc(); akantu::Int prank = comm.whoAmI(); akantu::debug::setDebugLevel(akantu::dblInfo); akantu::MeshPartition * partition = NULL; if(prank == 0) { - akantu::MeshIOMSH mesh_io; - mesh_io.read("segment.msh", mesh); + mesh.read("segment.msh"); partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); } akantu::SolidMechanicsModel model(mesh); model.initParallel(partition); /// model initialization - model.initFull("material.dat"); + model.initFull(); std::cout << model.getMaterial(0) << std::endl; model.assembleMassLumped(); model.setBaseName("segment_parallel"); model.addDumpField("displacement"); model.addDumpField("mass" ); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); model.addDumpField("stress" ); model.addDumpField("strain" ); /// boundary conditions for (akantu::UInt i = 0; i < mesh.getNbNodes(); ++i) { model.getDisplacement().storage()[spatial_dimension*i] = model.getFEM().getMesh().getNodes().storage()[i] / 100. ; if(model.getFEM().getMesh().getNodes().storage()[spatial_dimension*i] <= 1e-15) model.getBoundary().storage()[i] = true; } akantu::Real time_step = model.getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model.setTimeStep(time_step); for(akantu::UInt s = 1; s <= max_steps; ++s) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); akantu::Real epot = model.getPotentialEnergy(); akantu::Real ekin = model.getKineticEnergy(); if(prank == 0) { std::cout << s << " " << epot << " " << ekin << " " << epot + ekin << std::endl; } model.dump(); if(s % 10 == 0) std::cerr << "passing step " << s << "/" << max_steps << std::endl; } 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 ee6888626..9e74470a4 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,108 +1,101 @@ /** * @file test_solid_mechanics_model_square.cc * * @author Nicolas Richart * * @date Wed Sep 22 13:39:02 2010 * * @brief test of the class SolidMechanicsModel * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" -#include "material.hh" -#include "fem.hh" -/* -------------------------------------------------------------------------- */ + using namespace akantu; -int main(int argc, char *argv[]) -{ - akantu::initialize(argc, argv); +int main(int argc, char *argv[]) { + akantu::initialize("material.dat", argc, argv); UInt max_steps = 1000; Real epot, ekin; Mesh mesh(2); - MeshIOMSH mesh_io; - mesh_io.read("square.msh", mesh); + mesh.read("square.msh"); mesh.createBoundaryGroupFromGeometry(); SolidMechanicsModel model(mesh); /// model initialization - model.initFull("material.dat"); + model.initFull(); Real time_step = model.getStableTimeStep(); model.setTimeStep(time_step/10.); model.assembleMassLumped(); std::cout << model << std::endl; // Boundary condition (Neumann) Matrix stress(2,2); stress.eye(1e3); model.applyBC(BC::Neumann::FromHigherDim(stress), "boundary_0"); model.setBaseName("square"); model.addDumpField("displacement"); model.addDumpField("mass" ); model.addDumpField("velocity" ); model.addDumpField("acceleration"); model.addDumpField("force" ); model.addDumpField("residual" ); 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) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); epot = model.getPotentialEnergy(); ekin = model.getKineticEnergy(); 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_synchronizer/test_dof_synchronizer.cc b/test/test_synchronizer/test_dof_synchronizer.cc index fd47c67bc..14a4869cb 100644 --- a/test/test_synchronizer/test_dof_synchronizer.cc +++ b/test/test_synchronizer/test_dof_synchronizer.cc @@ -1,230 +1,229 @@ /** * @file test_dof_synchronizer.cc * * @author Nicolas Richart * * @date Fri Jun 17 17:28:22 2011 * * @brief Test the functionality of the DOFSynchronizer class * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "dof_synchronizer.hh" #include "mesh_partition_scotch.hh" #include "mesh_io.hh" #include "static_communicator.hh" #include "distributed_synchronizer.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.hh" #endif //AKANTU_USE_IOHELPER /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { const UInt spatial_dimension = 2; - debug::setDebugLevel(dblDebug); - initialize(argc, argv); + StaticCommunicator & comm = akantu::StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); Mesh mesh(spatial_dimension); /* ------------------------------------------------------------------------ */ /* Parallel initialization */ /* ------------------------------------------------------------------------ */ DistributedSynchronizer * communicator; MeshPartition * partition; if(prank == 0) { MeshIOMSH mesh_io; mesh_io.read("bar.msh", mesh); std::cout << "Partitioning mesh..." << std::endl; partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); communicator = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, partition); delete partition; } else { communicator = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, NULL); } UInt nb_nodes = mesh.getNbNodes(); Array dof_vector(nb_nodes, spatial_dimension, "Test vector"); std::cout << "Initializing the synchronizer" << std::endl; DOFSynchronizer dof_synchronizer(mesh, spatial_dimension); /* ------------------------------------------------------------------------ */ /* test the sznchroniyation */ /* ------------------------------------------------------------------------ */ for (UInt n = 0; n < nb_nodes; ++n) { UInt gn = mesh.getNodeGlobalId(n); for (UInt d = 0; d < spatial_dimension; ++d) { if(mesh.isMasterNode(n)) dof_vector(n,d) = gn*spatial_dimension + d; else if(mesh.isLocalNode(n)) dof_vector(n,d) = - (double) (gn*spatial_dimension + d); else if(mesh.isSlaveNode(n)) dof_vector(n,d) = NAN; else dof_vector(n,d) = -NAN; } } std::cout << "Synchronizing a dof vector" << std::endl; dof_synchronizer.synchronize(dof_vector); for (UInt n = 0; n < nb_nodes; ++n) { UInt gn = mesh.getNodeGlobalId(n); for (UInt d = 0; d < spatial_dimension; ++d) { if(!((mesh.isMasterNode(n) && dof_vector(n,d) == (gn*spatial_dimension + d)) || (mesh.isLocalNode(n) && dof_vector(n,d) == - (double) (gn*spatial_dimension + d)) || (mesh.isSlaveNode(n) && dof_vector(n,d) == (gn*spatial_dimension + d)) || (mesh.isPureGhostNode(n)) ) ) { debug::setDebugLevel(dblTest); std::cout << "prank : " << prank << " (node " << gn*spatial_dimension + d << "[" << n * spatial_dimension + d << "]) - " << (mesh.isMasterNode(n) && dof_vector(n,d) == (gn*spatial_dimension + d)) << " " << (mesh.isLocalNode(n) && dof_vector(n,d) == - (double) (gn*spatial_dimension + d)) << " " << (mesh.isSlaveNode(n) && dof_vector(n,d) == (gn*spatial_dimension + d)) << " " << (mesh.isPureGhostNode(n)) << std::endl; std::cout << dof_vector << dof_synchronizer.getDOFGlobalIDs() << dof_synchronizer.getDOFTypes() << std::endl; debug::setDebugLevel(dblDebug); return EXIT_FAILURE; } } } /* ------------------------------------------------------------------------ */ /* test the reduce operation */ /* ------------------------------------------------------------------------ */ for (UInt n = 0; n < nb_nodes; ++n) { for (UInt d = 0; d < spatial_dimension; ++d) { if(mesh.isMasterNode(n)) dof_vector(n,d) = 1; else if(mesh.isLocalNode(n)) dof_vector(n,d) = -300; else if(mesh.isSlaveNode(n)) dof_vector(n,d) = 2; else dof_vector(n,d) = -500; } } std::cout << "Reducing a dof vector" << std::endl; dof_synchronizer.reduceSynchronize(dof_vector); for (UInt n = 0; n < nb_nodes; ++n) { for (UInt d = 0; d < spatial_dimension; ++d) { if(!((mesh.isMasterNode(n) && dof_vector(n,d) >= 3) || (mesh.isLocalNode(n) && dof_vector(n,d) == -300) || (mesh.isSlaveNode(n) && dof_vector(n,d) >= 3) || (mesh.isPureGhostNode(n) && dof_vector(n,d) == -500) ) ) { debug::setDebugLevel(dblTest); std::cout << dof_vector << dof_synchronizer.getDOFGlobalIDs() << dof_synchronizer.getDOFTypes() << std::endl; debug::setDebugLevel(dblDebug); return EXIT_FAILURE; } } } /* ------------------------------------------------------------------------ */ /* test the gather/scatter */ /* ------------------------------------------------------------------------ */ dof_vector.clear(); for (UInt n = 0; n < nb_nodes; ++n) { UInt gn = mesh.getNodeGlobalId(n); for (UInt d = 0; d < spatial_dimension; ++d) { if(mesh.isMasterNode(n)) dof_vector(n,d) = gn * spatial_dimension + d; else if(mesh.isLocalNode(n)) dof_vector(n,d) = - (double) (gn * spatial_dimension + d); else if(mesh.isSlaveNode(n)) dof_vector(n,d) = NAN; else dof_vector(n,d) = -NAN; } } std::cout << "Initializing the gather/scatter information" << std::endl; dof_synchronizer.initScatterGatherCommunicationScheme(); std::cout << "Gathering on proc 0" << std::endl; if(prank == 0) { UInt nb_global_nodes = mesh.getNbGlobalNodes(); Array gathered(nb_global_nodes, spatial_dimension, "gathered information"); dof_synchronizer.gather(dof_vector, 0, &gathered); for (UInt n = 0; n < nb_nodes; ++n) { for (UInt d = 0; d < spatial_dimension; ++d) { if(std::abs(gathered(n,d)) != n * spatial_dimension + d) { debug::setDebugLevel(dblTest); std::cout << gathered << std::endl; std::cout << dof_vector << dof_synchronizer.getDOFGlobalIDs() << dof_synchronizer.getDOFTypes() << std::endl; debug::setDebugLevel(dblDebug); return EXIT_FAILURE; } } } } else { dof_synchronizer.gather(dof_vector, 0); } dof_vector.clear(); std::cout << "Scattering from proc 0" << std::endl; if(prank == 0) { UInt nb_global_nodes = mesh.getNbGlobalNodes(); Array to_scatter(nb_global_nodes, spatial_dimension, "to scatter information"); for (UInt d = 0; d < nb_global_nodes * spatial_dimension; ++d) { to_scatter.storage()[d] = d; } dof_synchronizer.scatter(dof_vector, 0, &to_scatter); } else { dof_synchronizer.scatter(dof_vector, 0); } for (UInt n = 0; n < nb_nodes; ++n) { UInt gn = mesh.getNodeGlobalId(n); for (UInt d = 0; d < spatial_dimension; ++d) { if(!mesh.isPureGhostNode(n) && !(dof_vector(n,d) == (gn * spatial_dimension + d))) { debug::setDebugLevel(dblTest); std::cout << dof_vector << dof_synchronizer.getDOFGlobalIDs() << dof_synchronizer.getDOFTypes() << std::endl; debug::setDebugLevel(dblDebug); return EXIT_FAILURE; } } } delete communicator; finalize(); return 0; }