diff --git a/packages/core.cmake b/packages/core.cmake index 3760fc4ca..a75192465 100644 --- a/packages/core.cmake +++ b/packages/core.cmake @@ -1,482 +1,480 @@ #=============================================================================== # @file 00_core.cmake # # @author Guillaume Anciaux # @author Nicolas Richart # # @date creation: Mon Nov 21 2011 # @date last modification: Fri Sep 19 2014 # # @brief package description for core # # @section LICENSE # # Copyright (©) 2010-2012, 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 . # #=============================================================================== package_declare(core NOT_OPTIONAL DESCRIPTION "core package for Akantu") package_declare_sources(core common/aka_array.cc common/aka_array.hh common/aka_array_tmpl.hh common/aka_blas_lapack.hh common/aka_circular_array.hh common/aka_circular_array_inline_impl.cc common/aka_common.cc common/aka_common.hh common/aka_common_inline_impl.cc common/aka_csr.hh common/aka_element_classes_info_inline_impl.cc common/aka_error.cc common/aka_error.hh common/aka_event_handler_manager.hh common/aka_extern.cc common/aka_fwd.hh common/aka_grid_dynamic.hh common/aka_math.cc common/aka_math.hh common/aka_math_tmpl.hh common/aka_memory.cc common/aka_memory.hh common/aka_memory_inline_impl.cc common/aka_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 fe_engine/element_class.cc fe_engine/element_class.hh fe_engine/element_class_tmpl.hh fe_engine/element_classes/element_class_hexahedron_8_inline_impl.cc fe_engine/element_classes/element_class_hexahedron_20_inline_impl.cc fe_engine/element_classes/element_class_pentahedron_6_inline_impl.cc fe_engine/element_classes/element_class_pentahedron_15_inline_impl.cc fe_engine/element_classes/element_class_point_1_inline_impl.cc fe_engine/element_classes/element_class_quadrangle_4_inline_impl.cc fe_engine/element_classes/element_class_quadrangle_8_inline_impl.cc fe_engine/element_classes/element_class_segment_2_inline_impl.cc fe_engine/element_classes/element_class_segment_3_inline_impl.cc fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.cc fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.cc fe_engine/element_classes/element_class_triangle_3_inline_impl.cc fe_engine/element_classes/element_class_triangle_6_inline_impl.cc fe_engine/fe_engine.cc fe_engine/fe_engine.hh fe_engine/fe_engine_inline_impl.cc fe_engine/fe_engine_template.hh fe_engine/fe_engine_template_tmpl.hh fe_engine/geometrical_element.cc fe_engine/integration_element.cc fe_engine/integrator.hh fe_engine/integrator_gauss.hh fe_engine/integrator_gauss_inline_impl.cc fe_engine/interpolation_element.cc fe_engine/interpolation_element_tmpl.hh fe_engine/quadrature_point.hh fe_engine/shape_functions.hh fe_engine/shape_functions_inline_impl.cc fe_engine/shape_lagrange.cc fe_engine/shape_lagrange.hh fe_engine/shape_lagrange_inline_impl.cc fe_engine/shape_linked.cc fe_engine/shape_linked.hh fe_engine/shape_linked_inline_impl.cc fe_engine/element.hh fe_engine/quadrature_point.hh io/dumper/dumpable.hh io/dumper/dumpable.cc io/dumper/dumpable_dummy.hh io/dumper/dumpable_inline_impl.hh io/dumper/dumper_field.hh io/dumper/dumper_material_padders.hh io/dumper/dumper_filtered_connectivity.hh io/dumper/dumper_element_type.hh io/dumper/dumper_element_partition.hh io/mesh_io.cc io/mesh_io.hh io/mesh_io/mesh_io_abaqus.cc io/mesh_io/mesh_io_abaqus.hh io/mesh_io/mesh_io_diana.cc io/mesh_io/mesh_io_diana.hh io/mesh_io/mesh_io_msh.cc io/mesh_io/mesh_io_msh.hh io/model_io.cc io/model_io.hh io/parser/algebraic_parser.hh io/parser/input_file_parser.hh io/parser/parsable.cc io/parser/parsable.hh io/parser/parsable_tmpl.hh io/parser/parser.cc io/parser/parser.hh io/parser/parser_tmpl.hh io/parser/cppargparse/cppargparse.hh io/parser/cppargparse/cppargparse.cc io/parser/cppargparse/cppargparse_tmpl.hh mesh/element_group.cc mesh/element_group.hh mesh/element_group_inline_impl.cc mesh/element_type_map.hh mesh/element_type_map_tmpl.hh mesh/element_type_map_filter.hh mesh/group_manager.cc mesh/group_manager.hh mesh/group_manager_inline_impl.cc mesh/mesh.cc mesh/mesh.hh mesh/mesh_accessor.hh mesh/mesh_events.hh mesh/mesh_filter.hh mesh/mesh_data.cc mesh/mesh_data.hh mesh/mesh_data_tmpl.hh mesh/mesh_inline_impl.cc mesh/node_group.cc mesh/node_group.hh mesh/node_group_inline_impl.cc mesh_utils/mesh_partition.cc mesh_utils/mesh_partition.hh mesh_utils/mesh_partition/mesh_partition_mesh_data.cc mesh_utils/mesh_partition/mesh_partition_mesh_data.hh mesh_utils/mesh_partition/mesh_partition_scotch.hh mesh_utils/mesh_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/dof_manager.cc model/dof_manager.hh model/dof_manager_inline_impl.cc model/model_solver.cc model/model_solver.hh model/non_linear_solver.hh model/non_linear_solver_default.cc model/non_linear_solver_default.hh model/solver_callback.hh model/time_step_solver.hh model/time_step_solvers/time_step_solver_default.cc model/time_step_solvers/time_step_solver_default.hh model/time_step_solvers/time_step_solver_default_explicit.hh model/non_linear_solver_callback.hh model/integration_scheme/integration_scheme.hh model/time_step_solvers/time_step_solver_default_solver_callback.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_selector.hh model/solid_mechanics/material_selector_tmpl.hh model/solid_mechanics/materials/internal_field.hh model/solid_mechanics/materials/internal_field_tmpl.hh model/solid_mechanics/materials/random_internal_field.hh model/solid_mechanics/materials/random_internal_field_tmpl.hh model/solid_mechanics/solid_mechanics_model.cc model/solid_mechanics/solid_mechanics_model.hh model/solid_mechanics/solid_mechanics_model_inline_impl.cc model/solid_mechanics/solid_mechanics_model_mass.cc model/solid_mechanics/solid_mechanics_model_material.cc model/solid_mechanics/solid_mechanics_model_tmpl.hh model/solid_mechanics/solid_mechanics_model_event_handler.hh model/solid_mechanics/materials/plane_stress_toolbox.hh model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh model/solid_mechanics/materials/material_core_includes.hh model/solid_mechanics/materials/material_elastic.cc model/solid_mechanics/materials/material_elastic.hh model/solid_mechanics/materials/material_elastic_inline_impl.cc model/solid_mechanics/materials/material_thermal.cc model/solid_mechanics/materials/material_thermal.hh model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh model/solid_mechanics/materials/material_elastic_orthotropic.cc model/solid_mechanics/materials/material_elastic_orthotropic.hh model/solid_mechanics/materials/material_damage/material_damage.hh model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh model/solid_mechanics/materials/material_damage/material_marigo.cc model/solid_mechanics/materials/material_damage/material_marigo.hh model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.cc model/solid_mechanics/materials/material_damage/material_mazars.cc model/solid_mechanics/materials/material_damage/material_mazars.hh model/solid_mechanics/materials/material_damage/material_mazars_inline_impl.cc model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh model/solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.cc model/solid_mechanics/materials/material_plastic/material_plastic.cc model/solid_mechanics/materials/material_plastic/material_plastic.hh model/solid_mechanics/materials/material_plastic/material_plastic_inline_impl.cc model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.cc model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh solver/sparse_solver.cc solver/sparse_solver.hh solver/sparse_solver_inline_impl.cc solver/sparse_matrix.cc solver/sparse_matrix.hh solver/sparse_matrix_inline_impl.cc - solver/static_solver.hh - solver/static_solver.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 ) package_declare_elements(core ELEMENT_TYPES _point_1 _segment_2 _segment_3 _triangle_3 _triangle_6 _quadrangle_4 _quadrangle_8 _tetrahedron_4 _tetrahedron_10 _pentahedron_6 _pentahedron_15 _hexahedron_8 _hexahedron_20 KIND regular GEOMETRICAL_TYPES _gt_point _gt_segment_2 _gt_segment_3 _gt_triangle_3 _gt_triangle_6 _gt_quadrangle_4 _gt_quadrangle_8 _gt_tetrahedron_4 _gt_tetrahedron_10 _gt_hexahedron_8 _gt_hexahedron_20 _gt_pentahedron_6 _gt_pentahedron_15 INTERPOLATION_TYPES _itp_lagrange_point_1 _itp_lagrange_segment_2 _itp_lagrange_segment_3 _itp_lagrange_triangle_3 _itp_lagrange_triangle_6 _itp_lagrange_quadrangle_4 _itp_serendip_quadrangle_8 _itp_lagrange_tetrahedron_4 _itp_lagrange_tetrahedron_10 _itp_lagrange_hexahedron_8 _itp_serendip_hexahedron_20 _itp_lagrange_pentahedron_6 _itp_lagrange_pentahedron_15 GEOMETRICAL_SHAPES _gst_point _gst_triangle _gst_square _gst_prism GAUSS_INTEGRATION_TYPES _git_point _git_segment _git_triangle _git_tetrahedron _git_pentahedron INTERPOLATION_KIND _itk_lagrangian FE_ENGINE_LISTS gradient_on_quadrature_points interpolate_on_quadrature_points interpolate compute_normals_on_control_points inverse_map contains compute_shapes compute_shapes_derivatives get_shapes_derivatives ) package_declare_material_infos(core LIST AKANTU_CORE_MATERIAL_LIST INCLUDE material_core_includes.hh ) package_declare_documentation_files(core manual.sty manual.cls manual.tex manual-macros.sty manual-titlepages.tex manual-introduction.tex manual-gettingstarted.tex manual-io.tex manual-solidmechanicsmodel.tex manual-constitutive-laws.tex manual-lumping.tex manual-elements.tex manual-appendix-elements.tex manual-appendix-materials.tex manual-appendix-packages.tex manual-backmatter.tex manual-bibliography.bib manual-bibliographystyle.bst figures/bc_and_ic_example.pdf figures/boundary.pdf figures/boundary.svg figures/dirichlet.pdf figures/dirichlet.svg figures/doc_wheel.pdf figures/doc_wheel.svg figures/dynamic_analysis.png figures/explicit_dynamic.pdf figures/explicit_dynamic.svg figures/static.pdf figures/static.svg figures/hooke_law.pdf figures/hot-point-1.png figures/hot-point-2.png figures/implicit_dynamic.pdf figures/implicit_dynamic.svg figures/insertion.pdf figures/interpolate.pdf figures/interpolate.svg figures/problemDomain.pdf_tex figures/problemDomain.pdf figures/static_analysis.png figures/stress_strain_el.pdf figures/tangent.pdf figures/tangent.svg figures/vectors.pdf figures/vectors.svg figures/stress_strain_neo.pdf figures/visco_elastic_law.pdf figures/isotropic_hardening_plasticity.pdf figures/stress_strain_visco.pdf figures/elements/hexahedron_8.pdf figures/elements/hexahedron_8.svg figures/elements/quadrangle_4.pdf figures/elements/quadrangle_4.svg figures/elements/quadrangle_8.pdf figures/elements/quadrangle_8.svg figures/elements/segment_2.pdf figures/elements/segment_2.svg figures/elements/segment_3.pdf figures/elements/segment_3.svg figures/elements/tetrahedron_10.pdf figures/elements/tetrahedron_10.svg figures/elements/tetrahedron_4.pdf figures/elements/tetrahedron_4.svg figures/elements/triangle_3.pdf figures/elements/triangle_3.svg figures/elements/triangle_6.pdf figures/elements/triangle_6.svg figures/elements/xtemp.pdf ) package_declare_documentation(core "This package is the core engine of \\akantu. It depends on:" "\\begin{itemize}" "\\item A C++ compiler (\\href{http://gcc.gnu.org/}{GCC} >= 4, or \\href{https://software.intel.com/en-us/intel-compilers}{Intel})." "\\item The cross-platform, open-source \\href{http://www.cmake.org/}{CMake} build system." "\\item The \\href{http://www.boost.org/}{Boost} C++ portable libraries." "\\item The \\href{http://www.zlib.net/}{zlib} compression library." "\\end{itemize}" "" "Under Ubuntu (14.04 LTS) the installation can be performed using the commands:" "\\begin{command}" " > sudo apt-get install cmake libboost-dev zlib1g-dev g++" "\\end{command}" "" "Under Mac OS X the installation requires the following steps:" "\\begin{itemize}" "\\item Install Xcode" "\\item Install the command line tools." "\\item Install the MacPorts project which allows to automatically" "download and install opensource packages." "\\end{itemize}" "Then the following commands should be typed in a terminal:" "\\begin{command}" " > sudo port install cmake gcc48 boost" "\\end{command}" ) find_program(READLINK_COMMAND readlink) find_program(ADDR2LINE_COMMAND addr2line) 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 CACHE INTERNAL "" FORCE) else() set(AKANTU_USE_OBSOLETE_GETTIMEOFDAY OFF CACHE INTERNAL "" FORCE) endif() diff --git a/src/common/aka_common.cc b/src/common/aka_common.cc index 272a70cf6..46064d603 100644 --- a/src/common/aka_common.cc +++ b/src/common/aka_common.cc @@ -1,145 +1,137 @@ /** * @file aka_common.cc * * @author Nicolas Richart * * @date creation: Mon Jun 14 2010 * @date last modification: Mon Sep 15 2014 * * @brief Initialization of global variables * * @section LICENSE * * Copyright (©) 2010-2012, 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 "aka_common.hh" #include "aka_static_memory.hh" #include "static_communicator.hh" -#include "static_solver.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(); static_argparser.setParallelContext(comm.whoAmI(), comm.getNbProc()); static_argparser.setExternalExitFunction(debug::exit); static_argparser.addArgument("--aka_input_file", "Akantu's input file", 1, cppargparse::_string, std::string()); static_argparser.addArgument("--aka_debug_level", std::string("Akantu's overall debug level") + std::string(" (0: error, 1: exceptions, 4: warnings, 5: info, ..., 100: dump,") + std::string(" more info on levels can be foind in aka_error.hh)"), 1, cppargparse::_integer, int(dblWarning)); static_argparser.addArgument("--aka_print_backtrace", "Should Akantu print a backtrace in case of error", 0, cppargparse::_boolean, false, true); static_argparser.parse(argc, argv, cppargparse::_remove_parsed); std::string infile = static_argparser["aka_input_file"]; if(infile == "") infile = input_file; debug::setDebugLevel(dblError); if ("" != infile) { static_parser.parse(infile); } long int seed; try { seed = static_parser.getParameter("seed", _ppsc_current_scope); } catch (debug::Exception &) { seed = time(NULL); } int dbl_level = static_argparser["aka_debug_level"]; debug::setDebugLevel(DebugLevel(dbl_level)); debug::debugger.printBacktrace(static_argparser["aka_print_backtrace"]); seed *= (comm.whoAmI() + 1); Rand48Generator::seed(seed); RandGenerator::seed(seed); AKANTU_DEBUG_INFO("Random seed set to " << seed); - /// initialize external solvers - StaticSolver::getStaticSolver().initialize(argc,argv); - AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void finalize() { AKANTU_DEBUG_IN(); - /// finalize external solvers - StaticSolver::getStaticSolver().finalize(); - 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; } /* -------------------------------------------------------------------------- */ 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 489fb4f3d..632fdf86f 100644 --- a/src/common/aka_common.hh +++ b/src/common/aka_common.hh @@ -1,458 +1,464 @@ /** * @file aka_common.hh * * @author Nicolas Richart * * @date creation: Mon Jun 14 2010 * @date last modification: Mon Sep 15 2014 * * @brief common type descriptions for akantu * * @section LICENSE * * Copyright (©) 2010-2012, 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 . * * @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__ }; /* -------------------------------------------------------------------------- */ #define __BEGIN_AKANTU_DUMPER__ namespace dumper { #define __END_AKANTU_DUMPER__ } /* -------------------------------------------------------------------------- */ #if defined(WIN32) # define __attribute__(x) #endif /* -------------------------------------------------------------------------- */ #include "aka_config.hh" #include "aka_error.hh" #include "aka_safe_enum.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Common types */ /* -------------------------------------------------------------------------- */ typedef std::string ID; static const Real UINT_INIT_VALUE = Real(0.); #ifdef AKANTU_NDEBUG static const Real REAL_INIT_VALUE = Real(0.); #else static const Real REAL_INIT_VALUE = std::numeric_limits::quiet_NaN(); #endif /* -------------------------------------------------------------------------- */ /* Memory types */ /* -------------------------------------------------------------------------- */ typedef UInt MemoryID; typedef std::string Surface; typedef std::pair SurfacePair; typedef std::list< SurfacePair > SurfacePairList; /* -------------------------------------------------------------------------- */ extern const UInt _all_dimensions; /* -------------------------------------------------------------------------- */ /* Mesh/FEM/Model types */ /* -------------------------------------------------------------------------- */ __END_AKANTU__ #include "aka_element_classes_info.hh" __BEGIN_AKANTU__ /// small help to use names for directions enum SpacialDirection { _x = 0, _y = 1, _z = 2 }; /// enum MeshIOType type of mesh reader/writer enum MeshIOType { _miot_auto, ///< Auto guess of the reader to use based on the extension _miot_gmsh, ///< Gmsh files _miot_gmsh_struct, ///< Gsmh reader with reintpretation of elements has structures elements _miot_diana, ///< TNO Diana mesh format _miot_abaqus ///< Abaqus mesh format }; /// enum 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 DOFSupportType defines which kind of dof that can exists enum DOFSupportType { _dst_nodal, _dst_generic }; -//! enum ContactResolutionMethod types of solving for the contact -enum ContactResolutionMethod { - _penalty, - _lagrangian, - _augmented_lagrangian, - _nitsche, - _mortar -}; - -//! enum ContactImplementationMethod types for different contact implementations -enum ContactImplementationMethod { - _none, - _uzawa, - _generalized_newton -}; - - /// Type of non linear resolution available in akantu enum NonLinearSolverType { _nls_linear, ///< No non linear convergence loop _nls_newton_raphson, ///< Regular Newton-Raphson _nls_newton_raphson_modified, ///< Newton-Raphson with initial tangent }; /// Type of time stepping solver enum TimeStepSolverType { - _tsst_forward_euler, - _tsst_trapezoidal_rule_1, - _tsst_backward_euler, - _tsst_central_difference, - _tsst_trapezoidal_rule_2 + _tsst_forward_euler, ///< GeneralizedTrapezoidal(0) + _tsst_trapezoidal_rule_1, ///< GeneralizedTrapezoidal(1/2) + _tsst_backward_euler, ///< GeneralizedTrapezoidal(1) + _tsst_central_difference, ///< NewmarkBeta(0, 1/2) + _tsst_fox_goodwin, ///< NewmarkBeta(1/6, 1/2) + _tsst_trapezoidal_rule_2, ///< NewmarkBeta(1/2, 1/2) + _tsst_linear_acceleration, ///< NewmarkBeta(1/3, 1/2) + _tsst_newmark_beta, ///< generic NewmarkBeta with user defined + /// alpha and beta + _tsst_generalized_trapezoidal, ///< generic GeneralizedTrapezoidal with user + ///defined alpha }; /// 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_solution, ///< Use solution to test the convergence _scc_residual_mass_wgh ///< Use residual weighted by inv. nodal mass to testb }; /// enum CohesiveMethod type of insertion of cohesive elements enum CohesiveMethod { _intrinsic, _extrinsic }; +//! enum ContactResolutionMethod types of solving for the contact +enum ContactResolutionMethod { + _penalty, + _lagrangian, + _augmented_lagrangian, + _nitsche, + _mortar +}; + +//! enum ContactImplementationMethod types for different contact implementations +enum ContactImplementationMethod { + _none, + _uzawa, + _generalized_newton +}; + + /// 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 MatrixType { _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_gradu, //< synchronization of the SolidMechanicsModel.displacement _gst_smm_boundary, //< synchronization of the boundary, forces, velocities and displacement _gst_smm_uv, //< synchronization of the nodal velocities and displacement _gst_smm_res, //< synchronization of the nodal residual _gst_smm_init_mat, //< synchronization of the data to initialize materials _gst_smm_stress, //< synchronization of the stresses to compute the internal forces _gst_smmc_facets, //< synchronization of facet data to setup facet synch _gst_smmc_facets_conn, //< synchronization of facet global connectivity _gst_smmc_facets_stress, //< synchronization of facets' stress to setup facet synch _gst_smmc_damage, //< synchronization of damage //--- CohesiveElementInserter tags --- _gst_ce_inserter, //< synchronization of global nodes id of newly inserted cohesive elements _gst_ce_groups, //< synchronization of cohesive element insertion depending on facet groups //--- GroupManager tags --- _gst_gm_clusters, //< synchronization of clusters //--- HeatTransfer tags --- _gst_htm_capacity, //< synchronization of the nodal heat capacity _gst_htm_temperature, //< synchronization of the nodal temperature _gst_htm_gradient_temperature, //< synchronization of the element gradient temperature //--- LevelSet tags --- /// 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_user_1, //< tag for user simulations _gst_user_2, //< tag for user simulations _gst_material_id, //< synchronization of the material ids _gst_for_dump, //< everything that needs to be synch before dump //--- Contact & Friction --- _gst_cf_nodal, //< synchronization of disp, velo, and current position _gst_cf_incr, //< synchronization of increment ///--- Solver tags --- _gst_solver_solution //< synchronization of the solution obained with the PETSc solver }; /// standard output stream operator for SynchronizationTag inline std::ostream & operator <<(std::ostream & stream, SynchronizationTag type); /// @enum GhostType type of ghost enum GhostType { _not_ghost, _ghost, _casper // not used but a real cute ghost }; /* -------------------------------------------------------------------------- */ struct GhostType_def { 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); /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /// give a string representation of the a human readable size in bit template std::string printMemorySize(UInt size); /* -------------------------------------------------------------------------- */ __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 Parser & getStaticParser(); /// get access to the user part of the internal input file parser const ParserSection & getUserParser(); __END_AKANTU__ #include "aka_common_inline_impl.cc" #endif /* __AKANTU_COMMON_HH__ */ diff --git a/src/common/aka_extern.cc b/src/common/aka_extern.cc index b2648381c..0b4065d37 100644 --- a/src/common/aka_extern.cc +++ b/src/common/aka_extern.cc @@ -1,101 +1,95 @@ /** * @file aka_extern.cc * * @author Nicolas Richart * * @date creation: Mon Jun 14 2010 * @date last modification: Thu Apr 03 2014 * * @brief initialisation of all global variables * to insure the order of creation * * @section LICENSE * * Copyright (©) 2010-2012, 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 "aka_common.hh" #include "aka_array.hh" #include "aka_math.hh" #include "aka_random_generator.hh" #include "parser.hh" #include "cppargparse.hh" -#include "static_solver.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; /// 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; -/* -------------------------------------------------------------------------- */ -UInt StaticSolver::nb_references = 0; -StaticSolver * StaticSolver::static_solver = NULL; - /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/fe_engine/fe_engine.hh b/src/fe_engine/fe_engine.hh index 55577e65c..ff64042ec 100644 --- a/src/fe_engine/fe_engine.hh +++ b/src/fe_engine/fe_engine.hh @@ -1,356 +1,352 @@ /** * @file fe_engine.hh * * @author Guillaume Anciaux * @author Nicolas Richart * * @date creation: Tue Jul 20 2010 * @date last modification: Mon Jul 07 2014 * * @brief FEM class * * @section LICENSE * * Copyright (©) 2010-2012, 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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_FE_ENGINE_HH__ #define __AKANTU_FE_ENGINE_HH__ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" #include "mesh.hh" #include "element_class.hh" #include "quadrature_point.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ class Integrator; class ShapeFunctions; /* -------------------------------------------------------------------------- */ /** * The generic FEEngine class derived in a FEEngineTemplate class containing the * shape functions and the integration method */ class FEEngine : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FEEngine(Mesh & mesh, UInt spatial_dimension = _all_dimensions, ID id = "fem", MemoryID memory_id = 0); virtual ~FEEngine(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// 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); + 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; + 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; + 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" but don't sum over all quadrature points 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; + 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; + const ElementType & type, + UInt index, const GhostType & ghost_type = _not_ghost) const = 0; /* ------------------------------------------------------------------------ */ /* compatibility with old FEEngine fashion */ /* ------------------------------------------------------------------------ */ #ifndef SWIG /// get the number of quadrature points virtual UInt getNbQuadraturePoints(const ElementType & type, - const GhostType & ghost_type = _not_ghost) const = 0; + 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, - UInt id = 0) const = 0; + const GhostType & ghost_type = _not_ghost, + UInt id = 0) 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; #endif /* ------------------------------------------------------------------------ */ /* 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, + 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, + 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, - ElementTypeMapArray & uq, + ElementTypeMapArray & uq, const ElementTypeMapArray * filter_elements = NULL) const = 0; virtual void interpolate(const Vector & real_coords, - const Matrix & nodal_values, - Vector & interpolated, - const Element & element) const = 0; + const Matrix & nodal_values, + Vector & interpolated, + const Element & element) const = 0; virtual void computeShapes(const Vector & real_coords, UInt elem, const ElementType & type, Vector & shapes, const GhostType & ghost_type = _not_ghost) const = 0; virtual void computeShapeDerivatives(const Vector & real__coords, UInt element, const ElementType & type, Matrix & shape_derivatives, const GhostType & ghost_type = _not_ghost) 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) { + __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 { + __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 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 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 { + virtual void assembleFieldLumped(__attribute__ ((unused)) const Array & field, + __attribute__ ((unused)) Array & lumped, + __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 { + __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(); } #ifdef AKANTU_STRUCTURAL_MECHANICS virtual void assembleFieldMatrix(__attribute__ ((unused)) const Array & field_1, - __attribute__ ((unused)) UInt nb_degree_of_freedom, - __attribute__ ((unused)) SparseMatrix & M, - __attribute__ ((unused)) Array * n, - __attribute__ ((unused)) ElementTypeMapArray & rotation_mat, - __attribute__ ((unused)) ElementType type, - __attribute__ ((unused)) const GhostType & ghost_type) const { + __attribute__ ((unused)) UInt nb_degree_of_freedom, + __attribute__ ((unused)) SparseMatrix & M, + __attribute__ ((unused)) Array * n, + __attribute__ ((unused)) ElementTypeMapArray & rotation_mat, + __attribute__ ((unused)) ElementType type, + __attribute__ ((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); } virtual void computeShapesMatrix(__attribute__ ((unused))const ElementType & type, - __attribute__ ((unused))UInt nb_degree_of_freedom, - __attribute__ ((unused))UInt nb_nodes_per_element, - __attribute__ ((unused))Array * n, - __attribute__ ((unused))UInt id, - __attribute__ ((unused))UInt degree_to_interpolate, - __attribute__ ((unused))UInt degree_interpolated, - __attribute__ ((unused))const bool sign, - __attribute__ ((unused))const GhostType & ghost_type) const { + __attribute__ ((unused))UInt nb_degree_of_freedom, + __attribute__ ((unused))UInt nb_nodes_per_element, + __attribute__ ((unused))Array * n, + __attribute__ ((unused))UInt id, + __attribute__ ((unused))UInt degree_to_interpolate, + __attribute__ ((unused))UInt degree_interpolated, + __attribute__ ((unused))const bool sign, + __attribute__ ((unused))const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); } #endif /// 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: /// get the dimension of the element handeled by this fe_engine object AKANTU_GET_MACRO(ElementDimension, element_dimension, UInt); /// get the mesh contained in the fem object AKANTU_GET_MACRO(Mesh, mesh, const Mesh &); /// get the mesh contained in the fem object AKANTU_GET_MACRO_NOT_CONST(Mesh, mesh, Mesh &); /// 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); /// get igfem element type for a given regular type static inline Vector getIGFEMElementTypes(const ElementType & type); /// get the interpolation element associated to an element type static inline InterpolationType getInterpolationType(const ElementType & el_type); virtual const ShapeFunctions & getShapeFunctionsInterface() const = 0; virtual const Integrator & getIntegratorInterface() const = 0; /* ------------------------------------------------------------------------ */ /* 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 ElementTypeMapArray normals_on_quad_points; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const FEEngine & _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 "fe_engine_inline_impl.cc" #include "fe_engine_template.hh" #endif /* __AKANTU_FE_ENGINE_HH__ */ diff --git a/src/model/boundary_condition_tmpl.hh b/src/model/boundary_condition_tmpl.hh index a00a6a4e7..f339ec171 100644 --- a/src/model/boundary_condition_tmpl.hh +++ b/src/model/boundary_condition_tmpl.hh @@ -1,265 +1,263 @@ /** * @file boundary_condition_tmpl.hh * * @author Dana Christen * @author Nicolas Richart * * @date creation: Fri May 03 2013 * @date last modification: Mon Jun 23 2014 * * @brief XXX * * @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 "element_group.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template void BoundaryCondition::initBC(ModelType & model, Array & primal, Array & dual) { this->model = &model; this->primal = &primal; this->dual = &dual; if(this->model->getSpatialDimension() > 1) this->model->initFEEngineBoundary(); } /* -------------------------------------------------------------------------- */ template void BoundaryCondition::initBC(ModelType & model, - Array & primal, - Array & primal_increment, - Array & dual) + Array & primal, + Array & primal_increment, + Array & dual) { this->initBC(model, primal, dual); this->primal_increment = &primal_increment; } /* -------------------------------------------------------------------------- */ /* Partial specialization for DIRICHLET functors */ template template struct BoundaryCondition::TemplateFunctionWrapper { static inline void applyBC(const FunctorType & func, const ElementGroup & group, BoundaryCondition & bc_instance) { ModelType & model = bc_instance.getModel(); Array & primal = bc_instance.getPrimal(); const Array & coords = model.getMesh().getNodes(); Array & boundary_flags = model.getBlockedDOFs(); UInt dim = model.getMesh().getSpatialDimension(); Array::vector_iterator primal_iter = primal.begin(primal.getNbComponent()); Array::const_vector_iterator coords_iter = coords.begin(dim); Array::vector_iterator flags_iter = boundary_flags.begin(boundary_flags.getNbComponent()); for(ElementGroup::const_node_iterator nodes_it(group.node_begin()); nodes_it!= group.node_end(); ++nodes_it) { UInt n = *nodes_it; Vector flag(flags_iter[n]); Vector primal(primal_iter[n]); Vector coords(coords_iter[n]); func(n, flag, primal, coords); } } }; /* -------------------------------------------------------------------------- */ /* Partial specialization for NEUMANN functors */ template template struct BoundaryCondition::TemplateFunctionWrapper { static inline void applyBC(const FunctorType & func, const ElementGroup & group, BoundaryCondition & bc_instance) { UInt dim = bc_instance.getModel().getSpatialDimension(); switch(dim) { case 1: { AKANTU_DEBUG_TO_IMPLEMENT(); break; } case 2: case 3: { applyBC(func, group, bc_instance, _not_ghost); applyBC(func, group, bc_instance, _ghost); break; } } } static inline void applyBC(const FunctorType & func, const ElementGroup & group, BoundaryCondition & bc_instance, GhostType ghost_type) { ModelType & model = bc_instance.getModel(); Array & dual = bc_instance.getDual(); const Mesh & mesh = model.getMesh(); const Array & nodes_coords = mesh.getNodes(); const FEEngine & fem_boundary = model.getFEEngineBoundary(); UInt dim = model.getSpatialDimension(); UInt nb_degree_of_freedom = dual.getNbComponent(); QuadraturePoint quad_point; quad_point.ghost_type = ghost_type; ElementGroup::type_iterator type_it = group.firstType(dim - 1, ghost_type); ElementGroup::type_iterator type_end = group.lastType (dim - 1, ghost_type); // Loop over the boundary element types for(; type_it != type_end; ++type_it) { const Array & element_ids = group.getElements(*type_it, ghost_type); Array::const_scalar_iterator elem_iter = element_ids.begin(); Array::const_scalar_iterator elem_iter_end = element_ids.end(); UInt nb_quad_points = fem_boundary.getNbQuadraturePoints(*type_it, ghost_type); UInt nb_elements = element_ids.getSize(); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*type_it); Array * dual_before_integ = new Array(nb_elements * nb_quad_points, - nb_degree_of_freedom, - 0.); + nb_degree_of_freedom, + 0.); Array * quad_coords = new Array(nb_elements * nb_quad_points, dim); const Array & normals_on_quad = - fem_boundary.getNormalsOnQuadPoints(*type_it, ghost_type); + fem_boundary.getNormalsOnQuadPoints(*type_it, ghost_type); fem_boundary.interpolateOnQuadraturePoints(nodes_coords, *quad_coords, - dim, - *type_it, ghost_type, - element_ids); + dim, + *type_it, ghost_type, + element_ids); Array::const_vector_iterator normals_begin = normals_on_quad.begin(dim); Array::const_vector_iterator normals_iter; Array::const_vector_iterator quad_coords_iter = quad_coords->begin(dim); Array::vector_iterator dual_iter = dual_before_integ->begin(nb_degree_of_freedom); quad_point.type = *type_it; for(; elem_iter != elem_iter_end; ++elem_iter) { UInt el = *elem_iter; quad_point.element = el; - normals_iter = normals_begin + el * nb_quad_points; + normals_iter = normals_begin + el * nb_quad_points; for(UInt q(0); q < nb_quad_points; ++q) { quad_point.num_point = q; func(quad_point, *dual_iter, *quad_coords_iter, *normals_iter); ++dual_iter; ++quad_coords_iter; ++normals_iter; } } delete quad_coords; /* -------------------------------------------------------------------- */ // Initialization of iterators Array::matrix_iterator dual_iter_mat = - dual_before_integ->begin(nb_degree_of_freedom,1); + dual_before_integ->begin(nb_degree_of_freedom,1); elem_iter = element_ids.begin(); Array::const_matrix_iterator shapes_iter_begin = - fem_boundary.getShapes(*type_it, ghost_type).begin(1, nb_nodes_per_element); + fem_boundary.getShapes(*type_it, ghost_type).begin(1, nb_nodes_per_element); Array * dual_by_shapes = - new Array(nb_elements*nb_quad_points, nb_degree_of_freedom*nb_nodes_per_element); + new Array(nb_elements*nb_quad_points, nb_degree_of_freedom*nb_nodes_per_element); Array::matrix_iterator dual_by_shapes_iter = - dual_by_shapes->begin(nb_degree_of_freedom, nb_nodes_per_element); + dual_by_shapes->begin(nb_degree_of_freedom, nb_nodes_per_element); Array::const_matrix_iterator shapes_iter; /* -------------------------------------------------------------------- */ // Loop computing dual x shapes for(; elem_iter != elem_iter_end; ++elem_iter) { - shapes_iter = shapes_iter_begin + *elem_iter*nb_quad_points; + shapes_iter = shapes_iter_begin + *elem_iter*nb_quad_points; for(UInt q(0); q < nb_quad_points; ++q, - ++dual_iter_mat, ++dual_by_shapes_iter, ++shapes_iter) { + ++dual_iter_mat, ++dual_by_shapes_iter, ++shapes_iter) { dual_by_shapes_iter->mul(*dual_iter_mat, *shapes_iter); } } delete dual_before_integ; Array * dual_by_shapes_integ = new Array(nb_elements, nb_degree_of_freedom*nb_nodes_per_element); fem_boundary.integrate(*dual_by_shapes, *dual_by_shapes_integ, nb_degree_of_freedom*nb_nodes_per_element, *type_it, ghost_type, element_ids); delete dual_by_shapes; // assemble the result into force vector - fem_boundary.assembleArray(*dual_by_shapes_integ, - dual, - model.getDOFSynchronizer().getLocalDOFEquationNumbers(), - nb_degree_of_freedom, - *type_it, - ghost_type, - element_ids); + model.getDOFManager().assembleElementalArrayLocalArray(*dual_by_shapes_integ, + dual, + *type_it, + ghost_type, + element_ids); delete dual_by_shapes_integ; } } }; /* -------------------------------------------------------------------------- */ template template inline void BoundaryCondition::applyBC(const FunctorType & func) { GroupManager::const_element_group_iterator bit = model->getMesh().getGroupManager().element_group_begin(); GroupManager::const_element_group_iterator bend = model->getMesh().getGroupManager().element_group_end(); for(; bit != bend; ++bit) applyBC(func, *bit); } /* -------------------------------------------------------------------------- */ template template inline void BoundaryCondition::applyBC(const FunctorType & func, - const std::string & group_name) { + const std::string & group_name) { try { const ElementGroup & element_group = model->getMesh().getElementGroup(group_name); applyBC(func, element_group); } catch(akantu::debug::Exception e) { AKANTU_EXCEPTION("Error applying a boundary condition onto \"" - << group_name << "\"! [" << e.what() <<"]"); + << group_name << "\"! [" << e.what() <<"]"); } } /* -------------------------------------------------------------------------- */ template template inline void BoundaryCondition::applyBC(const FunctorType & func, - const ElementGroup & element_group) { + const ElementGroup & element_group) { #if !defined(AKANTU_NDEBUG) if(element_group.getDimension() != model->getSpatialDimension() - 1) AKANTU_DEBUG_WARNING("The group " << element_group.getName() << " does not contain only boundaries elements"); #endif TemplateFunctionWrapper::applyBC(func, element_group, *this); } __END_AKANTU__ diff --git a/src/model/dof_manager.cc b/src/model/dof_manager.cc index 56681d818..2d3b33581 100644 --- a/src/model/dof_manager.cc +++ b/src/model/dof_manager.cc @@ -1,231 +1,244 @@ /** * @file dof_manager.cc * * @author Nicolas Richart * * @date Wed Aug 12 09:52:30 2015 * * @brief Implementation of the common parts of the DOFManagers * * @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 "dof_manager.hh" #include "mesh.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ DOFManager::DOFManager(const Mesh & mesh, const ID & id, const MemoryID & memory_id) : Memory(id, memory_id), mesh(mesh) {} /* -------------------------------------------------------------------------- */ DOFManager::~DOFManager() { DOFStorage::iterator ds_it = dofs.begin(); DOFStorage::iterator ds_end = dofs.end(); for (; ds_it != ds_end; ++ds_it) delete ds_it->second; SparseMatricesMap::iterator sm_it = matrices.begin(); SparseMatricesMap::iterator sm_end = matrices.end(); for (; sm_it != sm_end; ++sm_it) delete sm_it->second; NonLinearSolversMap::iterator nls_it = non_linear_solvers.begin(); NonLinearSolversMap::iterator nls_end = non_linear_solvers.end(); for (; nls_it != nls_end; ++nls_it) delete nls_it->second; TimeStepSolversMap::iterator tss_it = time_step_solvers.begin(); TimeStepSolversMap::iterator tss_end = time_step_solvers.end(); for (; tss_it != tss_end; ++tss_it) delete tss_it->second; } /* -------------------------------------------------------------------------- */ void DOFManager::assembleElementalArrayLocalArray( const Array & elementary_vect, Array & array_assembeled, const ElementType & type, const GhostType & ghost_type, Real scale_factor, const Array & filter_elements) { AKANTU_DEBUG_IN(); UInt nb_element; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_degree_of_freedom = elementary_vect.getNbComponent() / nb_nodes_per_element; UInt * filter_it = NULL; if (filter_elements != empty_filter) { nb_element = filter_elements.getSize(); filter_it = filter_elements.storage(); } else { nb_element = mesh.getNbElement(type, ghost_type); } AKANTU_DEBUG_ASSERT(elementary_vect.getSize() == nb_element, "The vector elementary_vect(" << elementary_vect.getID() << ") has not the good size."); const Array connectivity = this->mesh.getConnectivity(type, ghost_type); Array::const_vector_iterator conn_begin = connectivity.begin(nb_nodes_per_element); Array::const_vector_iterator conn_it = conn_begin; UInt size_mat = nb_nodes_per_element * nb_degree_of_freedom; Array::const_vector_iterator elem_it = elementary_vect.begin(size_mat); for (UInt el = 0; el < nb_element; ++el, ++elem_it) { if (filter_it != NULL) conn_it = conn_begin + *filter_it; for (UInt n = 0, ld = 0; n < nb_nodes_per_element; ++n) { UInt offset_node = (*conn_it)(n) * nb_degree_of_freedom; for (UInt d = 0; d < nb_degree_of_freedom; ++d, ++ld) { array_assembeled[offset_node + d] += scale_factor * (*elem_it)(ld); } } if (filter_it != NULL) ++filter_it; else ++conn_it; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void DOFManager::assembleElementalArrayResidual( const ID & dof_id, const Array & elementary_vect, const ElementType & type, const GhostType & ghost_type, Real scale_factor, const Array & filter_elements) { AKANTU_DEBUG_IN(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_degree_of_freedom = elementary_vect.getNbComponent() / nb_nodes_per_element; Array array_localy_assembeled(this->mesh.getNbNodes(), nb_degree_of_freedom); this->assembleElementalArrayLocalArray( elementary_vect, array_localy_assembeled, type, ghost_type, scale_factor, filter_elements); this->assembleToResidual(dof_id, array_localy_assembeled, scale_factor); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void DOFManager::registerDOFs(const ID & dof_id, Array & dofs_array, const DOFSupportType & support_type) { DOFStorage::iterator it = this->dofs.find(dof_id); if (it != this->dofs.end()) { AKANTU_EXCEPTION("This dof array has already been registered"); } DOFData * dofs_storage = new DOFData(); dofs_storage->dof = &dofs_array; dofs_storage->blocked_dofs = NULL; dofs_storage->support_type = support_type; switch (support_type) { case _dst_nodal: { UInt nb_local_dofs = mesh.getNbNodes(); AKANTU_DEBUG_ASSERT( dofs_array.getSize() == nb_local_dofs, "The array of dof is too shot to be associated to nodes."); UInt nb_nodes = this->mesh.getNbNodes(); UInt nb_pure_local = 0; for (UInt n = 0; n < nb_nodes; ++n) { nb_pure_local += mesh.isLocalOrMasterNode(n) ? 1 : 0; } nb_pure_local *= dofs_array.getNbComponent(); this->pure_local_system_size += nb_pure_local; this->system_size += this->mesh.getNbNodes() * dofs_array.getNbComponent(); nb_local_dofs *= dofs_array.getNbComponent(); this->local_system_size += nb_local_dofs; break; } default: { AKANTU_EXCEPTION("This type of dofs is not handled yet."); } } this->dofs[dof_id] = dofs_storage; } /* -------------------------------------------------------------------------- */ void DOFManager::registerDOFsDerivative(const ID & dof_id, UInt order, Array & dofs_derivative) { DOFStorage::iterator it = this->dofs.find(dof_id); if (it == this->dofs.end()) { AKANTU_EXCEPTION("The dof array corresponding to this derivatives has not " << "been registered yet"); } DOFData & dof = *it->second; std::vector *> & derivatives = dof.dof_derivatives; if (derivatives.size() < order) { derivatives.resize(order, NULL); } else { if (derivatives[order - 1] != NULL) { AKANTU_EXCEPTION("The dof derivatives of order " << order << " already been registered for this dof (" << dof_id << ")"); } } derivatives[order - 1] = &dofs_derivative; } /* -------------------------------------------------------------------------- */ void DOFManager::registerBlockedDOFs(const ID & dof_id, - Array & blocked_dofs) { + Array & blocked_dofs) { DOFStorage::iterator it = this->dofs.find(dof_id); if (it == this->dofs.end()) { AKANTU_EXCEPTION("The dof array corresponding to this derivatives has not " << "been registered yet"); } DOFData & dof = *it->second; if (dof.blocked_dofs != NULL) { AKANTU_EXCEPTION("The blocked dofs array for " << dof_id << " has already been registered"); } dof.blocked_dofs = &blocked_dofs; } /* -------------------------------------------------------------------------- */ +void DOFManager::splitSolutionPerDOFs() { + DOFStorage::iterator it = this->dofs.begin(); + DOFStorage::iterator end = this->dofs.end(); + + for (; it != end; ++it) { + DOFData & dof_data = *it->second; + this->getSolutionPerDOFs(it->first, *dof_data.solution); + } +} + + +/* -------------------------------------------------------------------------- */ + __END_AKANTU__ diff --git a/src/model/dof_manager.hh b/src/model/dof_manager.hh index 839dcf183..109d83abd 100644 --- a/src/model/dof_manager.hh +++ b/src/model/dof_manager.hh @@ -1,287 +1,304 @@ /** * @file dof_manager.hh * * @author Nicolas Richart * * @date Wed Jul 22 11:43:43 2015 * * @brief Class handling the different types of dofs * * @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_memory.hh" #include "non_linear_solver.hh" #include "time_step_solver.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_DOF_MANAGER_HH__ #define __AKANTU_DOF_MANAGER_HH__ namespace akantu { class NonLinearSolverCallback; class SparseMatrixAIJ; } __BEGIN_AKANTU__ class DOFManager : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: DOFManager(const Mesh & mesh, const ID & id = "dof_manager", const MemoryID & memory_id = 0); virtual ~DOFManager(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// register an array of degree of freedom void registerDOFs(const ID & dof_id, Array & dofs_array, const DOFSupportType & support_type); /// register an array of derivatives for a particular dof array void registerDOFsDerivative(const ID & dof_id, UInt order, Array & dofs_derivative); /// register array representing the blocked degree of freedoms - void registerBlockedDOFs(const ID & dof_id, Array & blocked_dofs); - - /// Get the part of the solution corresponding to the dof_id - virtual void getSolution(const ID & dof_id, Array & solution_array) = 0; + void registerBlockedDOFs(const ID & dof_id, Array & blocked_dofs); /// Assemble an array to the global residual array virtual void assembleToResidual(const ID & dof_id, const Array & array_to_assemble, Real scale_factor = 1.) = 0; /** * Assemble elementary values to a local array of the size nb_nodes * * nb_dof_per_node. The dof number is implicitly considered as * conn(el, n) * nb_nodes_per_element + d. * With 0 < n < nb_nodes_per_element and 0 < d < nb_dof_per_node **/ virtual void assembleElementalArrayLocalArray( const Array & elementary_vect, Array & array_assembeled, const ElementType & type, const GhostType & ghost_type, Real scale_factor = 1., const Array & filter_elements = empty_filter); /** * Assemble elementary values to the global residual array. The dof number is * implicitly considered as conn(el, n) * nb_nodes_per_element + d. * With 0 < n < nb_nodes_per_element and 0 < d < nb_dof_per_node **/ virtual void assembleElementalArrayResidual( const ID & dof_id, const Array & elementary_vect, const ElementType & type, const GhostType & ghost_type, Real scale_factor = 1., const Array & filter_elements = empty_filter); /** * Assemble elementary values to the global residual array. The dof number is * implicitly considered as conn(el, n) * nb_nodes_per_element + d. With 0 < * n < nb_nodes_per_element and 0 < d < nb_dof_per_node **/ virtual void assembleElementalMatricesToMatrix( const ID & matrix_id, const ID & dof_id, const Array & elementary_mat, const ElementType & type, const GhostType & ghost_type, const MatrixType & elemental_matrix_type = _symmetric, const Array & filter_elements = empty_filter) = 0; /// notation fully defined yet... // virtual void assemblePreassembledMatrix(const ID & matrix_id, // const ID & dof_id_m, // const ID & dof_id_n, // const Matrix & matrix) = 0; /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; protected: + /// splits the solution storage from a global view to the per dof storages + void splitSolutionPerDOFs(); + + /// minimum fonctionality to implement per derived version of the DOFManager + /// to allow the splitSolutionPerDOFs function to work + virtual void getSolutionPerDOFs(const ID & dof_id, + Array & solution_array) = 0; + /// fill a Vector with the equation numbers corresponding to the given /// connectivity inline void extractElementEquationNumber( const Array & equation_numbers, const Vector & connectivity, UInt nb_degree_of_freedom, Vector & local_equation_number); /// register a matrix void registerSparseMatrix(const ID & matrix_id, SparseMatrix & matrix); + /// register a time step solver instantiated by a derived class + void registerTimeStepSolver(const ID & time_step_solver_id, + TimeStepSolver & time_step_solver); + /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the equation numbers (in local numbering) corresponding to a dof ID Array & getLocalEquationNumbers(const ID & dof_id); /// get the equation numbers (in global numbering) corresponding to a dof ID Array & getGlobalEquationNumbers(const ID & dof_id); /// get the local equation number corresponding to the global equation number /// get the equation numbers (in local numbering) corresponding to a dof ID const Array & getLocalEquationNumbers(const ID & dof_id) const; /// get the equation numbers (in global numbering) corresponding to a dof ID const Array & getGlobalEquationNumbers(const ID & dof_id) const; /// Global number of dofs AKANTU_GET_MACRO(SystemSize, this->system_size, UInt); /// Local number of dofs AKANTU_GET_MACRO(LocalSystemSize, this->local_system_size, UInt); /// Get the solver callback stored in the dof_manager AKANTU_GET_MACRO(SolverCallback, *solver_callback, NonLinearSolverCallback &); /* ------------------------------------------------------------------------ */ /* DOFs and derivatives accessors */ /* ------------------------------------------------------------------------ */ /// Get a reference to the registered dof array for a given id - Array & getDOFs(ID & dofs_id); + Array & getDOFs(const ID & dofs_id); /// Get a reference to the registered dof derivatives array for a given id - Array & getDOFsDerivatives(ID & dofs_id, UInt order); + Array & getDOFsDerivatives(const ID & dofs_id, UInt order); - /// Get a reference to the blocked dofs array registered for the given id - Array & getBlockedDOFs(ID & dofs_id); + // /// Get a reference to the blocked dofs array registered for the given id + // Array & getBlockedDOFs(const ID & dofs_id); /// Get a reference to the blocked dofs array registered for the given id - const Array & getBlockedDOFs(ID & dofs_id) const; + const Array & getBlockedDOFs(const ID & dofs_id) const; /// Get a reference to the solution array registered for the given id - const Array & getSolution(ID & dofs_id) const; + const Array & getSolution(const ID & dofs_id) const; - /// Get a reference to the right hand side array registered for the given dof - /// id - const Array & getRHS() const; + // /// Get a reference to the right hand side array registered for the given + // dof + // /// id + // const Array & getRHS() const; /* ------------------------------------------------------------------------ */ /* Matrices accessors */ /* ------------------------------------------------------------------------ */ /// Get an instance of a new SparseMatrix virtual SparseMatrix & getNewMatrix(const ID & matrix_id, const MatrixType & matrix_type); /// Get an instance of a new SparseMatrix as a copy of the SparseMatrix /// matrix_to_copy_id virtual SparseMatrix & getNewMatrix(const ID & matrix_id, const ID & matrix_to_copy_id); /// Get the reference of an existing matrix SparseMatrixAIJ & getMatrix(const ID & matrix_id); /* ------------------------------------------------------------------------ */ /* Non linear system solver */ /* ------------------------------------------------------------------------ */ /// Get instance of a non linear solver virtual NonLinearSolver & getNewNonLinearSolver(const ID & nls_solver_id, const NonLinearSolverType & _non_linear_solver_type); /// get instance of a non linear solver virtual NonLinearSolver & getNonLinearSolver(const ID & nls_solver_id); /* ------------------------------------------------------------------------ */ /* TimeStepSolver */ /* ------------------------------------------------------------------------ */ /// Get instance of a time step solver virtual TimeStepSolver & - getNewTimeStepSolver(const ID & time_step_solver_id, UInt order, + getNewTimeStepSolver(const ID & time_step_solver_id, const ID & dof_id, const TimeStepSolverType & type); /// get instance of a time step solver virtual TimeStepSolver & getTimeStepSolver(const ID & time_step_solver_id); /* ------------------------------------------------------------------------*/ /* Class Members */ /* ------------------------------------------------------------------------*/ protected: /// dof representations in the dof manager struct DOFData { /// DOF support type (nodal, general) this is needed to determine how the /// dof are shared among processors DOFSupportType support_type; /// Degree of freedom array Array * dof; + /// Blocked degree of freedoms array - Array * blocked_dofs; + Array * blocked_dofs; + /// Solution associated to the dof Array * solution; /* ---------------------------------------------------------------------- */ /* data for dynamic simulations */ /* ---------------------------------------------------------------------- */ /// Degree of freedom derivatives arrays std::vector *> dof_derivatives; /// local numbering equation numbers Array local_equation_number; }; /// equation number in global numbering Array global_equation_number; + /// type to store dofs informations typedef std::map DOFStorage; + + /// type to store all the matrices typedef std::map SparseMatricesMap; + + /// type to store all the non linear solver typedef std::map NonLinearSolversMap; + + /// type to store all the time step solver typedef std::map TimeStepSolversMap; + /// store a reference to the dof arrays DOFStorage dofs; /// list of sparse matrices that where created SparseMatricesMap matrices; /// non linear solvers storage NonLinearSolversMap non_linear_solvers; /// time step solvers storage TimeStepSolversMap time_step_solvers; - /// Residual associated to the problem - Array residual; - /// reference to the underlying mesh const Mesh & mesh; /// Solver callback to assemble residual and Jacobian matrix NonLinearSolverCallback * solver_callback; /// Total number of degrees of freedom (size with the ghosts) UInt local_system_size; /// Number of purely local dofs (size without the ghosts) UInt pure_local_system_size; /// Total number of degrees of freedom UInt system_size; }; __END_AKANTU__ #include "dof_manager_inline_impl.cc" #endif /* __AKANTU_DOF_MANAGER_HH__ */ diff --git a/src/model/dof_manager_default.cc b/src/model/dof_manager_default.cc index 265d1ebe6..2cde8b29d 100644 --- a/src/model/dof_manager_default.cc +++ b/src/model/dof_manager_default.cc @@ -1,310 +1,326 @@ /** * @file dof_manager_default.cc * * @author Nicolas Richart * * @date Tue Aug 11 16:21:01 2015 * * @brief Implementation of the default DOFManager * * @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 "dof_manager_default.hh" #include "sparse_matrix_aij.hh" +#include "time_step_solver_default.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ inline void DOFManagerDefault::addSymmetricElementalMatrixToSymmetric( SparseMatrixAIJ & matrix, const Matrix & elementary_mat, const Vector & equation_numbers, UInt max_size) { for (UInt i = 0; i < elementary_mat.rows(); ++i) { UInt c_irn = equation_numbers(i); if (c_irn < max_size) { for (UInt j = i; j < elementary_mat.cols(); ++j) { UInt c_jcn = equation_numbers(j); if (c_jcn < max_size) { matrix(c_irn, c_jcn) += elementary_mat(i, j); } } } } } /* -------------------------------------------------------------------------- */ inline void DOFManagerDefault::addUnsymmetricElementalMatrixToSymmetric( SparseMatrixAIJ & matrix, const Matrix & elementary_mat, const Vector & equation_numbers, UInt max_size) { for (UInt i = 0; i < elementary_mat.rows(); ++i) { UInt c_irn = equation_numbers(i); if (c_irn < max_size) { for (UInt j = 0; j < elementary_mat.cols(); ++j) { UInt c_jcn = equation_numbers(j); if (c_jcn < max_size) { if (c_jcn >= c_irn) { matrix(c_irn, c_jcn) += elementary_mat(i, j); } } } } } } /* -------------------------------------------------------------------------- */ inline void DOFManagerDefault::addElementalMatrixToUnsymmetric( SparseMatrixAIJ & matrix, const Matrix & elementary_mat, const Vector & equation_numbers, UInt max_size) { for (UInt i = 0; i < elementary_mat.rows(); ++i) { UInt c_irn = equation_numbers(i); if (c_irn < max_size) { for (UInt j = 0; j < elementary_mat.cols(); ++j) { UInt c_jcn = equation_numbers(j); if (c_jcn < max_size) { matrix(c_irn, c_jcn) += elementary_mat(i, j); } } } } } +/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ DOFManagerDefault::DOFManagerDefault(const Mesh & mesh, const ID & id, const MemoryID & memory_id) : DOFManager(mesh, id, memory_id) {} /* -------------------------------------------------------------------------- */ -DOFManagerDefault::~DOFManagerDefault() { - -} +DOFManagerDefault::~DOFManagerDefault() {} /* -------------------------------------------------------------------------- */ void DOFManagerDefault::registerDOFs(const ID & dof_id, Array & dofs_array, DOFSupportType & support_type) { // stores the current numbers of dofs UInt local_nb_dofs = this->local_system_size; UInt pure_local_nb_dofs = this->pure_local_system_size; // update or create the dof_data DOFManager::registerDOFs(dof_id, dofs_array, support_type); // Count the number of pure local dofs per proc StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); UInt prank = comm.whoAmI(); UInt psize = comm.getNbProc(); Array nb_dofs_per_proc(psize); nb_dofs_per_proc(prank) = this->pure_local_system_size - pure_local_nb_dofs; comm.allGather(nb_dofs_per_proc); UInt first_global_dofs_id = std::accumulate( nb_dofs_per_proc.begin(), nb_dofs_per_proc.begin() + prank, 0); // nb local dofs to account for UInt nb_dofs = this->local_system_size - local_nb_dofs; DOFData & dof_data = *dofs[dof_id]; this->global_equation_number.resize(this->local_system_size); // set the equation numbers if (support_type == _dst_nodal) { UInt first_dof_id = local_nb_dofs; dof_data.local_equation_number.resize(nb_dofs); for (UInt d = 0; d < nb_dofs; ++d) { UInt local_eq_num = first_dof_id + d; dof_data.local_equation_number(d) = local_eq_num; this->global_equation_number(local_eq_num) = first_global_dofs_id + d; } } } /* -------------------------------------------------------------------------- */ SparseMatrix & DOFManagerDefault::getNewMatrix(const ID & matrix_id, const MatrixType & matrix_type) { std::stringstream sstr; sstr << this->id << ":" << matrix_id; SparseMatrix * sm = new SparseMatrixAIJ(*this, matrix_type, sstr.str(), this->memory_id); this->registerSparseMatrix(matrix_id, *sm); return *sm; } /* -------------------------------------------------------------------------- */ SparseMatrix & DOFManagerDefault::getNewMatrix(const ID & matrix_id, const ID & matrix_to_copy_id) { std::stringstream sstr; sstr << this->id << ":" << matrix_id; SparseMatrixAIJ & sm_to_copy = this->getMatrix(matrix_to_copy_id); SparseMatrix * sm = new SparseMatrixAIJ(sm_to_copy, sstr.str(), this->memory_id); this->registerSparseMatrix(matrix_id, *sm); return *sm; } /* -------------------------------------------------------------------------- */ SparseMatrixAIJ & DOFManagerDefault::getMatrix(const ID & matrix_id) { AIJMatrixMap::iterator it = this->aij_matrices.find(matrix_id); if (it == this->aij_matrices.end()) AKANTU_EXCEPTION("The matrix " << matrix_id << " does not exists in the DOFManager " << this->id); return *(it->second); } /* -------------------------------------------------------------------------- */ -void DOFManagerDefault::getSolution(const ID & dof_id, - Array & solution_array) { +TimeStepSolver & DOFManagerDefault::getNewTimeStepSolver( + const ID & dof_id, const ID & time_step_solver_id, + const TimeStepSolverType & time_step_solver_type) { + std::stringstream sstr; + sstr << this->id << ":" << time_step_solver_id; + + TimeStepSolver * tss = new TimeStepSolverDefault( + *this, dof_id, time_step_solver_type, sstr.str(), this->memory_id); + + this->registerTimeStepSolver(time_step_solver_id, *tss); + + return *tss; +} + +/* -------------------------------------------------------------------------- */ +void DOFManagerDefault::getSolutionPerDOFs(const ID & dof_id, + Array & solution_array) { AKANTU_DEBUG_IN(); const Array & equation_number = this->getLocalEquationNumbers(dof_id); UInt nb_degree_of_freedoms = solution_array.getSize() * solution_array.getNbComponent(); AKANTU_DEBUG_ASSERT( equation_number.getSize() == nb_degree_of_freedoms, "The array to get the solution does not have a correct size." << " (" << solution_array.getID() << ")"); Real * sol_it = solution_array.storage(); UInt * equ_it = equation_number.storage(); Array solution; for (UInt d = 0; d < nb_degree_of_freedoms; ++d, ++sol_it, ++equ_it) { (*sol_it) = solution(*equ_it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void DOFManagerDefault::assembleToResidual(const ID & dof_id, const Array & array_to_assemble, Real scale_factor) { AKANTU_DEBUG_IN(); const Array & equation_number = this->getLocalEquationNumbers(dof_id); UInt nb_degree_of_freedoms = array_to_assemble.getSize() * array_to_assemble.getNbComponent(); AKANTU_DEBUG_ASSERT(equation_number.getSize() == nb_degree_of_freedoms, "The array to assemble does not have a correct size." << " (" << array_to_assemble.getID() << ")"); Real * arr_it = array_to_assemble.storage(); UInt * equ_it = equation_number.storage(); for (UInt d = 0; d < nb_degree_of_freedoms; ++d, ++arr_it, ++equ_it) { residual(*equ_it) += scale_factor * (*arr_it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void DOFManagerDefault::assembleElementalMatricesToMatrix( const ID & matrix_id, const ID & dof_id, const Array & elementary_mat, const ElementType & type, const GhostType & ghost_type, const MatrixType & elemental_matrix_type, const Array & filter_elements) { AKANTU_DEBUG_IN(); const Array & equation_number = this->getLocalEquationNumbers(dof_id); SparseMatrixAIJ & A = this->getMatrix(matrix_id); UInt nb_element; if (ghost_type == _not_ghost) { nb_element = mesh.getNbElement(type); } else { AKANTU_DEBUG_TO_IMPLEMENT(); } UInt * filter_it = NULL; if (filter_elements != empty_filter) { nb_element = filter_elements.getSize(); filter_it = filter_elements.storage(); } else { nb_element = mesh.getNbElement(type, ghost_type); } AKANTU_DEBUG_ASSERT(elementary_mat.getSize() == nb_element, "The vector elementary_mat(" << elementary_mat.getID() << ") has not the good size."); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_degree_of_freedom = elementary_mat.getNbComponent() / (nb_nodes_per_element * nb_nodes_per_element); const Array connectivity = this->mesh.getConnectivity(type, ghost_type); Array::const_vector_iterator conn_begin = connectivity.begin(nb_nodes_per_element); Array::const_vector_iterator conn_it = conn_begin; UInt size_mat = nb_nodes_per_element * nb_degree_of_freedom; Vector local_eq_nb(nb_degree_of_freedom * nb_nodes_per_element); Array::const_matrix_iterator el_mat_it = elementary_mat.begin(size_mat, size_mat); for (UInt e = 0; e < nb_element; ++e, ++el_mat_it) { if (filter_it != NULL) conn_it = conn_begin + *filter_it; this->extractElementEquationNumber(equation_number, *conn_it, nb_degree_of_freedom, local_eq_nb); if (filter_it != NULL) ++filter_it; else ++conn_it; if (A.getMatrixType() == _symmetric) if (elemental_matrix_type == _symmetric) this->addSymmetricElementalMatrixToSymmetric(A, *el_mat_it, local_eq_nb, A.getSize()); else this->addUnsymmetricElementalMatrixToSymmetric( A, *el_mat_it, local_eq_nb, A.getSize()); else this->addElementalMatrixToUnsymmetric(A, *el_mat_it, local_eq_nb, A.getSize()); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/model/dof_manager_default.hh b/src/model/dof_manager_default.hh index f339d9f1d..b1b217e95 100644 --- a/src/model/dof_manager_default.hh +++ b/src/model/dof_manager_default.hh @@ -1,159 +1,174 @@ /** * @file dof_manager_default.hh * * @author Nicolas Richart * * @date Tue Aug 11 14:06:18 2015 * * @brief Default implementation of the dof manager * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "dof_manager.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_DOF_MANAGER_DEFAULT_HH__ #define __AKANTU_DOF_MANAGER_DEFAULT_HH__ namespace akantu { -class SparseMatrixAIJ; + class SparseMatrixAIJ; + class NonLinearSolverDefault; + class TimeStepSolverDefault; } __BEGIN_AKANTU__ class DOFManagerDefault : public DOFManager { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: DOFManagerDefault(const Mesh & mesh, const ID & id = "dof_manager_default", const MemoryID & memory_id = 0); virtual ~DOFManagerDefault(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// register an array of degree of freedom void registerDOFs(const ID & dof_id, Array & dofs_array, DOFSupportType & support_type); - /// Get the part of the solution corresponding to the dof_id - virtual void getSolution(const ID & dof_id, Array & solution_array); - /// Assemble an array to the global residual array virtual void assembleToResidual(const ID & dof_id, const Array & array_to_assemble, Real scale_factor = 1.); /** * Assemble elementary values to the global residual array. The dof number is * implicitly considered as conn(el, n) * nb_nodes_per_element + d. * With 0 < n < nb_nodes_per_element and 0 < d < nb_dof_per_node **/ virtual void assembleElementalArrayResidual( const ID & dof_id, const Array & array_to_assemble, const ElementType & type, const GhostType & ghost_type, Real scale_factor = 1.); /** * Assemble elementary values to the global matrix. The dof number is * implicitly considered as conn(el, n) * nb_nodes_per_element + d. * With 0 < n < nb_nodes_per_element and 0 < d < nb_dof_per_node **/ virtual void assembleElementalMatricesToMatrix( const ID & matrix_id, const ID & dof_id, const Array & elementary_mat, const ElementType & type, const GhostType & ghost_type, const MatrixType & elemental_matrix_type, const Array & filter_elements); +protected: + /// Get the part of the solution corresponding to the dof_id + virtual void getSolutionPerDOFs(const ID & dof_id, Array & solution_array); + + private: /// Add a symmetric matrices to a symmetric sparse matrix void addSymmetricElementalMatrixToSymmetric( SparseMatrixAIJ & matrix, const Matrix & element_mat, const Vector & equation_numbers, UInt max_size); /// Add a unsymmetric matrices to a symmetric sparse matrix (i.e. cohesive /// elements) void addUnsymmetricElementalMatrixToSymmetric( SparseMatrixAIJ & matrix, const Matrix & element_mat, const Vector & equation_numbers, UInt max_size); /// Add a matrices to a unsymmetric sparse matrix void addElementalMatrixToUnsymmetric(SparseMatrixAIJ & matrix, const Matrix & element_mat, const Vector & equation_numbers, UInt max_size); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// Get an instance of a new SparseMatrix virtual SparseMatrix & getNewMatrix(const ID & matrix_id, const MatrixType & matrix_type); /// Get an instance of a new SparseMatrix as a copy of the SparseMatrix /// matrix_to_copy_id virtual SparseMatrix & getNewMatrix(const ID & matrix_id, const ID & matrix_to_copy_id); /// Get the reference of an existing matrix SparseMatrixAIJ & getMatrix(const ID & matrix_id); + /*------------------------------------------------------------------------- */ + /// Get an instance of a time step solver + virtual TimeStepSolver & + getNewTimeStepSolver(const ID & time_step_solver, const ID & dof_id, + const TimeStepSolverType & time_step_solver_type); + + /* ------------------------------------------------------------------------ */ /// Get the solution array - AKANTU_GET_MACRO_NOT_CONST(Solution, solution, Array &); + AKANTU_GET_MACRO_NOT_CONST(GlobalSolution, global_solution, Array &); /// Get the residual array AKANTU_GET_MACRO_NOT_CONST(Residual, residual, Array &); /// Get the blocked dofs array - AKANTU_GET_MACRO(BlockedDOFs, blocked_dofs, const Array &); - + AKANTU_GET_MACRO(GlobalBlockedDOFs, global_blocked_dofs, const Array &); bool isLocalOrMasterDOF(UInt dof_num); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: typedef std::map AIJMatrixMap; + typedef std::map DefaultNonLinearSolversMap; + typedef std::map DefaultTimeStepSolversMap; /// rhs to the system of equation corresponding to the residual linked to the /// different dofs Array residual; /// solution of the system of equation corresponding to the different dofs - Array solution; + Array global_solution; /// blocked degree of freedom in the system equation corresponding to the /// different dofs - Array blocked_dofs; + Array global_blocked_dofs; /// define the dofs type, local, shared, ghost Array dofs_type; /// Map of the different matrices stored in the dof manager AIJMatrixMap aij_matrices; + + /// Map of the different time step solvers stored with there real type + DefaultTimeStepSolversMap default_time_step_solver_map; }; __END_AKANTU__ #include "dof_manager_default_inline_impl.cc" #endif /* __AKANTU_DOF_MANAGER_DEFAULT_HH__ */ diff --git a/src/model/dof_manager_petsc.cc b/src/model/dof_manager_petsc.cc index 9e2b5e853..7f5f2e780 100644 --- a/src/model/dof_manager_petsc.cc +++ b/src/model/dof_manager_petsc.cc @@ -1,327 +1,396 @@ /** * @file dof_manager_petsc.cc * * @author Nicolas Richart * * @date Mon Oct 5 21:19:58 2015 * * @brief DOFManaterPETSc is the PETSc implementation of the DOFManager * * @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 "dof_manager_petsc.hh" #include "cppargparse.hh" #if defined(AKANTU_USE_MPI) -# include "static_communicator.hh" -# include "mpi_type_wrapper.hh" +#include "static_communicator.hh" +#include "mpi_type_wrapper.hh" #endif /* -------------------------------------------------------------------------- */ +#include +/* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ +#if not defined(PETSC_CLANGUAGE_CXX) +/// small hack to use the c binding of petsc when the cxx binding does notation +/// exists +int aka_PETScError(int ierr) { + CHKERRQ(ierr); + return 0; +} +#endif + UInt DOFManagerPETSc::petsc_dof_manager_instances = 0; +/// Error handler to make PETSc errors caught by Akantu #if PETSC_VERSION_MAJOR >= 3 && PETSC_VERSION_MINOR >= 5 static PetscErrorCode PETScErrorHandler(MPI_Comm, int line, const char * dir, const char * file, PetscErrorCode number, PetscErrorType type, const char * message, void *) { AKANTU_DEBUG_ERROR("An error occured in PETSc in file \"" << file << ":" << line << "\" - PetscErrorCode " << number << " - \"" << message << "\""); } #else static PetscErrorCode PETScErrorHandler(MPI_Comm, int line, const char * func, const char * dir, const char * file, PetscErrorCode number, PetscErrorType type, const char * message, void *) { AKANTU_DEBUG_ERROR("An error occured in PETSc in file \"" << file << ":" << line << "\" - PetscErrorCode " << number << " - \"" << message << "\""); } #endif /* -------------------------------------------------------------------------- */ DOFManagerPETSc::DOFManagerPETSc(const Mesh & mesh, const ID & id, const MemoryID & memory_id) : DOFManager(mesh, id, memory_id) { +// check if the akantu types and PETSc one are consistant +#if __cplusplus > 199711L + static_assert(sizeof(Int) == sizeof(PetscInt), + "The integer type of Akantu does not match the one from PETSc"); + static_assert(sizeof(Real) == sizeof(PetscReal), + "The integer type of Akantu does not match the one from PETSc"); +#else + AKANTU_DEBUG_ASSERT( + sizeof(Int) == sizeof(PetscInt), + "The integer type of Akantu does not match the one from PETSc"); + AKANTU_DEBUG_ASSERT( + sizeof(Real) == sizeof(PetscReal), + "The integer type of Akantu does not match the one from PETSc"); +#endif + if (this->petsc_dof_manager_instances == 0) { #if defined(AKANTU_USE_MPI) StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); const StaticCommunicatorMPI & mpi_st_comm = dynamic_cast( comm.getRealStaticCommunicator()); this->communicator = mpi_st_comm.getMPITypeWrapper().getMPICommunicator(); #else this->communicator = PETSC_COMM_SELF; #endif cppargparse::ArgumentParser & argparser = getStaticArgumentParser(); int & argc = argparser.getARGC(); char **& argv = argparser.getARGV(); PetscErrorCode petsc_error = PetscInitialize(&argc, &argv, NULL, NULL); - if(petsc_error != 0) { - AKANTU_DEBUG_ERROR("An error occured while initializing Petsc (PetscErrorCode "<< petsc_error << ")"); + if (petsc_error != 0) { + AKANTU_DEBUG_ERROR( + "An error occured while initializing Petsc (PetscErrorCode " + << petsc_error << ")"); } PetscPushErrorHandler(PETScErrorHandler, NULL); this->petsc_dof_manager_instances++; } VecCreate(PETSC_COMM_WORLD, &this->residual); VecCreate(PETSC_COMM_WORLD, &this->solution); } /* -------------------------------------------------------------------------- */ DOFManagerPETSc::~DOFManagerPETSc() { PetscErrorCode ierr; ierr = VecDestroy(&(this->residual)); CHKERRXX(ierr); ierr = VecDestroy(&(this->solution)); CHKERRXX(ierr); this->petsc_dof_manager_instances--; - if(this->petsc_dof_manager_instances == 0) { + if (this->petsc_dof_manager_instances == 0) { PetscFinalize(); } } /* -------------------------------------------------------------------------- */ -void DOFManagerPETSc::registerDOFs(const ID & dof_id, - Array & dofs_array, +void DOFManagerPETSc::registerDOFs(const ID & dof_id, Array & dofs_array, DOFSupportType & support_type) { DOFManager::registerDOFs(dof_id, dofs_array, support_type); PetscErrorCode ierr; - ierr = VecSetSizes(this->residual, this->local_system_size, PETSC_DECIDE); - CHKERRXX(ierr); - ierr = VecSetFromOptions(this->residual); + PetscInt current_size; + ierr = VecGetSize(this->residual, ¤t_size); CHKERRXX(ierr); - ierr = VecDuplicate(this->residual, &this->solution); - CHKERRXX(ierr); + if (current_size == 0) { // first time vector is set + PetscInt local_size = this->pure_local_system_size; + ierr = VecSetSizes(this->residual, local_size, PETSC_DECIDE); + CHKERRXX(ierr); + + ierr = VecSetFromOptions(this->residual); + CHKERRXX(ierr); + +#ifndef AKANTU_NDEBUG + PetscInt global_size; + ierr = VecGetSize(this->residual, &global_size); + CHKERRXX(ierr); + AKANTU_DEBUG_ASSERT(this->system_size == UInt(global_size), + "The local value of the system size does not match the " + "one determined by PETSc"); +#endif + PetscInt start_dof, end_dof; + VecGetOwnershipRange(this->residual, &start_dof, &end_dof); + + PetscInt * global_indices = new PetscInt[local_size]; + global_indices[0] = start_dof; + + for (PetscInt d = 0; d < local_size; d++) + global_indices[d + 1] = global_indices[d] + 1; + +// To be change if we switch to a block definition +#if PETSC_VERSION_MAJOR >= 3 && PETSC_VERSION_MINOR >= 5 + ISLocalToGlobalMappingCreate(this->communicator, 1, local_size, + global_indices, PETSC_COPY_VALUES, + &this->is_ltog); + +#else + ISLocalToGlobalMappingCreate(this->communicator, local_size, global_indices, + PETSC_COPY_VALUES, &this->is_ltog); +#endif + + VecSetLocalToGlobalMapping(this->residual, this->is_ltog); + delete[] global_indices; + + ierr = VecDuplicate(this->residual, &this->solution); + CHKERRXX(ierr); + + } else { // this is an update of the object already created + AKANTU_DEBUG_TO_IMPLEMENT(); + } /// set the solution to zero - ierr = VecZeroEntries(this->solution); - CHKERRXX(ierr); + // ierr = VecZeroEntries(this->solution); + // CHKERRXX(ierr); } /* -------------------------------------------------------------------------- */ - /** * This function creates the non-zero pattern of the PETSc matrix. In * PETSc the parallel matrix is partitioned across processors such * that the first m0 rows belong to process 0, the next m1 rows belong * to process 1, the next m2 rows belong to process 2 etc.. where * m0,m1,m2,.. are the input parameter 'm'. i.e each processor stores * values corresponding to [m x N] submatrix * (http://www.mcs.anl.gov/petsc/). * @param mesh mesh discretizing the domain we want to analyze * @param dof_synchronizer dof synchronizer that maps the local * dofs to the global dofs and the equation numbers, i.e., the * position at which the dof is assembled in the matrix */ // void SparseMatrixPETSc::buildProfile(const Mesh & mesh, // const DOFSynchronizer & // dof_synchronizer, // UInt nb_degree_of_freedom) { // AKANTU_DEBUG_IN(); // // clearProfile(); // this->dof_synchronizer = &const_cast(dof_synchronizer); // this->setSize(); // PetscErrorCode ierr; // /// resize arrays to store the number of nonzeros in each row // this->d_nnz.resize(this->local_size); // this->o_nnz.resize(this->local_size); // /// set arrays to zero everywhere // this->d_nnz.set(0); // this->o_nnz.set(0); // // if(irn_jcn_to_k) delete irn_jcn_to_k; // // irn_jcn_to_k = new std::map, UInt>; // coordinate_list_map::iterator irn_jcn_k_it; // Int * eq_nb_val = dof_synchronizer.getGlobalDOFEquationNumbers().storage(); // UInt nb_global_dofs = dof_synchronizer.getNbGlobalDOFs(); // Array index_pair(2); // /// Loop over all the ghost types // for (ghost_type_t::iterator gt = ghost_type_t::begin(); // gt != ghost_type_t::end(); ++gt) { // const GhostType & ghost_type = *gt; // Mesh::type_iterator it = // mesh.firstType(mesh.getSpatialDimension(), ghost_type, // _ek_not_defined); // Mesh::type_iterator end = // mesh.lastType(mesh.getSpatialDimension(), ghost_type, // _ek_not_defined); // for (; it != end; ++it) { // UInt nb_element = mesh.getNbElement(*it, ghost_type); // UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); // UInt size_mat = nb_nodes_per_element * nb_degree_of_freedom; // UInt * conn_val = mesh.getConnectivity(*it, ghost_type).storage(); // Int * local_eq_nb_val = // new Int[nb_degree_of_freedom * nb_nodes_per_element]; // for (UInt e = 0; e < nb_element; ++e) { // Int * tmp_local_eq_nb_val = local_eq_nb_val; // for (UInt i = 0; i < nb_nodes_per_element; ++i) { // UInt n = conn_val[i]; // for (UInt d = 0; d < nb_degree_of_freedom; ++d) { // /** // * !!!!!!Careful!!!!!! This is a ugly fix. @todo this is a // * very ugly fix, because the offset for the global // * equation number, where the dof will be assembled, is // * hardcoded. In the future a class dof manager has to be // * added to Akantu to handle the mapping between the dofs // * and the equation numbers // * // */ // *tmp_local_eq_nb_val++ = // eq_nb_val[n * nb_degree_of_freedom + d] - // (dof_synchronizer.isPureGhostDOF(n * nb_degree_of_freedom + // d) // ? nb_global_dofs // : 0); // } // } // for (UInt i = 0; i < size_mat; ++i) { // Int c_irn = local_eq_nb_val[i]; // UInt j_start = 0; // for (UInt j = j_start; j < size_mat; ++j) { // Int c_jcn = local_eq_nb_val[j]; // index_pair(0) = c_irn; // index_pair(1) = c_jcn; // AOApplicationToPetsc(this->petsc_matrix_wrapper->ao, 2, // index_pair.storage()); // if (index_pair(0) >= first_global_index && // index_pair(0) < first_global_index + this->local_size) { // KeyCOO irn_jcn = keyPETSc(c_irn, c_jcn); // irn_jcn_k_it = irn_jcn_k.find(irn_jcn); // if (irn_jcn_k_it == irn_jcn_k.end()) { // irn_jcn_k[irn_jcn] = nb_non_zero; // // check if node is slave node // if (index_pair(1) >= first_global_index && // index_pair(1) < first_global_index + this->local_size) // this->d_nnz(index_pair(0) - first_global_index) += 1; // else // this->o_nnz(index_pair(0) - first_global_index) += 1; // nb_non_zero++; // } // } // } // } // conn_val += nb_nodes_per_element; // } // delete[] local_eq_nb_val; // } // } // // /// for pbc @todo correct it for parallel // // if(StaticCommunicator::getStaticCommunicator().getNbProc() == 1) { // // for (UInt i = 0; i < size; ++i) { // // KeyCOO irn_jcn = key(i, i); // // irn_jcn_k_it = irn_jcn_k.find(irn_jcn); // // if(irn_jcn_k_it == irn_jcn_k.end()) { // // irn_jcn_k[irn_jcn] = nb_non_zero; // // irn.push_back(i + 1); // // jcn.push_back(i + 1); // // nb_non_zero++; // // } // // } // // } // // std::string mat_type; // // mat_type.resize(20, 'a'); // // std::cout << "MatType: " << mat_type << std::endl; // // const char * mat_type_ptr = mat_type.c_str(); // MatType type; // MatGetType(this->petsc_matrix_wrapper->mat, &type); // /// std::cout << "the matrix type is: " << type << std::endl; // /** // * PETSc will use only one of the following preallocation commands // * depending on the matrix type and ignore the rest. Note that for // * the block matrix format a block size of 1 is used. This might // * result in bad performance. @todo For better results implement // * buildProfile() with larger block size. // * // */ // /// build profile: // if (strcmp(type, MATSEQAIJ) == 0) { // ierr = MatSeqAIJSetPreallocation(this->petsc_matrix_wrapper->mat, 0, // d_nnz.storage()); // CHKERRXX(ierr); // } else if ((strcmp(type, MATMPIAIJ) == 0)) { // ierr = MatMPIAIJSetPreallocation(this->petsc_matrix_wrapper->mat, 0, // d_nnz.storage(), 0, o_nnz.storage()); // CHKERRXX(ierr); // } else { // AKANTU_DEBUG_ERROR("The type " << type // << " of PETSc matrix is not handled by" // << " akantu in the preallocation step"); // } // // ierr = MatSeqSBAIJSetPreallocation(this->petsc_matrix_wrapper->mat, 1, // // 0, d_nnz.storage()); CHKERRXX(ierr); // if (this->sparse_matrix_type == _symmetric) { // /// set flag for symmetry to enable ICC/Cholesky preconditioner // ierr = MatSetOption(this->petsc_matrix_wrapper->mat, MAT_SYMMETRIC, // PETSC_TRUE); // CHKERRXX(ierr); // /// set flag for symmetric positive definite // ierr = MatSetOption(this->petsc_matrix_wrapper->mat, MAT_SPD, // PETSC_TRUE); // CHKERRXX(ierr); // } // /// once the profile has been build ignore any new nonzero locations // ierr = MatSetOption(this->petsc_matrix_wrapper->mat, // MAT_NEW_NONZERO_LOCATIONS, PETSC_TRUE); // CHKERRXX(ierr); // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/model/dof_manager_petsc.hh b/src/model/dof_manager_petsc.hh index bcf13a1ef..b5937c71a 100644 --- a/src/model/dof_manager_petsc.hh +++ b/src/model/dof_manager_petsc.hh @@ -1,152 +1,169 @@ /** * @file dof_manager_petsc.hh * * @author Nicolas Richart * * @date Tue Aug 11 14:06:18 2015 * * @brief PETSc implementation of the dof manager * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "dof_manager.hh" /* -------------------------------------------------------------------------- */ #include +#include /* -------------------------------------------------------------------------- */ +#if not defined(PETSC_CLANGUAGE_CXX) +extern int aka_PETScError(int ierr); + +#define CHKERRXX(x) \ + do { \ + int error = aka_PETScError(x); \ + if (error != 0) { \ + AKANTU_EXCEPTION("Error in PETSC"); \ + } \ + } while (0) +#endif + #ifndef __AKANTU_DOF_MANAGER_PETSC_HH__ #define __AKANTU_DOF_MANAGER_PETSC_HH__ __BEGIN_AKANTU__ class SparseMatrixPETSc; class DOFManagerPETSc : public DOFManager { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: DOFManagerPETSc(const Mesh & mesh, const ID & id = "dof_manager_petsc", const MemoryID & memory_id = 0); virtual ~DOFManagerPETSc(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// register an array of degree of freedom void registerDOFs(const ID & dof_id, Array & dofs_array, DOFSupportType & support_type); - /// Get the part of the solution corresponding to the dof_id - virtual void getSolution(const ID & dof_id, Array & solution_array); - /// Assemble an array to the global residual array virtual void assembleToResidual(const ID & dof_id, const Array & array_to_assemble, Real scale_factor = 1.); /** * Assemble elementary values to the global residual array. The dof number is * implicitly considered as conn(el, n) * nb_nodes_per_element + d. * With 0 < n < nb_nodes_per_element and 0 < d < nb_dof_per_node **/ virtual void assembleElementalArrayResidual( const ID & dof_id, const Array & array_to_assemble, const ElementType & type, const GhostType & ghost_type, Real scale_factor = 1.); /** * Assemble elementary values to the global residual array. The dof number is * implicitly considered as conn(el, n) * nb_nodes_per_element + d. * With 0 < n < nb_nodes_per_element and 0 < d < nb_dof_per_node **/ virtual void assembleElementalMatricesToMatrix( const ID & matrix_id, const ID & dof_id, const Array & elementary_mat, const ElementType & type, const GhostType & ghost_type, const MatrixType & elemental_matrix_type, const Array & filter_elements); +protected: + /// Get the part of the solution corresponding to the dof_id + virtual void getSolutionPerDOFs(const ID & dof_id, Array & solution_array); + private: /// Add a symmetric matrices to a symmetric sparse matrix inline void addSymmetricElementalMatrixToSymmetric( SparseMatrixAIJ & matrix, const Matrix & element_mat, const Vector & equation_numbers, UInt max_size); /// Add a unsymmetric matrices to a symmetric sparse matrix (i.e. cohesive /// elements) inline void addUnsymmetricElementalMatrixToSymmetric( SparseMatrixAIJ & matrix, const Matrix & element_mat, const Vector & equation_numbers, UInt max_size); /// Add a matrices to a unsymmetric sparse matrix inline void addElementalMatrixToUnsymmetric( SparseMatrixAIJ & matrix, const Matrix & element_mat, const Vector & equation_numbers, UInt max_size); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// Get an instance of a new SparseMatrix virtual SparseMatrix & getNewMatrix(const ID & matrix_id, const MatrixType & matrix_type); /// Get an instance of a new SparseMatrix as a copy of the SparseMatrix /// matrix_to_copy_id virtual SparseMatrix & getNewMatrix(const ID & matrix_id, const ID & matrix_to_copy_id); /// Get the reference of an existing matrix SparseMatrixPETSc & getMatrix(const ID & matrix_id); /// Get the solution array - AKANTU_GET_MACRO_NOT_CONST(Solution, solution, Vec &); + AKANTU_GET_MACRO_NOT_CONST(GlobalSolution, this->solution, Vec &); /// Get the residual array - AKANTU_GET_MACRO_NOT_CONST(Residual, residual, Vec &); + AKANTU_GET_MACRO_NOT_CONST(Residual, this->residual, Vec &); /// Get the blocked dofs array // AKANTU_GET_MACRO(BlockedDOFs, blocked_dofs, const Array &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: typedef std::map PETScMatrixMap; /// list of matrices registered to the dof manager PETScMatrixMap petsc_matrices; /// PETSc version of the solution Vec solution; /// PETSc version of the residual Vec residual; + /// PETSc local to global mapping of dofs + ISLocalToGlobalMapping is_ltog; + /// Communicator associated to PETSc MPI_Comm communicator; /// Static handler for petsc to know if it was initialized or not static UInt petsc_dof_manager_instances; }; __END_AKANTU__ #endif /* __AKANTU_DOF_MANAGER_PETSC_HH__ */ diff --git a/src/model/integration_scheme/newmark-beta.hh b/src/model/integration_scheme/newmark-beta.hh index 9baf8e468..5bc9f6875 100644 --- a/src/model/integration_scheme/newmark-beta.hh +++ b/src/model/integration_scheme/newmark-beta.hh @@ -1,188 +1,200 @@ /** * @file newmark-beta.hh * * @author David Simon Kammer * @author Nicolas Richart * * @date creation: Tue Oct 05 2010 * @date last modification: Thu Jun 05 2014 * * @brief implementation of the newmark-@f$\beta@f$ integration scheme. This * implementation is taken from Méthodes numériques en mécanique des solides by * Alain Curnier \note{ISBN: 2-88074-247-1} * * @section LICENSE * * Copyright (©) 2010-2012, 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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NEWMARK_BETA_HH__ #define __AKANTU_NEWMARK_BETA_HH__ /* -------------------------------------------------------------------------- */ #include "integration_scheme_2nd_order.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /** * The three differentiate equations (dynamic and cinematic) are : * @f{eqnarray*}{ * M \ddot{u}_{n+1} + C \dot{u}_{n+1} + K u_{n+1} &=& q_{n+1} \\ * u_{n+1} &=& u_{n} + (1 - \alpha) \Delta t \dot{u}_{n} + \alpha \Delta t *\dot{u}_{n+1} + (1/2 - \alpha) \Delta t^2 \ddot{u}_n \\ * \dot{u}_{n+1} &=& \dot{u}_{n} + (1 - \beta) \Delta t \ddot{u}_{n} + \beta *\Delta t \ddot{u}_{n+1} * @f} * * Predictor: * @f{eqnarray*}{ * u^{0}_{n+1} &=& u_{n} + \Delta t \dot{u}_n + \frac{\Delta t^2}{2} *\ddot{u}_n \\ * \dot{u}^{0}_{n+1} &=& \dot{u}_{n} + \Delta t \ddot{u}_{n} \\ * \ddot{u}^{0}_{n+1} &=& \ddot{u}_{n} * @f} * * Solve : * @f[ (c M + d C + e K^i_{n+1}) w = = q_{n+1} - f^i_{n+1} - C \dot{u}^i_{n+1} *- M \ddot{u}^i_{n+1} @f] * * Corrector : * @f{eqnarray*}{ * \ddot{u}^{i+1}_{n+1} &=& \ddot{u}^{i}_{n+1} + c w \\ * \dot{u}^{i+1}_{n+1} &=& \dot{u}^{i}_{n+1} + d w \\ * u^{i+1}_{n+1} &=& u^{i}_{n+1} + e w * @f} * * c, d and e are parameters depending on the method used to solve the equations *@n * For acceleration : @f$ w = \delta \ddot{u}, e = \alpha \beta \Delta t^2, d = *\beta \Delta t, c = 1 @f$ @n * For velocity : @f$ w = \delta \dot{u}, e = 1/\beta \Delta t, d = *1, c = \alpha \Delta t @f$ @n * For displacement : @f$ w = \delta u, e = 1, d = *1/\alpha \Delta t, c = 1/\alpha \beta \Delta t^2 @f$ */ class NewmarkBeta : public IntegrationScheme2ndOrder { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NewmarkBeta(Real alpha, Real beta) : beta(beta), alpha(alpha), k(0.), h(0.){}; ~NewmarkBeta(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: inline void integrationSchemePred(Real delta_t, Array & u, Array & u_dot, Array & u_dot_dot, const Array & blocked_dofs) const; inline void integrationSchemeCorrAccel(Real delta_t, Array & u, Array & u_dot, Array & u_dot_dot, const Array & blocked_dofs, const Array & delta) const; inline void integrationSchemeCorrVeloc(Real delta_t, Array & u, Array & u_dot, Array & u_dot_dot, const Array & blocked_dofs, const Array & delta) const; inline void integrationSchemeCorrDispl(Real delta_t, Array & u, Array & u_dot, Array & u_dot_dot, const Array & blocked_dofs, const Array & delta) const; public: template Real getAccelerationCoefficient(Real delta_t) const; template Real getVelocityCoefficient(Real delta_t) const; template Real getDisplacementCoefficient(Real delta_t) const; private: template void integrationSchemeCorr(Real delta_t, Array & u, Array & u_dot, Array & u_dot_dot, const Array & blocked_dofs, const Array & delta) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(Beta, beta, Real); AKANTU_GET_MACRO(Alpha, alpha, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the @f$\beta@f$ parameter const Real beta; /// the @f$\alpha@f$ parameter const Real alpha; const Real k; const Real h; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined(AKANTU_INCLUDE_INLINE_IMPL) #include "newmark-beta_inline_impl.cc" #endif /** * central difference method (explicit) * undamped stability condition : * @f$ \Delta t = \alpha \Delta t_{crit} = \frac{2}{\omega_{max}} \leq \min_{e} *\frac{l_e}{c_e} * */ class CentralDifference : public NewmarkBeta { public: - CentralDifference() : NewmarkBeta(0., .5){}; + CentralDifference() : NewmarkBeta(0., 1./2.){}; }; //#include "integration_scheme/central_difference.hh" /// undamped trapezoidal rule (implicit) class TrapezoidalRule2 : public NewmarkBeta { public: - TrapezoidalRule2() : NewmarkBeta(.5, .5){}; + TrapezoidalRule2() : NewmarkBeta(1./2., 1./2.){}; +}; + +/// Fox-Goodwin rule (implicit) +class FoxGoodwin : public NewmarkBeta { +public: + FoxGoodwin() : NewmarkBeta(1./6., 1./2.){}; +}; + +/// Linear acceleration (implicit) +class LinearAceleration : public NewmarkBeta { +public: + LinearAceleration() : NewmarkBeta(1./3., 1./2.){}; }; __END_AKANTU__ #endif /* __AKANTU_NEWMARK_BETA_HH__ */ diff --git a/src/model/model.cc b/src/model/model.cc index d01ae12b8..075feff51 100644 --- a/src/model/model.cc +++ b/src/model/model.cc @@ -1,398 +1,394 @@ /** * @file model.cc * * @author Guillaume Anciaux * @author David Simon Kammer * @author Nicolas Richart * * @date creation: Mon Oct 03 2011 * @date last modification: Fri Sep 05 2014 * * @brief implementation of model common parts * * @section LICENSE * * Copyright (©) 2010-2012, 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 "model.hh" #include "element_group.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Model::Model(Mesh& mesh, UInt dim, const ID & id, - const MemoryID & memory_id) : - Memory(id, memory_id), ModelSolver(mesh, id), + const MemoryID & memory_id) : + Memory(id, memory_id), ModelSolver(mesh, id, memory_id), mesh(mesh), spatial_dimension(dim == _all_dimensions ? mesh.getSpatialDimension() : dim), synch_registry(NULL), - dof_synchronizer(NULL), is_pbc_slave_node(0,1,"is_pbc_slave_node") , parser(&getStaticParser()) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Model::~Model() { AKANTU_DEBUG_IN(); FEEngineMap::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::setParser(Parser & parser){ this->parser = &parser; } /* -------------------------------------------------------------------------- */ void Model::initFull(const ModelOptions & options) { AKANTU_DEBUG_IN(); 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.computeBoundingBox(); if (x) MeshUtils::computePBCMap(this->mesh, 0, this->pbc_pair); if (y) MeshUtils::computePBCMap(this->mesh, 1, this->pbc_pair); if (z) MeshUtils::computePBCMap(this->mesh, 2, this->pbc_pair); } /* -------------------------------------------------------------------------- */ void Model::setPBC(SurfacePairList & surface_pairs){ SurfacePairList::iterator s_it; for(s_it = surface_pairs.begin(); s_it != surface_pairs.end(); ++s_it) { MeshUtils::computePBCMap(this->mesh, *s_it, this->pbc_pair); } } /* -------------------------------------------------------------------------- */ void Model::initPBC() { 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(getFEEngine().getMesh(), partition); else synch = DistributedSynchronizer::createDistributedSynchronizerMesh(getFEEngine().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(); } /* -------------------------------------------------------------------------- */ // DUMPER stuff /* -------------------------------------------------------------------------- */ void Model::addDumpGroupFieldToDumper(const std::string & field_id, dumper::Field * field, DumperIOHelper & dumper) { #ifdef AKANTU_USE_IOHELPER dumper.registerField(field_id,field); #endif } /* -------------------------------------------------------------------------- */ void Model::addDumpField(const std::string & field_id) { this->addDumpFieldToDumper(mesh.getDefaultDumperName(),field_id); } /* -------------------------------------------------------------------------- */ void Model::addDumpFieldVector(const std::string & field_id) { this->addDumpFieldVectorToDumper(mesh.getDefaultDumperName(),field_id); } /* -------------------------------------------------------------------------- */ void Model::addDumpFieldTensor(const std::string & field_id) { this->addDumpFieldTensorToDumper(mesh.getDefaultDumperName(),field_id); } /* -------------------------------------------------------------------------- */ void Model::setBaseName(const std::string & field_id) { mesh.setBaseName(field_id); } /* -------------------------------------------------------------------------- */ void Model::setBaseNameToDumper(const std::string & dumper_name, const std::string & basename) { mesh.setBaseNameToDumper(dumper_name,basename); } /* -------------------------------------------------------------------------- */ void Model::addDumpFieldToDumper(const std::string & dumper_name, const std::string & field_id) { this->addDumpGroupFieldToDumper(dumper_name,field_id,"all",_ek_regular,false); } /* -------------------------------------------------------------------------- */ void Model::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,_ek_regular,false); } /* -------------------------------------------------------------------------- */ void Model::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 Model::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 Model::addDumpFieldVectorToDumper(const std::string & dumper_name, const std::string & field_id) { this->addDumpGroupFieldToDumper(dumper_name,field_id,"all",_ek_regular,3); } /* -------------------------------------------------------------------------- */ void Model::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 Model::addDumpGroupFieldVectorToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name) { this->addDumpGroupFieldToDumper(dumper_name,field_id,group_name,_ek_regular,true); } /* -------------------------------------------------------------------------- */ void Model::addDumpFieldTensorToDumper(const std::string & dumper_name, const std::string & field_id) { this->addDumpGroupFieldToDumper(dumper_name,field_id,"all",_ek_regular,true); } /* -------------------------------------------------------------------------- */ void Model::addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name, const ElementKind & element_kind, bool padding_flag) { this->addDumpGroupFieldToDumper(dumper_name, field_id, group_name, this->spatial_dimension, element_kind, padding_flag); } /* -------------------------------------------------------------------------- */ void Model::addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name, UInt spatial_dimension, const ElementKind & element_kind, bool padding_flag) { #ifdef AKANTU_USE_IOHELPER dumper::Field * field = NULL; if (!field) field = this->createNodalFieldReal(field_id,group_name,padding_flag); if (!field) field = this->createNodalFieldUInt(field_id,group_name,padding_flag); if (!field) field = this->createNodalFieldBool(field_id,group_name,padding_flag); if (!field) field = this->createElementalField(field_id,group_name,padding_flag,spatial_dimension,element_kind); if (!field) field = this->mesh.createFieldFromAttachedData(field_id,group_name, element_kind); if (!field) field = this->mesh.createFieldFromAttachedData(field_id,group_name, element_kind); if (!field) AKANTU_DEBUG_WARNING("No field could be found based on name: " << field_id); if (field) { DumperIOHelper & dumper = mesh.getGroupDumper(dumper_name,group_name); this->addDumpGroupFieldToDumper(field_id,field,dumper); } #endif } /* -------------------------------------------------------------------------- */ void Model::dump() { mesh.dump(); } /* -------------------------------------------------------------------------- */ void Model::setDirectory(const std::string & directory) { mesh.setDirectory(directory); } /* -------------------------------------------------------------------------- */ void Model::setDirectoryToDumper(const std::string & dumper_name, const std::string & directory) { mesh.setDirectoryToDumper(dumper_name,directory); } /* -------------------------------------------------------------------------- */ void Model::setTextModeToDumper(){ mesh.setTextModeToDumper(); } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/model/model.hh b/src/model/model.hh index 0818254b5..f5e30bca1 100644 --- a/src/model/model.hh +++ b/src/model/model.hh @@ -1,323 +1,316 @@ /** * @file model.hh * * @author Guillaume Anciaux * @author David Simon Kammer * @author Nicolas Richart * * @date creation: Tue Jul 27 2010 * @date last modification: Fri Sep 05 2014 * * @brief Interface of a model * * @section LICENSE * * Copyright (©) 2010-2012, 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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MODEL_HH__ #define __AKANTU_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "mesh.hh" #include "fe_engine.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" #include "model_solver.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ struct ModelOptions { - virtual ~ModelOptions() {} }; class DumperIOHelper; class Model : public Memory, public ModelSolver { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Model(Mesh& mesh, UInt spatial_dimension = _all_dimensions, - const ID & id = "model", - const MemoryID & memory_id = 0); + const ID & id = "model", + const MemoryID & memory_id = 0); virtual ~Model(); typedef std::map FEEngineMap; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: 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); + 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); virtual void initPBC(); /// set the parser to use void setParser(Parser & parser); /* ------------------------------------------------------------------------ */ /* 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); + 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); + 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); + 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 handling equation numbers - AKANTU_GET_MACRO(DOFSynchronizer, *dof_synchronizer, const DOFSynchronizer &) - /// return the object handling synchronizers AKANTU_GET_MACRO(SynchronizerRegistry, *synch_registry, SynchronizerRegistry &) /// synchronize the boundary in case of parallel run virtual void synchronizeBoundaries() {}; /// return the fem object associated with a provided name inline FEEngine & getFEEngine(const ID & name = "") const; /// return the fem boundary object associated with a provided name virtual FEEngine & getFEEngineBoundary(const ID & name = ""); /// register a fem object associated with name template inline void registerFEEngineObject(const std::string & name, - Mesh & mesh, - UInt spatial_dimension); + Mesh & mesh, + UInt spatial_dimension); /// unregister a fem object associated with name inline void unRegisterFEEngineObject(const std::string & name); /// return the synchronizer registry SynchronizerRegistry & getSynchronizerRegistry(); /// return the fem object associated with a provided name template inline FEEngineClass & getFEEngineClass(std::string name = "") const; /// return the fem boundary object associated with a provided name template inline FEEngineClass & getFEEngineClassBoundary(std::string name = ""); /// get the pbc pairs std::map & getPBCPairs(){return pbc_pair;}; /// returns if node is slave in pbc inline bool isPBCSlaveNode(const UInt node) const; /// returns the array of pbc slave nodes (boolean information) AKANTU_GET_MACRO(IsPBCSlaveNode, is_pbc_slave_node, const Array &) /* ------------------------------------------------------------------------ */ /* Pack and unpack helper functions */ /* ------------------------------------------------------------------------ */ public: inline UInt getNbQuadraturePoints(const Array & elements, - const ID & fem_id = ID()) const; + const ID & fem_id = ID()) const; /* ------------------------------------------------------------------------ */ /* Dumpable interface (kept for convenience) and dumper relative functions */ /* ------------------------------------------------------------------------ */ void setTextModeToDumper(); virtual void addDumpGroupFieldToDumper(const std::string & field_id, - dumper::Field * field, - DumperIOHelper & dumper); + dumper::Field * field, + DumperIOHelper & dumper); virtual void addDumpField(const std::string & field_id); virtual void addDumpFieldVector(const std::string & field_id); virtual void addDumpFieldToDumper(const std::string & dumper_name, - const std::string & field_id); + const std::string & field_id); virtual void addDumpFieldVectorToDumper(const std::string & dumper_name, - const std::string & field_id); + const std::string & field_id); virtual void addDumpFieldTensorToDumper(const std::string & dumper_name, - const std::string & field_id); + const std::string & field_id); virtual void addDumpFieldTensor(const std::string & field_id); virtual void setBaseName(const std::string & basename); virtual void setBaseNameToDumper(const std::string & dumper_name, - const std::string & basename); + const std::string & basename); virtual void addDumpGroupField(const std::string & field_id, - const std::string & group_name); + const std::string & group_name); virtual void addDumpGroupFieldToDumper(const std::string & dumper_name, - const std::string & field_id, - const std::string & group_name, - const ElementKind & element_kind, - bool padding_flag); + const std::string & field_id, + const std::string & group_name, + const ElementKind & element_kind, + bool padding_flag); virtual void addDumpGroupFieldToDumper(const std::string & dumper_name, - const std::string & field_id, - const std::string & group_name, - UInt spatial_dimension, - const ElementKind & element_kind, - bool padding_flag); + const std::string & field_id, + const std::string & group_name, + UInt spatial_dimension, + const ElementKind & element_kind, + bool padding_flag); virtual void removeDumpGroupField(const std::string & field_id, - const std::string & group_name); + const std::string & group_name); virtual void removeDumpGroupFieldFromDumper(const std::string & dumper_name, - const std::string & field_id, - const std::string & group_name); + const std::string & field_id, + const std::string & group_name); virtual void addDumpGroupFieldVector(const std::string & field_id, - const std::string & group_name); + const std::string & group_name); virtual void addDumpGroupFieldVectorToDumper(const std::string & dumper_name, - const std::string & field_id, - const std::string & group_name); + const std::string & field_id, + const std::string & group_name); virtual dumper::Field * createNodalFieldReal(const std::string & field_name, - const std::string & group_name, - bool padding_flag){return NULL;} + const std::string & group_name, + bool padding_flag){return NULL;} virtual dumper::Field * createNodalFieldUInt(const std::string & field_name, - const std::string & group_name, - bool padding_flag){return NULL;} + const std::string & group_name, + bool padding_flag){return NULL;} virtual dumper::Field * createNodalFieldBool(const std::string & field_name, - const std::string & group_name, - bool padding_flag){return NULL;} + const std::string & group_name, + bool padding_flag){return NULL;} virtual dumper::Field * createElementalField(const std::string & field_name, - const std::string & group_name, - bool padding_flag, - const UInt & spatial_dimension, - const ElementKind & kind){return NULL;} + const std::string & group_name, + bool padding_flag, + const UInt & spatial_dimension, + const ElementKind & kind){return NULL;} void setDirectory(const std::string & directory); void setDirectoryToDumper(const std::string & dumper_name, - const std::string & directory); + const std::string & directory); virtual void dump(); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Mesh Mesh & mesh; /// Spatial dimension of the problem UInt spatial_dimension; /// the main fem object present in all models FEEngineMap fems; /// the fem object present in all models for boundaries FEEngineMap fems_boundary; /// default fem object std::string default_fem; /// 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; /// parser to the pointer to use Parser * parser; }; /* -------------------------------------------------------------------------- */ /* 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/model_inline_impl.cc b/src/model/model_inline_impl.cc index 4850edcdb..b16dbf432 100644 --- a/src/model/model_inline_impl.cc +++ b/src/model/model_inline_impl.cc @@ -1,196 +1,197 @@ /** * @file model_inline_impl.cc * * @author Guillaume Anciaux * @author Nicolas Richart * * @date creation: Wed Aug 25 2010 * @date last modification: Tue Jul 29 2014 * * @brief inline implementation of the model class * * @section LICENSE * * Copyright (©) 2010-2012, 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 . * */ /* -------------------------------------------------------------------------- */ inline SynchronizerRegistry & Model::getSynchronizerRegistry(){ AKANTU_DEBUG_ASSERT(synch_registry,"synchronizer registry not initialized:" << " did you call createSynchronizerRegistry ?"); return *synch_registry; } /* -------------------------------------------------------------------------- */ template inline FEEngineClass & Model::getFEEngineClassBoundary(std::string name) { AKANTU_DEBUG_IN(); if (name == "") name = default_fem; FEEngineMap::const_iterator it_boun = fems_boundary.find(name); FEEngineClass * tmp_fem_boundary; if (it_boun == fems_boundary.end()){ AKANTU_DEBUG_INFO("Creating FEEngine boundary " << name); FEEngineMap::const_iterator it = fems.find(name); AKANTU_DEBUG_ASSERT(it != fems.end(), "The FEEngine " << name << " is not registered"); UInt spatial_dimension = it->second->getElementDimension(); std::stringstream sstr; sstr << id << ":fem_boundary:" << name; tmp_fem_boundary = new FEEngineClass(it->second->getMesh(), spatial_dimension-1, sstr.str(), memory_id); fems_boundary[name] = tmp_fem_boundary; } else { tmp_fem_boundary = dynamic_cast(it_boun->second); } AKANTU_DEBUG_OUT(); return *tmp_fem_boundary; } /* -------------------------------------------------------------------------- */ template inline FEEngineClass & Model::getFEEngineClass(std::string name) const{ AKANTU_DEBUG_IN(); if (name == "") name = default_fem; FEEngineMap::const_iterator it = fems.find(name); AKANTU_DEBUG_ASSERT(it != fems.end(), "The FEEngine " << name << " is not registered"); AKANTU_DEBUG_OUT(); return dynamic_cast(*(it->second)); } /* -------------------------------------------------------------------------- */ inline void Model::unRegisterFEEngineObject(const std::string & name){ FEEngineMap::iterator it = fems.find(name); AKANTU_DEBUG_ASSERT(it != fems.end(), "FEEngine object with name " << name << " was not found"); delete((*it).second); fems.erase(it); if (!fems.empty()) default_fem = (*fems.begin()).first; } /* -------------------------------------------------------------------------- */ template inline void Model::registerFEEngineObject(const std::string & name, Mesh & mesh, UInt spatial_dimension){ if (fems.size() == 0) default_fem = name; #ifndef AKANTU_NDEBUG FEEngineMap::iterator it = fems.find(name); AKANTU_DEBUG_ASSERT(it == fems.end(), "FEEngine object with name " << name << " was already created"); #endif std::stringstream sstr; sstr << id << ":fem:" << name; fems[name] = new FEEngineClass(mesh, spatial_dimension, sstr.str(), memory_id); // MeshUtils::buildFacets(fems[name]->getMesh()); // std::stringstream sstr2; sstr2 << id << ":fem_boundary:" << name; // fems_boundary[name] = new FEEngineClass(mesh, spatial_dimension-1, sstr2.str(), memory_id); } /* -------------------------------------------------------------------------- */ inline FEEngine & Model::getFEEngine(const ID & name) const{ AKANTU_DEBUG_IN(); ID tmp_name = name; if (name == "") tmp_name = default_fem; FEEngineMap::const_iterator it = fems.find(tmp_name); AKANTU_DEBUG_ASSERT(it != fems.end(), "The FEEngine " << tmp_name << " is not registered"); AKANTU_DEBUG_OUT(); return *(it->second); } /* -------------------------------------------------------------------------- */ inline FEEngine & Model::getFEEngineBoundary(const ID & name){ AKANTU_DEBUG_IN(); ID tmp_name = name; if (name == "") tmp_name = default_fem; FEEngineMap::const_iterator it = fems_boundary.find(tmp_name); AKANTU_DEBUG_ASSERT(it != fems_boundary.end(), "The FEEngine boundary " << tmp_name << " is not registered"); AKANTU_DEBUG_ASSERT(it->second != NULL, "The FEEngine boundary " << tmp_name << " was not created"); AKANTU_DEBUG_OUT(); return *(it->second); } -/* -------------------------------------------------------------------------- */ -/// @todo : should merge with a single function which handles local and global -inline void Model::changeLocalEquationNumberForPBC(std::map & pbc_pair, - UInt dimension){ - for (std::map::iterator it = pbc_pair.begin(); - it != pbc_pair.end();++it) { - Int node_master = (*it).second; - Int node_slave = (*it).first; - for (UInt i = 0; i < dimension; ++i) { - (*dof_synchronizer->getLocalDOFEquationNumbersPointer()) - (node_slave*dimension+i) = dimension*node_master+i; - (*dof_synchronizer->getGlobalDOFEquationNumbersPointer()) - (node_slave*dimension+i) = dimension*node_master+i; - } - } -} -/* -------------------------------------------------------------------------- */ -inline bool Model::isPBCSlaveNode(const UInt node) const { - // if no pbc is defined, is_pbc_slave_node is of size zero - if (is_pbc_slave_node.getSize() == 0) - return false; - else - return is_pbc_slave_node(node); -} + +// /* -------------------------------------------------------------------------- */ +// /// @todo : should merge with a single function which handles local and global +// inline void Model::changeLocalEquationNumberForPBC(std::map & pbc_pair, +// UInt dimension){ +// for (std::map::iterator it = pbc_pair.begin(); +// it != pbc_pair.end();++it) { +// Int node_master = (*it).second; +// Int node_slave = (*it).first; +// for (UInt i = 0; i < dimension; ++i) { +// (*dof_synchronizer->getLocalDOFEquationNumbersPointer()) +// (node_slave*dimension+i) = dimension*node_master+i; +// (*dof_synchronizer->getGlobalDOFEquationNumbersPointer()) +// (node_slave*dimension+i) = dimension*node_master+i; +// } +// } +// } +// /* -------------------------------------------------------------------------- */ +// inline bool Model::isPBCSlaveNode(const UInt node) const { +// // if no pbc is defined, is_pbc_slave_node is of size zero +// if (is_pbc_slave_node.getSize() == 0) +// return false; +// else +// return is_pbc_slave_node(node); +// } /* -------------------------------------------------------------------------- */ inline UInt Model::getNbQuadraturePoints(const Array & elements, const ID & fem_id) const { UInt nb_quad = 0; Array::const_iterator it = elements.begin(); Array::const_iterator end = elements.end(); for (; it != end; ++it) { const Element & el = *it; nb_quad += getFEEngine(fem_id).getNbQuadraturePoints(el.type, el.ghost_type); } return nb_quad; } /* -------------------------------------------------------------------------- */ diff --git a/src/model/model_solver.cc b/src/model/model_solver.cc index ba7bb8190..0d5551a25 100644 --- a/src/model/model_solver.cc +++ b/src/model/model_solver.cc @@ -1,356 +1,384 @@ /** * @file model_solver.cc * * @author Nicolas Richart * * @date Wed Aug 12 13:31:56 2015 * * @brief Implementation of ModelSolver * * @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_solver.hh" #include "dof_manager.hh" #if defined(AKANTU_USE_MPI) -# include "mpi_type_wrapper.hh" +#include "mpi_type_wrapper.hh" #endif #if defined(AKANTU_USE_MUMPS) #include "dof_manager_default.hh" #endif #if defined(AKANTU_USE_PETSC) #include "dof_manager_petsc.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ -ModelSolver::ModelSolver(const Mesh & mesh, const ID & id) +ModelSolver::ModelSolver(const Mesh & mesh, const ID & id, UInt memory_id) : Parsable(_st_solver, id), dof_manager(NULL) { std::pair sub_sect = getStaticParser().getSubSections(_st_solver); if (sub_sect.first != sub_sect.second) { AKANTU_EXCEPTION("More than on solver section present in the input file"); } const ParserSection & section = *sub_sect.first; std::string solver_type = section.getName(); if (solver_type == "petsc") { #if defined(AKANTU_USE_PETSC) - this->dof_manager = new DOFManagerPETSc(mesh, id + ":dof_manager_petsc"); + this->dof_manager = new DOFManagerPETSc(mesh, id + ":dof_manager_petsc", memory_id); #else AKANTU_EXCEPTION( "To use PETSc you have to activate it in the compilations options"); #endif } else if (solver_type == "mumps") { #if defined(AKANTU_USE_MUMPS) - this->dof_manager = new DOFManagerDefault(mesh, id + ":dof_manager_default"); + this->dof_manager = + new DOFManagerDefault(mesh, id + ":dof_manager_default", memory_id); #else AKANTU_EXCEPTION( "To use MUMPS you have to activate it in the compilations options"); #endif } else { AKANTU_EXCEPTION( "To use the solver " << solver_type << " you will have to code it. This is an unknown solver type."); } } +/* -------------------------------------------------------------------------- */ +void ModelSolver::initTimeStepSolver( + const ID & time_step_solver_id, const ID & dof_id, + const TimeStepSolverType & time_step_solver_type) { + if(this->default_time_step_solver == "") { + this->default_time_step_solver = time_step_solver_id; + } + + this->dof_manager->getNewTimeStepSolver(time_step_solver_id, dof_id, + time_step_solver_type); +} + /* -------------------------------------------------------------------------- */ -// /* -------------------------------------------------------------------------- */ +// /* -------------------------------------------------------------------------- +// */ // template // void SolidMechanicsModel::solve(Array &increment, Real block_val, -// bool need_factorize, bool has_profile_changed) { +// bool need_factorize, bool +// has_profile_changed) { // if(has_profile_changed) { // this->initJacobianMatrix(); // need_factorize = true; // } // updateResidualInternal(); //doesn't do anything for static // if(need_factorize) { // Real c = 0.,d = 0.,e = 0.; // if(method == _static) { // AKANTU_DEBUG_INFO("Solving K inc = r"); // e = 1.; // } else { // AKANTU_DEBUG_INFO("Solving (c M + d C + e K) inc = r"); // NewmarkBeta * nmb_int = dynamic_cast(integrator); // c = nmb_int->getAccelerationCoefficient(time_step); // d = nmb_int->getVelocityCoefficient(time_step); // e = nmb_int->getDisplacementCoefficient(time_step); // } - // jacobian_matrix->clear(); // // J = c M + d C + e K // if(stiffness_matrix) // jacobian_matrix->add(*stiffness_matrix, e); // if(mass_matrix) // jacobian_matrix->add(*mass_matrix, c); // #if !defined(AKANTU_NDEBUG) // if(mass_matrix && AKANTU_DEBUG_TEST(dblDump)) // mass_matrix->saveMatrix("M.mtx"); // #endif // if(velocity_damping_matrix) // jacobian_matrix->add(*velocity_damping_matrix, d); // jacobian_matrix->applyBoundary(*blocked_dofs, block_val); // #if !defined(AKANTU_NDEBUG) // if(AKANTU_DEBUG_TEST(dblDump)) // jacobian_matrix->saveMatrix("J.mtx"); // #endif // solver->factorize(); // } // // if (rhs.getSize() != 0) // // solver->setRHS(rhs); // // else // solver->setOperators(); // solver->setRHS(*residual); // // solve @f[ J \delta w = r @f] // solver->solve(increment); // UInt nb_nodes = displacement-> getSize(); // UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes; // bool * blocked_dofs_val = blocked_dofs->storage(); // Real * increment_val = increment.storage(); // for (UInt j = 0; j < nb_degree_of_freedom; // ++j,++increment_val, ++blocked_dofs_val) { // if ((*blocked_dofs_val)) // *increment_val = 0.0; // } // } - -// /* -------------------------------------------------------------------------- */ +// /* -------------------------------------------------------------------------- +// */ // template // bool SolidMechanicsModel::solveStatic(Real tolerance, UInt max_iteration, // bool do_not_factorize) { // AKANTU_DEBUG_INFO("Solving Ku = f"); // AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, -// "You should first initialize the implicit solver and assemble the stiffness matrix by calling initImplicit"); +// "You should first initialize the implicit solver and +// assemble the stiffness matrix by calling +// initImplicit"); // AnalysisMethod analysis_method=method; // Real error = 0.; // method=_static; -// bool converged = this->template solveStep(tolerance, error, max_iteration, do_not_factorize); +// bool converged = this->template solveStep(tolerance, +// error, max_iteration, do_not_factorize); // method=analysis_method; // return converged; // } -// /* -------------------------------------------------------------------------- */ +// /* -------------------------------------------------------------------------- +// */ // template // bool SolidMechanicsModel::solveStep(Real tolerance, // UInt max_iteration) { // Real error = 0.; // return this->template solveStep(tolerance, // error, // max_iteration); // } -// /* -------------------------------------------------------------------------- */ +// /* -------------------------------------------------------------------------- +// */ // template -// bool SolidMechanicsModel::solveStep(Real tolerance, Real & error, UInt max_iteration, +// bool SolidMechanicsModel::solveStep(Real tolerance, Real & error, UInt +// max_iteration, // bool do_not_factorize) { // EventManager::sendEvent(SolidMechanicsModelEvent::BeforeSolveStepEvent(method)); // this->implicitPred(); // this->updateResidual(); // AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, -// "You should first initialize the implicit solver and assemble the stiffness matrix"); +// "You should first initialize the implicit solver and +// assemble the stiffness matrix"); // bool need_factorize = !do_not_factorize; // if (method==_implicit_dynamic) { // AKANTU_DEBUG_ASSERT(mass_matrix != NULL, -// "You should first initialize the implicit solver and assemble the mass matrix"); +// "You should first initialize the implicit solver and +// assemble the mass matrix"); // } // switch (cmethod) { // case _scm_newton_raphson_tangent: // case _scm_newton_raphson_tangent_not_computed: // break; // case _scm_newton_raphson_tangent_modified: // this->assembleStiffnessMatrix(); // break; // default: -// AKANTU_DEBUG_ERROR("The resolution method " << cmethod << " has not been implemented!"); +// AKANTU_DEBUG_ERROR("The resolution method " << cmethod << " has not been +// implemented!"); // } // this->n_iter = 0; // bool converged = false; // error = 0.; // if(criteria == _scc_residual) { // converged = this->testConvergence (tolerance, error); // if(converged) return converged; // } // do { // if (cmethod == _scm_newton_raphson_tangent) // this->assembleStiffnessMatrix(); -// solve (*increment, 1., need_factorize); +// solve (*increment, 1., +// need_factorize); // this->implicitCorr(); // if(criteria == _scc_residual) this->updateResidual(); // converged = this->testConvergence (tolerance, error); // if(criteria == _scc_increment && !converged) this->updateResidual(); // //this->dump(); // this->n_iter++; // AKANTU_DEBUG_INFO("[" << criteria << "] Convergence iteration " // << std::setw(std::log10(max_iteration)) << this->n_iter -// << ": error " << error << (converged ? " < " : " > ") << tolerance); +// << ": error " << error << (converged ? " < " : " > ") +// << tolerance); // switch (cmethod) { // case _scm_newton_raphson_tangent: // need_factorize = true; // break; // case _scm_newton_raphson_tangent_not_computed: // case _scm_newton_raphson_tangent_modified: // need_factorize = false; // break; // default: -// AKANTU_DEBUG_ERROR("The resolution method " << cmethod << " has not been implemented!"); +// AKANTU_DEBUG_ERROR("The resolution method " << cmethod << " has not +// been implemented!"); // } - // } while (!converged && this->n_iter < max_iteration); -// // this makes sure that you have correct strains and stresses after the solveStep function (e.g., for dumping) +// // this makes sure that you have correct strains and stresses after the +// solveStep function (e.g., for dumping) // if(criteria == _scc_increment) this->updateResidual(); // if (converged) { // EventManager::sendEvent(SolidMechanicsModelEvent::AfterSolveStepEvent(method)); // } else if(this->n_iter == max_iteration) { -// AKANTU_DEBUG_WARNING("[" << criteria << "] Convergence not reached after " -// << std::setw(std::log10(max_iteration)) << this->n_iter << -// " iteration" << (this->n_iter == 1 ? "" : "s") << "!" << std::endl); +// AKANTU_DEBUG_WARNING("[" << criteria << "] Convergence not reached after +// " +// << std::setw(std::log10(max_iteration)) << +// this->n_iter << +// " iteration" << (this->n_iter == 1 ? "" : "s") << +// "!" << std::endl); // } // return converged; // } // 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 * blocked_dofs_val = blocked_dofs->storage(); // for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { // if(!(*blocked_dofs_val)) { // *res_val -= *accel_val * *mass_val /f_m2a; // } // blocked_dofs_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::solveLumped(Array & x, // const Array & A, // const Array & b, // const Array & blocked_dofs, // Real alpha) { // Real * A_val = A.storage(); // Real * b_val = b.storage(); // Real * x_val = x.storage(); // bool * blocked_dofs_val = blocked_dofs.storage(); // UInt nb_degrees_of_freedom = x.getSize() * x.getNbComponent(); // for (UInt n = 0; n < nb_degrees_of_freedom; ++n) { // if(!(*blocked_dofs_val)) { // *x_val = alpha * (*b_val / *A_val); // } // x_val++; // A_val++; // b_val++; // blocked_dofs_val++; // } // } __END_AKANTU__ diff --git a/src/model/model_solver.hh b/src/model/model_solver.hh index 758346dee..f34febd8c 100644 --- a/src/model/model_solver.hh +++ b/src/model/model_solver.hh @@ -1,81 +1,87 @@ /** * @file model_solver.hh * * @author Nicolas Richart * * @date Wed Jul 22 10:53:10 2015 * * @brief Class regrouping the common solve interface to the different models * * @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 "parsable.hh" #include "dof_manager.hh" +#include "non_linear_solver_callback.hh" +/* -------------------------------------------------------------------------- */ +#include /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MODEL_SOLVER_HH__ #define __AKANTU_MODEL_SOLVER_HH__ __BEGIN_AKANTU__ -class ModelSolver : public Parsable { +class ModelSolver : public Parsable, public NonLinearSolverCallback { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - ModelSolver(const Mesh & mesh, const ID & id); + ModelSolver(const Mesh & mesh, const ID & id, UInt memory_id); virtual ~ModelSolver(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// Solve a step, implicit, explicit, static, ... any things based on the /// current configuration void solveStep(); -protected: - /// assemble the residual - void assembleResidual() { AKANTU_DEBUG_TO_IMPLEMENT(); } - - /// assemble the Jacobian matrix - void assembleJacobian() { AKANTU_DEBUG_TO_IMPLEMENT(); } + /// Initialize a time solver that can be used afterwards with its id + void initTimeStepSolver(const ID & time_step_solver_id, const ID & dof_id, + const TimeStepSolverType & time_step_solver_type); +protected: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ protected: DOFManager & getDOFManager() { return *this->dof_manager; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ -protected: +private: + /// Underlying dof_manager (the brain...) DOFManager * dof_manager; - // TimeStepSolver * time_step_solver; + + /// List of instantiated time step solvers + std::set time_step_solvers; + + /// Default time step solver to use + ID default_time_step_solver; }; __END_AKANTU__ - #endif /* __AKANTU_MODEL_SOLVER_HH__ */ diff --git a/src/solver/static_solver.cc b/src/model/non_linear_solver.cc similarity index 50% rename from src/solver/static_solver.cc rename to src/model/non_linear_solver.cc index 75bf43684..09df956c0 100644 --- a/src/solver/static_solver.cc +++ b/src/model/non_linear_solver.cc @@ -1,92 +1,78 @@ /** - * @file static_solver.cc - * @author Aurelia Cuba Ramos - * @date Wed Jul 30 15:35:01 2014 + * @file non_linear_solver.cc * - * @brief implementation of the static solver + * @author Nicolas Richart + * + * @date Tue Oct 13 15:34:43 2015 + * + * @brief Implementation of the base class NonLinearSolver * * @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_solver.hh" - -#if defined(AKANTU_USE_MPI) -# include "mpi_type_wrapper.hh" -#endif - -/* -------------------------------------------------------------------------- */ -#ifdef AKANTU_USE_PETSC -#include -#endif - +#include "non_linear_solver.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ -StaticSolver::StaticSolver() : CommunicatorEventHandler(), is_initialized(false) { - StaticCommunicator::getStaticCommunicator().registerEventHandler(*this); -} - +void NonLinearSolver::callbackPredictors() { + NonLinearSolverCallbackMap it = solver_callbacks.begin(); + NonLinearSolverCallbackMap end = solver_callbacks.end(); -/* -------------------------------------------------------------------------- */ -StaticSolver::~StaticSolver() { - --this->nb_references; - if(this->nb_references == 0) { - StaticCommunicator::getStaticCommunicator().unregisterEventHandler(*this); - delete this->static_solver; + for (; it != end; ++it) { + it->second->predictor(); } } /* -------------------------------------------------------------------------- */ -StaticSolver & StaticSolver::getStaticSolver() { - if(nb_references == 0) - static_solver = new StaticSolver(); - ++nb_references; - return *static_solver; -} +void NonLinearSolver::callbackCorrectors() { + NonLinearSolverCallbackMap it = solver_callbacks.begin(); + NonLinearSolverCallbackMap end = solver_callbacks.end(); -#ifdef AKANTU_USE_PETSC -#endif + for (; it != end; ++it) { + it->second->corrector(); + } +} /* -------------------------------------------------------------------------- */ -void StaticSolver::initialize(int & argc, char ** & argv) { - if (this->is_initialized) return; - // AKANTU_DEBUG_ASSERT(this->is_initialized != true, "The static solver has already been initialized"); - +void NonLinearSolver::callbackAssembleJacobian() { + NonLinearSolverCallbackMap it = solver_callbacks.begin(); + NonLinearSolverCallbackMap end = solver_callbacks.end(); - this->is_initialized = true; + for (; it != end; ++it) { + it->second->assembleJacobian(); + } } /* -------------------------------------------------------------------------- */ -void StaticSolver::finalize() { - ParentEventHandler::sendEvent(StaticSolverEvent::BeforeStaticSolverDestroyEvent()); - +void NonLinearSolver::callbackAssembleResidual() { + NonLinearSolverCallbackMap it = solver_callbacks.begin(); + NonLinearSolverCallbackMap end = solver_callbacks.end(); - AKANTU_DEBUG_ASSERT(this->is_initialized == true, "The static solver has not been initialized"); -#ifdef AKANTU_USE_PETSC - PetscFinalize(); -#endif - - this->is_initialized = false; + for (; it != end; ++it) { + it->second->assembleResidual(); + } } +/* -------------------------------------------------------------------------- */ + __END_AKANTU__ diff --git a/src/model/non_linear_solver.hh b/src/model/non_linear_solver.hh index c35a947f6..2505f0290 100644 --- a/src/model/non_linear_solver.hh +++ b/src/model/non_linear_solver.hh @@ -1,80 +1,100 @@ /** * @file non_linear_solver.hh * * @author Nicolas Richart * * @date Mon Aug 24 23:48:41 2015 * * @brief Non linear solver interface * * @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_memory.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LINEAR_SOLVER_HH__ #define __AKANTU_NON_LINEAR_SOLVER_HH__ namespace akantu { class DOFManager; + class NonLinearSolverCallback; } __BEGIN_AKANTU__ class NonLinearSolver : Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NonLinearSolver(DOFManager & dof_manager, const NonLinearSolverType & non_linear_solver_type, const ID & id = "non_linear_solver", UInt memory_id = 0); virtual ~NonLinearSolver(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// solve the system described by the jacobian matrix, and rhs contained in /// the dof manager virtual void solve() = 0; +protected: + /// call all the registered predictors + virtual void callbackPredictors(); + + /// call all the registered correctors + virtual void callbackCorrectors(); + + /// call all the registered predictors + virtual void callbackAssembleJacobian(); + + /// call all the registered predictors + virtual void callbackAssembleResidual(); + /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// configure the solver from ParserSection virtual void setParameters(const ParserSection & parameters_section); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: + typedef std::map NonLinearSolverCallbackMap; + + /// Set of callbacks to use in the solver for jacobian assembly, residual + /// assembly, corrector & predictor if needed + NonLinearSolverCallbackMap solver_callbacks; + /// type of non linear solver NonLinearSolverType non_linear_solver_type; }; __END_AKANTU__ #endif /* __AKANTU_NON_LINEAR_SOLVER_HH__ */ diff --git a/src/model/non_linear_solver_callback.hh b/src/model/non_linear_solver_callback.hh index 7fb930ae9..c9a393af6 100644 --- a/src/model/non_linear_solver_callback.hh +++ b/src/model/non_linear_solver_callback.hh @@ -1,61 +1,61 @@ /** * @file non_linear_solver_callback.hh * * @author Nicolas Richart * * @date Mon Sep 28 18:48:21 2015 * * @brief Interface to implement for the non linear solver to work * * @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_NON_LINEAR_SOLVER_CALLBACK_HH__ #define __AKANTU_NON_LINEAR_SOLVER_CALLBACK_HH__ __BEGIN_AKANTU__ class NonLinearSolverCallback { /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// callback to assemble the Jacobian Matrix - virtual void assembleJacobian(); + virtual void assembleJacobian() { AKANTU_DEBUG_TO_IMPLEMENT(); } /// callback to assemble the residual (rhs) - virtual void assembleResidual(); + virtual void assembleResidual() { AKANTU_DEBUG_TO_IMPLEMENT(); } /* ------------------------------------------------------------------------ */ /* Dynamic simulations part */ /* ------------------------------------------------------------------------ */ /// callback for the predictor (in case of dynamic simulation) - virtual void predictor(); + virtual void predictor() { AKANTU_DEBUG_TO_IMPLEMENT(); } /// callback for the corrector (in case of dynamic simulation) - virtual void corrector(); + virtual void corrector() { AKANTU_DEBUG_TO_IMPLEMENT(); } }; __END_AKANTU__ #endif /* __AKANTU_NON_LINEAR_SOLVER_CALLBACK_HH__ */ diff --git a/src/model/non_linear_solver_default.cc b/src/model/non_linear_solver_default.cc index 1ea420bc6..f7d578911 100644 --- a/src/model/non_linear_solver_default.cc +++ b/src/model/non_linear_solver_default.cc @@ -1,167 +1,168 @@ /** * @file non_linear_solver_default.cc * * @author Nicolas Richart * * @date Tue Aug 25 00:57:00 2015 * * @brief Implementation of the default NonLinearSolver * * @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 "non_linear_solver_default.hh" #include "dof_manager_default.hh" #include "non_linear_solver_callback.hh" +#include "static_communicator.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ NonLinearSolverDefault::NonLinearSolverDefault( DOFManagerDefault & dof_manager, const NonLinearSolverType & non_linear_solver_type, const ID & id, UInt memory_id) : NonLinearSolver(dof_manager, non_linear_solver_type, id, memory_id), dof_manager(dof_manager), solver(dof_manager, "jacobian", id + ":sparse_solver", memory_id), convergence_criteria_type(_scc_solution), convergence_criteria(1e-10), max_iterations(10), n_iter(0), error(0.), converged(false) {} /* -------------------------------------------------------------------------- */ NonLinearSolverDefault::~NonLinearSolverDefault() {} /* ------------------------------------------------------------------------ */ void NonLinearSolverDefault::solve() { // EventManager::sendEvent(NonLinearSolver::BeforeNonLinearSolverSolve(method)); - this->solver_callback->predictor(); + this->callbackPredictors(); switch (this->non_linear_solver_type) { case _nls_linear: case _nls_newton_raphson: break; case _nls_newton_raphson_modified: - this->solver_callback->assembleJacobian(); + this->callbackAssembleJacobian(); break; default: AKANTU_DEBUG_ERROR("The resolution method " << this->non_linear_solver_type << " has not been implemented!"); } this->n_iter = 0; this->converged = false; if (this->convergence_criteria_type == _scc_residual) { this->converged = this->testConvergence(this->dof_manager.getResidual()); if (this->converged) return; } do { if (this->non_linear_solver_type == _nls_newton_raphson) - this->solver_callback->assembleJacobian(); + this->callbackAssembleJacobian(); this->solver.solve(); - this->solver_callback->corrector(); + this->callbackCorrectors(); // EventManager::sendEvent(NonLinearSolver::AfterSparseSolve(method)); if (this->convergence_criteria_type == _scc_residual) { - this->solver_callback->assembleResidual(); + this->callbackAssembleResidual(); this->converged = this->testConvergence(this->dof_manager.getResidual()); } else { - this->converged = this->testConvergence(this->dof_manager.getSolution()); + this->converged = this->testConvergence(this->dof_manager.getGlobalSolution()); } if (this->convergence_criteria_type == _scc_solution && !this->converged) - this->solver_callback->assembleResidual(); + this->callbackAssembleResidual(); // this->dump(); this->n_iter++; AKANTU_DEBUG_INFO( "[" << this->convergence_criteria_type << "] Convergence iteration " << std::setw(std::log10(this->max_iterations)) << this->n_iter << ": error " << this->error << (this->converged ? " < " : " > ") << this->convergence_criteria); } while (!this->converged && this->n_iter < this->max_iterations); // this makes sure that you have correct strains and stresses after the // solveStep function (e.g., for dumping) if (this->convergence_criteria_type == _scc_solution) - this->solver_callback->assembleResidual(); + this->callbackAssembleResidual(); if (this->converged) { // EventManager::sendEvent( // SolidMechanicsModelEvent::AfterNonLinearSolverSolves(method)); } else if (this->n_iter == this->max_iterations) { AKANTU_DEBUG_WARNING("[" << this->convergence_criteria_type << "] Convergence not reached after " << std::setw(std::log10(this->max_iterations)) << this->n_iter << " iteration" << (this->n_iter == 1 ? "" : "s") << "!" << std::endl); } return; } /* -------------------------------------------------------------------------- */ void NonLinearSolverDefault::setParameters( const ParserSection & parameters_section) {} /* -------------------------------------------------------------------------- */ bool NonLinearSolverDefault::testConvergence(const Array & array) { AKANTU_DEBUG_IN(); - const Array & blocked_dofs = this->dof_manager.getBlockedDOFs(); + const Array & blocked_dofs = this->dof_manager.getGlobalBlockedDOFs(); UInt nb_degree_of_freedoms = array.getSize(); Array::const_scalar_iterator arr_it = array.begin(); Array::const_scalar_iterator bld_it = blocked_dofs.begin(); Real norm = 0.; for (UInt n = 0; n < nb_degree_of_freedoms; ++n, ++arr_it, ++bld_it) { bool is_local_node = this->dof_manager.isLocalOrMasterDOF(n); if(!(*bld_it) && is_local_node) { norm += *arr_it * *arr_it; } } StaticCommunicator::getStaticCommunicator().allReduce(&norm, 1, _so_sum); norm = std::sqrt(norm); AKANTU_DEBUG_ASSERT(!Math::isnan(norm), "Something goes wrong in the solve phase"); this->error = norm; return (error < this->convergence_criteria); } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/model/non_linear_solver_default.hh b/src/model/non_linear_solver_default.hh index 1cc344287..9a1a16b85 100644 --- a/src/model/non_linear_solver_default.hh +++ b/src/model/non_linear_solver_default.hh @@ -1,109 +1,104 @@ /** * @file non_linear_solver_default.hh * * @author Nicolas Richart * * @date Tue Aug 25 00:48:07 2015 * * @brief Default implementation of NonLinearSolver, in case no external library * is there to do the job * * @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 "non_linear_solver.hh" #include "solver_mumps.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NON_LINEAR_SOLVER_DEFAULT_HH__ #define __AKANTU_NON_LINEAR_SOLVER_DEFAULT_HH__ namespace akantu { class DOFManagerDefault; - class NonLinearSolverCallback; } __BEGIN_AKANTU__ class NonLinearSolverDefault : public NonLinearSolver { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NonLinearSolverDefault(DOFManagerDefault & dof_manager, const NonLinearSolverType & non_linear_solver_type, const ID & id = "non_linear_solver_default", UInt memory_id = 0); virtual ~NonLinearSolverDefault(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// Function that solve the non linear system described by the dof manager and /// the solver callback functions void solve(); protected: /// test the convergence compare norm of array to convergence_criteria bool testConvergence(const Array & array); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: virtual void setParameters(const ParserSection & parameters_section); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: DOFManagerDefault & dof_manager; /// Sparse solver used for the linear solves SparseSolverMumps solver; /// Type of convergence criteria SolveConvergenceCriteria convergence_criteria_type; - /// Set of callbacks to use in the solver for jacobian assembly, residual - /// assembly, corrector & predictor if needed - NonLinearSolverCallback * solver_callback; - /// convergence threshold Real convergence_criteria; /// Max number of iterations UInt max_iterations; /// Number of iterations at last solve call UInt n_iter; /// Convergence error at last solve call Real error; /// Did the last call to solve reached convergence bool converged; }; __END_AKANTU__ #endif /* __AKANTU_NON_LINEAR_SOLVER_DEFAULT_HH__ */ diff --git a/src/model/solid_mechanics/material.cc b/src/model/solid_mechanics/material.cc index 2b5241a1c..98848b0c0 100644 --- a/src/model/solid_mechanics/material.cc +++ b/src/model/solid_mechanics/material.cc @@ -1,1872 +1,1867 @@ /** * @file material.cc * * @author Aurelia Isabel Cuba Ramos * @author Marco Vocialta * @author Nicolas Richart * @author Daniel Pino Muñoz * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Sep 16 2014 * * @brief Implementation of the common part of the material class * * @section LICENSE * * Copyright (©) 2010-2012, 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 "material.hh" #include "solid_mechanics_model.hh" #include "sparse_matrix.hh" #include "dof_synchronizer.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Material::Material(SolidMechanicsModel & model, const ID & id) : Memory(id, model.getMemoryID()), Parsable(_st_material, id), is_init(false), fem(&(model.getFEEngine())), finite_deformation(false), name(""), model(&model), spatial_dimension(this->model->getSpatialDimension()), element_filter("element_filter", id, this->memory_id), stress("stress", *this), eigengradu("eigen_grad_u", *this), gradu("grad_u", *this), green_strain("green_strain",*this), piola_kirchhoff_2("piola_kirchhoff_2", *this), // potential_energy_vector(false), potential_energy("potential_energy", *this), is_non_local(false), use_previous_stress(false), use_previous_gradu(false), interpolation_inverse_coordinates("interpolation inverse coordinates", *this), interpolation_points_matrices("interpolation points matrices", *this) { AKANTU_DEBUG_IN(); /// for each connectivity types allocate the element filer array of the material model.getMesh().initElementTypeMapArray(element_filter, - 1, - spatial_dimension, - false, - _ek_regular); + 1, + spatial_dimension, + false, + _ek_regular); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Material::Material(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id) : Memory(id, model.getMemoryID()), Parsable(_st_material, id), is_init(false), fem(&(model.getFEEngine())), finite_deformation(false), name(""), model(&model), spatial_dimension(dim), element_filter("element_filter", id, this->memory_id), stress("stress", *this, dim, fe_engine, this->element_filter), eigengradu("eigen_grad_u", *this, dim, fe_engine, this->element_filter), gradu("gradu", *this, dim, fe_engine, this->element_filter), green_strain("green_strain", *this, dim, fe_engine, this->element_filter), piola_kirchhoff_2("poila_kirchhoff_2", *this, dim, fe_engine, this->element_filter), potential_energy("potential_energy", *this, dim, fe_engine, this->element_filter), is_non_local(false), use_previous_stress(false), use_previous_gradu(false), interpolation_inverse_coordinates("interpolation inverse_coordinates", *this, dim, fe_engine, this->element_filter), interpolation_points_matrices("interpolation points matrices", *this, dim, fe_engine, this->element_filter) { AKANTU_DEBUG_IN(); mesh.initElementTypeMapArray(element_filter, 1, spatial_dimension, false, _ek_regular); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Material::~Material() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::initialize() { registerParam("rho" , rho , Real(0.) , _pat_parsable | _pat_modifiable, "Density"); registerParam("name" , name , std::string(), _pat_parsable | _pat_readable); registerParam("finite_deformation" , finite_deformation , false , _pat_parsable | _pat_readable, "Is finite deformation"); registerParam("inelastic_deformation", inelastic_deformation, false , _pat_internal, "Is inelastic deformation"); /// allocate gradu stress for local elements eigengradu.initialize(spatial_dimension * spatial_dimension); gradu.initialize(spatial_dimension * spatial_dimension); stress.initialize(spatial_dimension * spatial_dimension); this->model->registerEventHandler(*this); } /* -------------------------------------------------------------------------- */ void Material::initMaterial() { AKANTU_DEBUG_IN(); if(finite_deformation) { this->piola_kirchhoff_2.initialize(spatial_dimension * spatial_dimension); if(use_previous_stress) this->piola_kirchhoff_2.initializeHistory(); this->green_strain.initialize(spatial_dimension * spatial_dimension); } if(use_previous_stress) this->stress.initializeHistory(); if(use_previous_gradu) this->gradu.initializeHistory(); for (std::map *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->resize(); for (std::map *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->resize(); for (std::map *>::iterator it = internal_vectors_bool.begin(); it != internal_vectors_bool.end(); ++it) it->second->resize(); is_init = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::savePreviousState() { AKANTU_DEBUG_IN(); for (std::map *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) { if(it->second->hasHistory()) it->second->saveCurrentValues(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the residual by assembling @f$\int_{e} \sigma_e \frac{\partial * \varphi}{\partial X} dX @f$ * * @param[in] displacements nodes displacements * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ void Material::updateResidual(GhostType ghost_type) { AKANTU_DEBUG_IN(); computeAllStresses(ghost_type); assembleResidual(ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::assembleResidual(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); if(!finite_deformation){ - Array & residual = const_cast &>(model->getResidual()); + Array & internal_force = const_cast &>(model->getInternalForce()); - Mesh & mesh = fem->getMesh(); + Mesh & mesh = this->fem->getMesh(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { Array & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element) { - const Array & shapes_derivatives = fem->getShapesDerivatives(*it, ghost_type); + const Array & shapes_derivatives = fem->getShapesDerivatives(*it, ghost_type); - UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent(); - UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); - UInt nb_quadrature_points = fem->getNbQuadraturePoints(*it, ghost_type); + UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent(); + UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); + UInt nb_quadrature_points = fem->getNbQuadraturePoints(*it, ghost_type); - /// compute @f$\sigma \frac{\partial \varphi}{\partial X}@f$ by @f$\mathbf{B}^t \mathbf{\sigma}_q@f$ - Array * sigma_dphi_dx = - new Array(nb_element*nb_quadrature_points, - size_of_shapes_derivatives, "sigma_x_dphi_/_dX"); + /// compute @f$\sigma \frac{\partial \varphi}{\partial X}@f$ by @f$\mathbf{B}^t \mathbf{\sigma}_q@f$ + Array * sigma_dphi_dx = + new Array(nb_element*nb_quadrature_points, + size_of_shapes_derivatives, "sigma_x_dphi_/_dX"); - Array * shapesd_filtered = - new Array(0, size_of_shapes_derivatives, "filtered shapesd"); + Array * shapesd_filtered = + new Array(0, size_of_shapes_derivatives, "filtered shapesd"); - FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered, - *it, ghost_type, elem_filter); + FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered, + *it, ghost_type, elem_filter); - Array & stress_vect = this->stress(*it, ghost_type); + Array & stress_vect = this->stress(*it, ghost_type); - Array::matrix_iterator sigma = - stress_vect.begin(spatial_dimension, spatial_dimension); - Array::matrix_iterator B = - shapesd_filtered->begin(spatial_dimension, nb_nodes_per_element); - Array::matrix_iterator Bt_sigma_it = - sigma_dphi_dx->begin(spatial_dimension, nb_nodes_per_element); + Array::matrix_iterator sigma = + stress_vect.begin(spatial_dimension, spatial_dimension); + Array::matrix_iterator B = + shapesd_filtered->begin(spatial_dimension, nb_nodes_per_element); + Array::matrix_iterator Bt_sigma_it = + sigma_dphi_dx->begin(spatial_dimension, nb_nodes_per_element); - for (UInt q = 0; q < nb_element*nb_quadrature_points; ++q, ++sigma, ++B, ++Bt_sigma_it) - Bt_sigma_it->mul(*sigma, *B); + for (UInt q = 0; q < nb_element*nb_quadrature_points; ++q, ++sigma, ++B, ++Bt_sigma_it) + Bt_sigma_it->mul(*sigma, *B); - delete shapesd_filtered; + delete shapesd_filtered; - /** - * compute @f$\int \sigma * \frac{\partial \varphi}{\partial X}dX@f$ by @f$ \sum_q \mathbf{B}^t - * \mathbf{\sigma}_q \overline w_q J_q@f$ - */ - Array * int_sigma_dphi_dx = new Array(nb_element, - nb_nodes_per_element * spatial_dimension, - "int_sigma_x_dphi_/_dX"); + /** + * compute @f$\int \sigma * \frac{\partial \varphi}{\partial X}dX@f$ by @f$ \sum_q \mathbf{B}^t + * \mathbf{\sigma}_q \overline w_q J_q@f$ + */ + Array * int_sigma_dphi_dx = new Array(nb_element, + nb_nodes_per_element * spatial_dimension, + "int_sigma_x_dphi_/_dX"); - fem->integrate(*sigma_dphi_dx, *int_sigma_dphi_dx, - size_of_shapes_derivatives, - *it, ghost_type, - elem_filter); - delete sigma_dphi_dx; + this->fem->integrate(*sigma_dphi_dx, *int_sigma_dphi_dx, + size_of_shapes_derivatives, + *it, ghost_type, + elem_filter); + delete sigma_dphi_dx; - /// assemble - fem->assembleArray(*int_sigma_dphi_dx, residual, - model->getDOFSynchronizer().getLocalDOFEquationNumbers(), - residual.getNbComponent(), - *it, ghost_type, elem_filter, -1); - delete int_sigma_dphi_dx; + /// assemble + model->getDOFManager().assembleElementalArrayLocalArray(*int_sigma_dphi_dx, internal_force, + *it, ghost_type, -1, elem_filter); + delete int_sigma_dphi_dx; } } } else{ switch (spatial_dimension){ case 1: this->assembleResidual<1>(ghost_type); break; case 2: this->assembleResidual<2>(ghost_type); break; case 3: this->assembleResidual<3>(ghost_type); break; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the stress from the gradu * * @param[in] current_position nodes postition + displacements * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ void Material::computeAllStresses(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); Mesh::type_iterator it = fem->getMesh().firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = fem->getMesh().lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { Array & elem_filter = element_filter(*it, ghost_type); if (elem_filter.getSize() == 0) continue; Array & gradu_vect = gradu(*it, ghost_type); /// compute @f$\nabla u@f$ fem->gradientOnQuadraturePoints(model->getDisplacement(), gradu_vect, - spatial_dimension, - *it, ghost_type, elem_filter); + spatial_dimension, + *it, ghost_type, elem_filter); gradu_vect -= eigengradu(*it, ghost_type); /// compute @f$\mathbf{\sigma}_q@f$ from @f$\nabla u@f$ computeStress(*it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computeAllCauchyStresses(GhostType ghost_type) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(finite_deformation,"The Cauchy stress can only be computed if you are working in finite deformation."); //resizeInternalArray(stress); Mesh::type_iterator it = fem->getMesh().firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = fem->getMesh().lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) switch (spatial_dimension){ case 1: this->computeCauchyStress<1>(*it, ghost_type); break; case 2: this->computeCauchyStress<2>(*it, ghost_type); break; case 3: this->computeCauchyStress<3>(*it, ghost_type); break; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::computeCauchyStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array::matrix_iterator gradu_it = this->gradu(el_type, ghost_type).begin(dim, dim); Array::matrix_iterator gradu_end = this->gradu(el_type, ghost_type).end(dim, dim); Array::matrix_iterator piola_it = this->piola_kirchhoff_2(el_type, ghost_type).begin(dim, dim); Array::matrix_iterator stress_it = this->stress(el_type, ghost_type).begin(dim, dim); Matrix F_tensor(dim, dim); for (; gradu_it != gradu_end; ++gradu_it, ++piola_it, ++stress_it) { Matrix & grad_u = *gradu_it; Matrix & piola = *piola_it; Matrix & sigma = *stress_it; gradUToF (grad_u, F_tensor); this->computeCauchyStressOnQuad(F_tensor, piola, sigma); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::setToSteadyState(GhostType ghost_type) { AKANTU_DEBUG_IN(); const Array & displacement = model->getDisplacement(); //resizeInternalArray(gradu); UInt spatial_dimension = model->getSpatialDimension(); Mesh::type_iterator it = fem->getMesh().firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = fem->getMesh().lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { Array & elem_filter = element_filter(*it, ghost_type); Array & gradu_vect = gradu(*it, ghost_type); /// compute @f$\nabla u@f$ fem->gradientOnQuadraturePoints(displacement, gradu_vect, - spatial_dimension, - *it, ghost_type, elem_filter); + spatial_dimension, + *it, ghost_type, elem_filter); setToSteadyState(*it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the stiffness matrix by assembling @f$\int_{\omega} B^t \times D * \times B d\omega @f$ * * @param[in] current_position nodes postition + displacements * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ void Material::assembleStiffnessMatrix(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { if(finite_deformation){ switch (spatial_dimension) { case 1: - { - assembleStiffnessMatrixNL < 1 > (*it, ghost_type); - assembleStiffnessMatrixL2 < 1 > (*it, ghost_type); - break; - } + { + assembleStiffnessMatrixNL < 1 > (*it, ghost_type); + assembleStiffnessMatrixL2 < 1 > (*it, ghost_type); + break; + } case 2: - { - assembleStiffnessMatrixNL < 2 > (*it, ghost_type); - assembleStiffnessMatrixL2 < 2 > (*it, ghost_type); - break; - } + { + assembleStiffnessMatrixNL < 2 > (*it, ghost_type); + assembleStiffnessMatrixL2 < 2 > (*it, ghost_type); + break; + } case 3: - { - assembleStiffnessMatrixNL < 3 > (*it, ghost_type); - assembleStiffnessMatrixL2 < 3 > (*it, ghost_type); - break; - } + { + assembleStiffnessMatrixNL < 3 > (*it, ghost_type); + assembleStiffnessMatrixL2 < 3 > (*it, ghost_type); + break; + } } } else { switch(spatial_dimension) { case 1: { assembleStiffnessMatrix<1>(*it, ghost_type); break; } case 2: { assembleStiffnessMatrix<2>(*it, ghost_type); break; } case 3: { assembleStiffnessMatrix<3>(*it, ghost_type); break; } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::assembleStiffnessMatrix(const ElementType & type, - GhostType ghost_type) { + GhostType ghost_type) { AKANTU_DEBUG_IN(); Array & elem_filter = element_filter(type, ghost_type); if (elem_filter.getSize()) { - SparseMatrix & K = const_cast(model->getStiffnessMatrix()); - const Array & shapes_derivatives = fem->getShapesDerivatives(type, - ghost_type); - + ghost_type); + Array & gradu_vect = gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = fem->getNbQuadraturePoints(type, - ghost_type); + ghost_type); gradu_vect.resize(nb_quadrature_points * nb_element); fem->gradientOnQuadraturePoints(model->getDisplacement(), - gradu_vect, dim, type, ghost_type, - elem_filter); + gradu_vect, dim, type, ghost_type, + elem_filter); UInt tangent_size = getTangentStiffnessVoigtSize(dim); Array * tangent_stiffness_matrix = new Array(nb_element*nb_quadrature_points, tangent_size * tangent_size, - "tangent_stiffness_matrix"); + "tangent_stiffness_matrix"); tangent_stiffness_matrix->clear(); computeTangentModuli(type, *tangent_stiffness_matrix, ghost_type); Array * shapesd_filtered = new Array(0, dim * nb_nodes_per_element, "filtered shapesd"); FEEngine::filterElementalData(fem->getMesh(), shapes_derivatives, - *shapesd_filtered, type, ghost_type, elem_filter); + *shapesd_filtered, type, ghost_type, elem_filter); /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_d_b_size = dim * 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"); + bt_d_b_size * bt_d_b_size, + "B^t*D*B"); Matrix B(tangent_size, dim * nb_nodes_per_element); Matrix Bt_D(dim * nb_nodes_per_element, tangent_size); Array::matrix_iterator shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element); Array::matrix_iterator Bt_D_B_it = bt_d_b->begin(dim*nb_nodes_per_element, dim*nb_nodes_per_element); Array::matrix_iterator D_it = tangent_stiffness_matrix->begin(tangent_size, tangent_size); Array::matrix_iterator D_end = tangent_stiffness_matrix->end (tangent_size, tangent_size); for(; D_it != D_end; ++D_it, ++Bt_D_B_it, ++shapes_derivatives_filtered_it) { Matrix & D = *D_it; Matrix & Bt_D_B = *Bt_D_B_it; VoigtHelper::transferBMatrixToSymVoigtBMatrix( - *shapes_derivatives_filtered_it, B, nb_nodes_per_element); + *shapes_derivatives_filtered_it, B, nb_nodes_per_element); Bt_D.mul(B, D); Bt_D_B.mul(Bt_D, B); } delete tangent_stiffness_matrix; delete shapesd_filtered; /// 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"); + bt_d_b_size * bt_d_b_size, + "K_e"); fem->integrate(*bt_d_b, *K_e, - bt_d_b_size * bt_d_b_size, - type, ghost_type, - elem_filter); + bt_d_b_size * bt_d_b_size, + type, ghost_type, + elem_filter); delete bt_d_b; - fem->assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, - elem_filter); + model->getDOFManager().assembleElementalMatricesToMatrix("stiffness", "displacements", *K_e, + type, ghost_type, _symmetric, + elem_filter); delete K_e; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::assembleStiffnessMatrixNL(const ElementType & type, - GhostType ghost_type) { + GhostType ghost_type) { AKANTU_DEBUG_IN(); - SparseMatrix & K = const_cast (model->getStiffnessMatrix()); - const Array & shapes_derivatives = fem->getShapesDerivatives(type, ghost_type); Array & elem_filter = element_filter(type, ghost_type); //Array & gradu_vect = delta_gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = fem->getNbQuadraturePoints(type, ghost_type); //gradu_vect.resize(nb_quadrature_points * nb_element); // fem->gradientOnQuadraturePoints(model->getIncrement(), gradu_vect, // dim, type, ghost_type, &elem_filter); Array * shapes_derivatives_filtered = new Array (nb_element * nb_quadrature_points, - dim * nb_nodes_per_element, - "shapes derivatives filtered"); + dim * nb_nodes_per_element, + "shapes derivatives filtered"); Array::const_matrix_iterator shapes_derivatives_it = shapes_derivatives.begin(spatial_dimension, - nb_nodes_per_element); + nb_nodes_per_element); Array::matrix_iterator shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, - nb_nodes_per_element); + nb_nodes_per_element); UInt * elem_filter_val = elem_filter.storage(); for (UInt e = 0; e < nb_element; ++e, ++elem_filter_val) for (UInt q = 0; q < nb_quadrature_points; ++q, ++shapes_derivatives_filtered_it) *shapes_derivatives_filtered_it = shapes_derivatives_it[*elem_filter_val * nb_quadrature_points + q]; /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_s_b_size = dim * nb_nodes_per_element; Array * bt_s_b = new Array (nb_element * nb_quadrature_points, - bt_s_b_size * bt_s_b_size, - "B^t*D*B"); + bt_s_b_size * bt_s_b_size, + "B^t*D*B"); UInt piola_matrix_size = getCauchyStressMatrixSize(dim); Matrix B(piola_matrix_size, bt_s_b_size); Matrix Bt_S(bt_s_b_size, piola_matrix_size); Matrix S(piola_matrix_size, piola_matrix_size); shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, nb_nodes_per_element); Array::matrix_iterator Bt_S_B_it = bt_s_b->begin(bt_s_b_size, - bt_s_b_size); + bt_s_b_size); Array::matrix_iterator Bt_S_B_end = bt_s_b->end(bt_s_b_size, - bt_s_b_size); + bt_s_b_size); Array::matrix_iterator piola_it = piola_kirchhoff_2(type, ghost_type).begin(dim, dim); for (; Bt_S_B_it != Bt_S_B_end; ++Bt_S_B_it, ++shapes_derivatives_filtered_it, ++piola_it) { Matrix & Bt_S_B = *Bt_S_B_it; Matrix & Piola_kirchhoff_matrix = *piola_it; setCauchyStressMatrix< dim >(Piola_kirchhoff_matrix, S); VoigtHelper::transferBMatrixToBNL(*shapes_derivatives_filtered_it, B, nb_nodes_per_element); Bt_S.mul < true, false > (B, S); Bt_S_B.mul < false, false > (Bt_S, B); } delete shapes_derivatives_filtered; /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array * K_e = new Array (nb_element, - bt_s_b_size * bt_s_b_size, - "K_e"); + bt_s_b_size * bt_s_b_size, + "K_e"); fem->integrate(*bt_s_b, *K_e, - bt_s_b_size * bt_s_b_size, - type, ghost_type, - elem_filter); + bt_s_b_size * bt_s_b_size, + type, ghost_type, + elem_filter); delete bt_s_b; - fem->assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, elem_filter); + model->getDOFManager().assembleElementalMatricesToMatrix("stiffness", "displacements", *K_e, + type, ghost_type, _symmetric, + elem_filter); + delete K_e; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::assembleStiffnessMatrixL2(const ElementType & type, - GhostType ghost_type) { + GhostType ghost_type) { AKANTU_DEBUG_IN(); - SparseMatrix & K = const_cast (model->getStiffnessMatrix()); - const Array & shapes_derivatives = fem->getShapesDerivatives(type, ghost_type); Array & elem_filter = element_filter(type, ghost_type); Array & gradu_vect = gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = fem->getNbQuadraturePoints(type, ghost_type); gradu_vect.resize(nb_quadrature_points * nb_element); fem->gradientOnQuadraturePoints(model->getDisplacement(), gradu_vect, - dim, type, ghost_type, elem_filter); + dim, type, ghost_type, elem_filter); UInt tangent_size = getTangentStiffnessVoigtSize(dim); Array * tangent_stiffness_matrix = new Array (nb_element*nb_quadrature_points, tangent_size * tangent_size, - "tangent_stiffness_matrix"); + "tangent_stiffness_matrix"); tangent_stiffness_matrix->clear(); computeTangentModuli(type, *tangent_stiffness_matrix, ghost_type); Array * shapes_derivatives_filtered = new Array (nb_element * nb_quadrature_points, - dim * nb_nodes_per_element, - "shapes derivatives filtered"); + dim * nb_nodes_per_element, + "shapes derivatives filtered"); Array::const_matrix_iterator shapes_derivatives_it = shapes_derivatives.begin(spatial_dimension, - nb_nodes_per_element); + nb_nodes_per_element); Array::matrix_iterator shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, - nb_nodes_per_element); + nb_nodes_per_element); UInt * elem_filter_val = elem_filter.storage(); for (UInt e = 0; e < nb_element; ++e, ++elem_filter_val) for (UInt q = 0; q < nb_quadrature_points; ++q, ++shapes_derivatives_filtered_it) *shapes_derivatives_filtered_it = shapes_derivatives_it[*elem_filter_val * nb_quadrature_points + q]; /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_d_b_size = dim * 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"); + bt_d_b_size * bt_d_b_size, + "B^t*D*B"); Matrix B(tangent_size, dim * nb_nodes_per_element); Matrix B2(tangent_size, dim * nb_nodes_per_element); Matrix Bt_D(dim * nb_nodes_per_element, tangent_size); shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, nb_nodes_per_element); Array::matrix_iterator Bt_D_B_it = bt_d_b->begin(dim*nb_nodes_per_element, - dim * nb_nodes_per_element); + dim * nb_nodes_per_element); Array::matrix_iterator grad_u_it = gradu_vect.begin(dim, dim); Array::matrix_iterator D_it = tangent_stiffness_matrix->begin(tangent_size, - tangent_size); + tangent_size); Array::matrix_iterator D_end = tangent_stiffness_matrix->end(tangent_size, - tangent_size); + tangent_size); for (; D_it != D_end; ++D_it, ++Bt_D_B_it, ++shapes_derivatives_filtered_it, ++grad_u_it) { Matrix & grad_u = *grad_u_it; Matrix & D = *D_it; Matrix & Bt_D_B = *Bt_D_B_it; //transferBMatrixToBL1 (*shapes_derivatives_filtered_it, B, nb_nodes_per_element); VoigtHelper::transferBMatrixToSymVoigtBMatrix(*shapes_derivatives_filtered_it, B, nb_nodes_per_element); VoigtHelper::transferBMatrixToBL2(*shapes_derivatives_filtered_it, grad_u, B2, nb_nodes_per_element); B += B2; Bt_D.mul < true, false > (B, D); Bt_D_B.mul < false, false > (Bt_D, B); } delete tangent_stiffness_matrix; delete shapes_derivatives_filtered; /// 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"); + bt_d_b_size * bt_d_b_size, + "K_e"); fem->integrate(*bt_d_b, *K_e, - bt_d_b_size * bt_d_b_size, - type, ghost_type, - elem_filter); + bt_d_b_size * bt_d_b_size, + type, ghost_type, + elem_filter); delete bt_d_b; - fem->assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, elem_filter); + model->getDOFManager().assembleElementalMatricesToMatrix("stiffness", "displacements", *K_e, + type, ghost_type, _symmetric, + elem_filter); delete K_e; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::assembleResidual(GhostType ghost_type){ AKANTU_DEBUG_IN(); - Array & residual = const_cast &> (model->getResidual()); + Array & internal_force = model->getInternalForce(); Mesh & mesh = fem->getMesh(); Mesh::type_iterator it = element_filter.firstType(dim, ghost_type); Mesh::type_iterator last_type = element_filter.lastType(dim, ghost_type); for (; it != last_type; ++it) { const Array & shapes_derivatives = fem->getShapesDerivatives(*it, ghost_type); Array & elem_filter = element_filter(*it, ghost_type); if (elem_filter.getSize() == 0) continue; UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent(); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); UInt nb_quadrature_points = fem->getNbQuadraturePoints(*it, ghost_type); Array * shapesd_filtered = new Array(0, size_of_shapes_derivatives, "filtered shapesd"); FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered, - *it, ghost_type, elem_filter); + *it, ghost_type, elem_filter); Array::matrix_iterator shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, - nb_nodes_per_element); + nb_nodes_per_element); //Set stress vectors UInt stress_size = getTangentStiffnessVoigtSize(dim); //Set matrices B and BNL* UInt bt_s_size = dim * nb_nodes_per_element; Array * bt_s = new Array (nb_element * nb_quadrature_points, - bt_s_size, - "B^t*S"); + bt_s_size, + "B^t*S"); Array::matrix_iterator grad_u_it = this->gradu(*it, ghost_type).begin(dim, dim); Array::matrix_iterator grad_u_end = this->gradu(*it, ghost_type).end(dim, dim); Array::matrix_iterator stress_it = this->piola_kirchhoff_2(*it, ghost_type).begin(dim, dim); shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element); Array::matrix_iterator bt_s_it = bt_s->begin(bt_s_size, 1); Matrix S_vect(stress_size, 1); Matrix B_tensor(stress_size, bt_s_size); Matrix B2_tensor(stress_size, bt_s_size); for (; grad_u_it != grad_u_end; ++grad_u_it, ++stress_it, ++shapes_derivatives_filtered_it, ++bt_s_it) { Matrix & grad_u = *grad_u_it; Matrix & r_it = *bt_s_it; Matrix & S_it = *stress_it; SetCauchyStressArray (S_it, S_vect); VoigtHelper::transferBMatrixToSymVoigtBMatrix(*shapes_derivatives_filtered_it, B_tensor, nb_nodes_per_element); VoigtHelper::transferBMatrixToBL2(*shapes_derivatives_filtered_it, grad_u, B2_tensor, nb_nodes_per_element); B_tensor += B2_tensor; r_it.mul < true, false > (B_tensor, S_vect); } delete shapesd_filtered; /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array * r_e = new Array (nb_element, - bt_s_size, "r_e"); + bt_s_size, "r_e"); fem->integrate(*bt_s, *r_e, - bt_s_size, - *it, ghost_type, - elem_filter); + bt_s_size, + *it, ghost_type, + elem_filter); delete bt_s; - fem->assembleArray(*r_e, residual, - model->getDOFSynchronizer().getLocalDOFEquationNumbers(), - residual.getNbComponent(), - *it, ghost_type, elem_filter, -1); - + model->getDOFManager().assembleElementalArrayLocalArray(*r_e, internal_force, + *it, ghost_type, -1, elem_filter); delete r_e; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computeAllStressesFromTangentModuli(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { switch(spatial_dimension) { case 1: { computeAllStressesFromTangentModuli<1>(*it, ghost_type); break; } case 2: { computeAllStressesFromTangentModuli<2>(*it, ghost_type); break; } case 3: { computeAllStressesFromTangentModuli<3>(*it, ghost_type); break; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::computeAllStressesFromTangentModuli(const ElementType & type, - GhostType ghost_type) { + GhostType ghost_type) { AKANTU_DEBUG_IN(); const Array & shapes_derivatives = fem->getShapesDerivatives(type, ghost_type); Array & elem_filter = element_filter(type, ghost_type); Array & gradu_vect = gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = fem->getNbQuadraturePoints(type, ghost_type); gradu_vect.resize(nb_quadrature_points * nb_element); Array & disp = model->getDisplacement(); fem->gradientOnQuadraturePoints(disp, gradu_vect, - dim, type, ghost_type, elem_filter); + dim, type, ghost_type, elem_filter); UInt tangent_moduli_size = getTangentStiffnessVoigtSize(dim); Array * tangent_moduli_tensors = new Array(nb_element*nb_quadrature_points, tangent_moduli_size * tangent_moduli_size, - "tangent_moduli_tensors"); + "tangent_moduli_tensors"); tangent_moduli_tensors->clear(); computeTangentModuli(type, *tangent_moduli_tensors, ghost_type); Array * shapesd_filtered = new Array(0, dim* nb_nodes_per_element, "filtered shapesd"); FEEngine::filterElementalData(fem->getMesh(), shapes_derivatives, *shapesd_filtered, - type, ghost_type, elem_filter); + type, ghost_type, elem_filter); Array filtered_u(nb_element, nb_nodes_per_element * spatial_dimension); FEEngine::extractNodalToElementField(fem->getMesh(), disp, filtered_u, - type, ghost_type, elem_filter); + type, ghost_type, elem_filter); /// compute @f$\mathbf{D} \mathbf{B} \mathbf{u}@f$ Array::matrix_iterator shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element); Array::matrix_iterator D_it = tangent_moduli_tensors->begin(tangent_moduli_size, - tangent_moduli_size); + tangent_moduli_size); Array::matrix_iterator sigma_it = stress(type, ghost_type).begin(spatial_dimension, - spatial_dimension); + spatial_dimension); Array::vector_iterator u_it = filtered_u.begin(spatial_dimension * nb_nodes_per_element); Matrix B(tangent_moduli_size, spatial_dimension * nb_nodes_per_element); Vector Bu(tangent_moduli_size); Vector DBu(tangent_moduli_size); for (UInt e = 0; e < nb_element; ++e, ++u_it) { for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it, ++shapes_derivatives_filtered_it, ++sigma_it) { - Vector & u = *u_it; - Matrix & sigma = *sigma_it; - Matrix & D = *D_it; - - VoigtHelper::transferBMatrixToSymVoigtBMatrix(*shapes_derivatives_filtered_it, B, nb_nodes_per_element); - - Bu.mul(B, u); - DBu.mul(D, Bu); - - // Voigt notation to full symmetric tensor - for (UInt i = 0; i < dim; ++i) sigma(i, i) = DBu(i); - if(dim == 2) { - sigma(0,1) = sigma(1,0) = DBu(2); - } else if(dim == 3) { - sigma(1,2) = sigma(2,1) = DBu(3); - sigma(0,2) = sigma(2,0) = DBu(4); - sigma(0,1) = sigma(1,0) = DBu(5); - } + Vector & u = *u_it; + Matrix & sigma = *sigma_it; + Matrix & D = *D_it; + + VoigtHelper::transferBMatrixToSymVoigtBMatrix(*shapes_derivatives_filtered_it, B, nb_nodes_per_element); + + Bu.mul(B, u); + DBu.mul(D, Bu); + + // Voigt notation to full symmetric tensor + for (UInt i = 0; i < dim; ++i) sigma(i, i) = DBu(i); + if(dim == 2) { + sigma(0,1) = sigma(1,0) = DBu(2); + } else if(dim == 3) { + sigma(1,2) = sigma(2,1) = DBu(3); + sigma(0,2) = sigma(2,0) = DBu(4); + sigma(0,1) = sigma(1,0) = DBu(5); + } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computePotentialEnergyByElements() { AKANTU_DEBUG_IN(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension); Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension); for(; it != last_type; ++it) { computePotentialEnergy(*it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if(!potential_energy.exists(el_type, ghost_type)) { UInt nb_element = element_filter(el_type, ghost_type).getSize(); UInt nb_quadrature_points = fem->getNbQuadraturePoints(el_type, _not_ghost); potential_energy.alloc(nb_element * nb_quadrature_points, 1, - el_type, ghost_type); + el_type, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real Material::getPotentialEnergy() { AKANTU_DEBUG_IN(); Real epot = 0.; computePotentialEnergyByElements(); /// integrate the potential energy for each type of elements Mesh::type_iterator it = element_filter.firstType(spatial_dimension); Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension); for(; it != last_type; ++it) { epot += fem->integrate(potential_energy(*it, _not_ghost), *it, - _not_ghost, element_filter(*it, _not_ghost)); + _not_ghost, element_filter(*it, _not_ghost)); } AKANTU_DEBUG_OUT(); return epot; } /* -------------------------------------------------------------------------- */ Real Material::getPotentialEnergy(ElementType & type, UInt index) { AKANTU_DEBUG_IN(); Real epot = 0.; Vector epot_on_quad_points(fem->getNbQuadraturePoints(type)); computePotentialEnergyByElement(type, index, epot_on_quad_points); epot = fem->integrate(epot_on_quad_points, type, element_filter(type)(index)); AKANTU_DEBUG_OUT(); return epot; } /* -------------------------------------------------------------------------- */ Real Material::getEnergy(std::string type) { AKANTU_DEBUG_IN(); if(type == "potential") return getPotentialEnergy(); AKANTU_DEBUG_OUT(); return 0.; } /* -------------------------------------------------------------------------- */ Real Material::getEnergy(std::string energy_id, ElementType type, UInt index) { AKANTU_DEBUG_IN(); if(energy_id == "potential") return getPotentialEnergy(type, index); AKANTU_DEBUG_OUT(); return 0.; } /* -------------------------------------------------------------------------- */ void Material::computeQuadraturePointsCoordinates(ElementTypeMapArray & quadrature_points_coordinates, - const GhostType & ghost_type) const { + const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); const Mesh & mesh = this->model->getMesh(); Array nodes_coordinates(mesh.getNodes(), true); nodes_coordinates += this->model->getDisplacement(); Mesh::type_iterator it = this->element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = this->element_filter.lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { const Array & elem_filter = this->element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element == 0) continue; UInt nb_tot_quad = this->fem->getNbQuadraturePoints(*it, ghost_type) * nb_element; Array & quads = quadrature_points_coordinates(*it, ghost_type); quads.resize(nb_tot_quad); this->fem->interpolateOnQuadraturePoints(nodes_coordinates, - quads, spatial_dimension, - *it, ghost_type, elem_filter); + quads, spatial_dimension, + *it, ghost_type, elem_filter); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::initElementalFieldInterpolation(const ElementTypeMapArray & interpolation_points_coordinates) { AKANTU_DEBUG_IN(); const Mesh & mesh = fem->getMesh(); ElementTypeMapArray quadrature_points_coordinates("quadrature_points_coordinates_for_interpolation", getID()); mesh.initElementTypeMapArray(quadrature_points_coordinates, spatial_dimension, spatial_dimension); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; computeQuadraturePointsCoordinates(quadrature_points_coordinates, ghost_type); Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last = element_filter.lastType(spatial_dimension, ghost_type); for (; it != last; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type, ghost_type); if (nb_element == 0) continue; const Array & interp_points_coord = interpolation_points_coordinates(type, ghost_type); UInt nb_interpolation_points_per_elem = interp_points_coord.getSize() / nb_element; AKANTU_DEBUG_ASSERT(interp_points_coord.getSize() % nb_element == 0, - "Number of interpolation points is wrong"); + "Number of interpolation points is wrong"); -#define AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD(type) \ +#define AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD(type) \ initElementalFieldInterpolation(quadrature_points_coordinates(type, ghost_type), \ - interp_points_coord, \ - nb_interpolation_points_per_elem, \ - ghost_type) \ + interp_points_coord, \ + nb_interpolation_points_per_elem, \ + ghost_type) \ AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD); #undef AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::initElementalFieldInterpolation(const Array & quad_coordinates, - const Array & interpolation_points_coordinates, - const UInt nb_interpolation_points_per_elem, - const GhostType ghost_type) { + const Array & interpolation_points_coordinates, + const UInt nb_interpolation_points_per_elem, + const GhostType ghost_type) { AKANTU_DEBUG_IN(); Array & elem_fil = element_filter(type, ghost_type); UInt nb_element = elem_fil.getSize(); UInt nb_quad_per_element = fem->getNbQuadraturePoints(type, ghost_type); if(!interpolation_inverse_coordinates.exists(type, ghost_type)) interpolation_inverse_coordinates.alloc(nb_element, - nb_quad_per_element*nb_quad_per_element, - type, ghost_type); + nb_quad_per_element*nb_quad_per_element, + type, ghost_type); else interpolation_inverse_coordinates(type, ghost_type).resize(nb_element); if(!interpolation_points_matrices.exists(type, ghost_type)) interpolation_points_matrices.alloc(nb_element, - nb_interpolation_points_per_elem * nb_quad_per_element, - type, ghost_type); + nb_interpolation_points_per_elem * nb_quad_per_element, + type, ghost_type); else interpolation_points_matrices(type, ghost_type).resize(nb_element); Array & interp_inv_coord = interpolation_inverse_coordinates(type, ghost_type); Array & interp_points_mat = interpolation_points_matrices(type, ghost_type); Matrix quad_coord_matrix(nb_quad_per_element, nb_quad_per_element); Array::const_matrix_iterator quad_coords_it = quad_coordinates.begin_reinterpret(spatial_dimension, - nb_quad_per_element, - nb_element); + nb_quad_per_element, + nb_element); Array::const_matrix_iterator points_coords_begin = interpolation_points_coordinates.begin_reinterpret(spatial_dimension, - nb_interpolation_points_per_elem, - interpolation_points_coordinates.getSize() / nb_interpolation_points_per_elem); + nb_interpolation_points_per_elem, + interpolation_points_coordinates.getSize() / nb_interpolation_points_per_elem); Array::matrix_iterator inv_quad_coord_it = interp_inv_coord.begin(nb_quad_per_element, nb_quad_per_element); Array::matrix_iterator inv_points_mat_it = interp_points_mat.begin(nb_interpolation_points_per_elem, nb_quad_per_element); /// loop over the elements of the current material and element type for (UInt el = 0; el < nb_element; ++el, ++inv_quad_coord_it, - ++inv_points_mat_it, ++quad_coords_it) { + ++inv_points_mat_it, ++quad_coords_it) { /// matrix containing the quadrature points coordinates const Matrix & quad_coords = *quad_coords_it; /// matrix to store the matrix inversion result Matrix & inv_quad_coord_matrix = *inv_quad_coord_it; /// insert the quad coordinates in a matrix compatible with the interpolation buildElementalFieldInterpolationCoodinates(quad_coords, - quad_coord_matrix); + quad_coord_matrix); /// invert the interpolation matrix inv_quad_coord_matrix.inverse(quad_coord_matrix); /// matrix containing the interpolation points coordinates const Matrix & points_coords = points_coords_begin[elem_fil(el)]; /// matrix to store the interpolation points coordinates /// compatible with these functions Matrix & inv_points_coord_matrix = *inv_points_mat_it; /// insert the quad coordinates in a matrix compatible with the interpolation buildElementalFieldInterpolationCoodinates(points_coords, - inv_points_coord_matrix); + inv_points_coord_matrix); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::interpolateStress(ElementTypeMapArray & result, - const GhostType ghost_type) { + const GhostType ghost_type) { interpolateElementalField(stress, result, ghost_type); } /* -------------------------------------------------------------------------- */ void Material::interpolateElementalField(const ElementTypeMapArray & field, - ElementTypeMapArray & result, - const GhostType ghost_type) { + ElementTypeMapArray & result, + const GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last = element_filter.lastType(spatial_dimension, ghost_type); for (; it != last; ++it) { ElementType type = *it; Array & elem_fil = element_filter(type, ghost_type); UInt nb_element = elem_fil.getSize(); UInt nb_quad_per_element = fem->getNbQuadraturePoints(type, ghost_type); const Array & field_vec = field(type, ghost_type); Array & result_vec = result(type, ghost_type); Matrix coefficients(nb_quad_per_element, field_vec.getNbComponent()); const Array & interp_inv_coord = interpolation_inverse_coordinates(type, ghost_type); const Array & interp_points_coord = interpolation_points_matrices(type, ghost_type); UInt nb_interpolation_points_per_elem = interp_points_coord.getNbComponent() / nb_quad_per_element; Array::const_matrix_iterator field_it = field_vec.begin_reinterpret(field_vec.getNbComponent(), - nb_quad_per_element, - nb_element); + nb_quad_per_element, + nb_element); Array::const_matrix_iterator interpolation_points_coordinates_it = interp_points_coord.begin(nb_interpolation_points_per_elem, nb_quad_per_element); Array::matrix_iterator result_begin = result_vec.begin_reinterpret(field_vec.getNbComponent(), - nb_interpolation_points_per_elem, - result_vec.getSize() / nb_interpolation_points_per_elem); + nb_interpolation_points_per_elem, + result_vec.getSize() / nb_interpolation_points_per_elem); Array::const_matrix_iterator inv_quad_coord_it = interp_inv_coord.begin(nb_quad_per_element, nb_quad_per_element); /// loop over the elements of the current material and element type for (UInt el = 0; el < nb_element; - ++el, ++field_it, ++inv_quad_coord_it, ++interpolation_points_coordinates_it) { + ++el, ++field_it, ++inv_quad_coord_it, ++interpolation_points_coordinates_it) { /** * matrix containing the inversion of the quadrature points' * coordinates */ const Matrix & inv_quad_coord_matrix = *inv_quad_coord_it; /** * multiply it by the field values over quadrature points to get * the interpolation coefficients */ coefficients.mul(inv_quad_coord_matrix, *field_it); /// matrix containing the points' coordinates const Matrix & coord = *interpolation_points_coordinates_it; /// multiply the coordinates matrix by the coefficients matrix and store the result Matrix res(result_begin[elem_fil(el)]); res.mul(coefficients, coord); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::interpolateStressOnFacets(ElementTypeMapArray & result, - const GhostType ghost_type) { + const GhostType ghost_type) { interpolateElementalFieldOnFacets(stress, result, ghost_type); } /* -------------------------------------------------------------------------- */ void Material::interpolateElementalFieldOnFacets(const ElementTypeMapArray & field, - ElementTypeMapArray & result, - const GhostType ghost_type) { + ElementTypeMapArray & result, + const GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt sp2 = spatial_dimension * spatial_dimension; const Mesh & mesh = this->model->getMesh(); const Mesh & mesh_facets = mesh.getMeshFacets(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last = element_filter.lastType(spatial_dimension, ghost_type); for (; it != last; ++it) { ElementType type = *it; Array & elem_fil = element_filter(type, ghost_type); UInt nb_element = elem_fil.getSize(); UInt nb_quad_per_element = fem->getNbQuadraturePoints(type, ghost_type); const Array & field_vec = field(type, ghost_type); Matrix coefficients(nb_quad_per_element, field_vec.getNbComponent()); const Array & interp_inv_coord = interpolation_inverse_coordinates(type, ghost_type); const Array & interp_points_coord = interpolation_points_matrices(type, ghost_type); UInt nb_interpolation_points_per_elem = interp_points_coord.getNbComponent() / nb_quad_per_element; Array::const_matrix_iterator field_it = field_vec.begin_reinterpret(field_vec.getNbComponent(), - nb_quad_per_element, - nb_element); + nb_quad_per_element, + nb_element); Array::const_matrix_iterator interpolation_points_coordinates_it = interp_points_coord.begin(nb_interpolation_points_per_elem, nb_quad_per_element); Array::const_matrix_iterator inv_quad_coord_it = interp_inv_coord.begin(nb_quad_per_element, nb_quad_per_element); Matrix result_tmp(sp2, nb_interpolation_points_per_elem); const Array & facet_to_element = mesh_facets.getSubelementToElement(type, ghost_type); ElementType type_facet = Mesh::getFacetType(type); UInt nb_facet_per_elem = facet_to_element.getNbComponent(); UInt nb_quad_per_facet = nb_interpolation_points_per_elem / nb_facet_per_elem; Element element_for_comparison(type, 0, ghost_type); const Array< std::vector > * element_to_facet = NULL; GhostType current_ghost_type = _casper; Array * result_vec = NULL; /// loop over the elements of the current material and element type for (UInt el = 0; el < nb_element; - ++el, ++field_it, ++inv_quad_coord_it, ++interpolation_points_coordinates_it) { + ++el, ++field_it, ++inv_quad_coord_it, ++interpolation_points_coordinates_it) { /** * matrix containing the inversion of the quadrature points' * coordinates */ const Matrix & inv_quad_coord_matrix = *inv_quad_coord_it; /** * multiply it by the field values over quadrature points to get * the interpolation coefficients */ coefficients.mul(inv_quad_coord_matrix, *field_it); /// matrix containing the points' coordinates const Matrix & coord = *interpolation_points_coordinates_it; /// multiply the coordinates matrix by the coefficients matrix and store the result result_tmp.mul(coefficients, coord); UInt global_el = elem_fil(el); element_for_comparison.element = global_el; for (UInt f = 0; f < nb_facet_per_elem; ++f) { - Element facet_elem = facet_to_element(global_el, f); - UInt global_facet = facet_elem.element; - if (facet_elem.ghost_type != current_ghost_type) { - current_ghost_type = facet_elem.ghost_type; - element_to_facet = &mesh_facets.getElementToSubelement(type_facet, - current_ghost_type); - result_vec = &result(type_facet, current_ghost_type); - } - - bool is_second_element = (*element_to_facet)(global_facet)[0] != element_for_comparison; - - for (UInt q = 0; q < nb_quad_per_facet; ++q) { - Vector result_local(result_vec->storage() - + (global_facet * nb_quad_per_facet + q) * result_vec->getNbComponent() - + is_second_element * sp2, - sp2); - - result_local = result_tmp(f * nb_quad_per_facet + q); - } + Element facet_elem = facet_to_element(global_el, f); + UInt global_facet = facet_elem.element; + if (facet_elem.ghost_type != current_ghost_type) { + current_ghost_type = facet_elem.ghost_type; + element_to_facet = &mesh_facets.getElementToSubelement(type_facet, + current_ghost_type); + result_vec = &result(type_facet, current_ghost_type); + } + + bool is_second_element = (*element_to_facet)(global_facet)[0] != element_for_comparison; + + for (UInt q = 0; q < nb_quad_per_facet; ++q) { + Vector result_local(result_vec->storage() + + (global_facet * nb_quad_per_facet + q) * result_vec->getNbComponent() + + is_second_element * sp2, + sp2); + + result_local = result_tmp(f * nb_quad_per_facet + q); + } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template const Array & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); return NULL; } /* -------------------------------------------------------------------------- */ template Array & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); return NULL; } /* -------------------------------------------------------------------------- */ template<> const Array & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) const { std::stringstream sstr; std::string ghost_id = ""; if (ghost_type == _ghost) ghost_id = ":ghost"; sstr << getID() << ":" << vect_id << ":" << type << ghost_id; ID fvect_id = sstr.str(); try { return Memory::getArray(fvect_id); } catch(debug::Exception & e) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" < Array & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) { std::stringstream sstr; std::string ghost_id = ""; if (ghost_type == _ghost) ghost_id = ":ghost"; sstr << getID() << ":" << vect_id << ":" << type << ghost_id; ID fvect_id = sstr.str(); try { return Memory::getArray(fvect_id); } catch(debug::Exception & e) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain a vector " << vect_id << "(" << fvect_id << ") [" << e << "]"); } } /* -------------------------------------------------------------------------- */ template const InternalField & Material::getInternal(const ID & int_id) const { AKANTU_DEBUG_TO_IMPLEMENT(); return NULL; } /* -------------------------------------------------------------------------- */ template InternalField & Material::getInternal(const ID & int_id) { AKANTU_DEBUG_TO_IMPLEMENT(); return NULL; } /* -------------------------------------------------------------------------- */ template<> const InternalField & Material::getInternal(const ID & int_id) const { std::map *>::const_iterator it = internal_vectors_real.find(getID() + ":" + int_id); if(it == internal_vectors_real.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() - << ") does not contain an internal " - << int_id << " (" << (getID() + ":" + int_id) << ")"); + << ") does not contain an internal " + << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ template<> InternalField & Material::getInternal(const ID & int_id) { std::map *>::iterator it = internal_vectors_real.find(getID() + ":" + int_id); if(it == internal_vectors_real.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() - << ") does not contain an internal " - << int_id << " (" << (getID() + ":" + int_id) << ")"); + << ") does not contain an internal " + << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ template<> const InternalField & Material::getInternal(const ID & int_id) const { std::map *>::const_iterator it = internal_vectors_uint.find(getID() + ":" + int_id); if(it == internal_vectors_uint.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() - << ") does not contain an internal " - << int_id << " (" << (getID() + ":" + int_id) << ")"); + << ") does not contain an internal " + << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ template<> InternalField & Material::getInternal(const ID & int_id) { std::map *>::iterator it = internal_vectors_uint.find(getID() + ":" + int_id); if(it == internal_vectors_uint.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() - << ") does not contain an internal " - << int_id << " (" << (getID() + ":" + int_id) << ")"); + << ") does not contain an internal " + << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ void Material::addElements(const Array & elements_to_add) { AKANTU_DEBUG_IN(); UInt mat_id = model->getInternalIndexFromID(getID()); Array::const_iterator el_begin = elements_to_add.begin(); Array::const_iterator el_end = elements_to_add.end(); for(;el_begin != el_end; ++el_begin) { const Element & element = *el_begin; Array & mat_indexes = model->getMaterialByElement (element.type, element.ghost_type); Array & mat_loc_num = model->getMaterialLocalNumbering(element.type, element.ghost_type); UInt index = this->addElement(element.type, element.element, element.ghost_type); mat_indexes(element.element) = mat_id; mat_loc_num(element.element) = index; } this->resizeInternals(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::removeElements(const Array & elements_to_remove) { AKANTU_DEBUG_IN(); Array::const_iterator el_begin = elements_to_remove.begin(); Array::const_iterator el_end = elements_to_remove.end(); if(el_begin==el_end) return; ElementTypeMapArray material_local_new_numbering("remove mat filter elem", getID()); 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; ElementTypeMapArray::type_iterator it = element_filter.firstType(_all_dimensions, ghost_type, _ek_not_defined); ElementTypeMapArray::type_iterator end = element_filter.lastType(_all_dimensions, ghost_type, _ek_not_defined); for(; it != end; ++it) { ElementType type = *it; element.type = type; Array & elem_filter = this->element_filter(type, ghost_type); Array & mat_loc_num = this->model->getMaterialLocalNumbering(type, ghost_type); if(!material_local_new_numbering.exists(type, ghost_type)) - material_local_new_numbering.alloc(elem_filter.getSize(), 1, type, ghost_type); + material_local_new_numbering.alloc(elem_filter.getSize(), 1, type, ghost_type); Array & mat_renumbering = material_local_new_numbering(type, ghost_type); UInt nb_element = elem_filter.getSize(); element.kind=(*el_begin).kind; Array elem_filter_tmp; UInt new_id = 0; for (UInt el = 0; el < nb_element; ++el) { - element.element = elem_filter(el); + element.element = elem_filter(el); - if(std::find(el_begin, el_end, element) == el_end) { - elem_filter_tmp.push_back(element.element); + if(std::find(el_begin, el_end, element) == el_end) { + elem_filter_tmp.push_back(element.element); - mat_renumbering(el) = new_id; - mat_loc_num(element.element) = new_id; - ++new_id; - } else { - mat_renumbering(el) = UInt(-1); - } + mat_renumbering(el) = new_id; + mat_loc_num(element.element) = new_id; + ++new_id; + } else { + mat_renumbering(el) = UInt(-1); + } } elem_filter.resize(elem_filter_tmp.getSize()); elem_filter.copy(elem_filter_tmp); } } for (std::map *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->removeQuadraturePoints(material_local_new_numbering); for (std::map *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->removeQuadraturePoints(material_local_new_numbering); for (std::map *>::iterator it = internal_vectors_bool.begin(); it != internal_vectors_bool.end(); ++it) it->second->removeQuadraturePoints(material_local_new_numbering); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::resizeInternals() { AKANTU_DEBUG_IN(); for (std::map *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->resize(); for (std::map *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->resize(); for (std::map *>::iterator it = internal_vectors_bool.begin(); it != internal_vectors_bool.end(); ++it) it->second->resize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::onElementsAdded(__attribute__((unused)) const Array & element_list, - __attribute__((unused)) const NewElementsEvent & event) { + __attribute__((unused)) const NewElementsEvent & event) { this->resizeInternals(); } /* -------------------------------------------------------------------------- */ void Material::onElementsRemoved(const Array & element_list, - const ElementTypeMapArray & new_numbering, - __attribute__((unused)) const RemovedElementsEvent & event) { + const ElementTypeMapArray & new_numbering, + __attribute__((unused)) const RemovedElementsEvent & event) { UInt my_num = model->getInternalIndexFromID(getID()); ElementTypeMapArray material_local_new_numbering("remove mat filter elem", getID()); Array::const_iterator el_begin = element_list.begin(); Array::const_iterator el_end = element_list.end(); for (ghost_type_t::iterator g = ghost_type_t::begin(); g != ghost_type_t::end(); ++g) { GhostType gt = *g; ElementTypeMapArray::type_iterator it = new_numbering.firstType(_all_dimensions, gt, _ek_not_defined); ElementTypeMapArray::type_iterator end = new_numbering.lastType (_all_dimensions, gt, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; if(element_filter.exists(type, gt) && element_filter(type, gt).getSize()){ - Array & elem_filter = element_filter(type, gt); - - Array & mat_indexes = this->model->getMaterialByElement (*it, gt); - Array & mat_loc_num = this->model->getMaterialLocalNumbering(*it, gt); - UInt nb_element = this->model->getMesh().getNbElement(type, gt); - - // all materials will resize of the same size... - mat_indexes.resize(nb_element); - mat_loc_num.resize(nb_element); - - if(!material_local_new_numbering.exists(type, gt)) - material_local_new_numbering.alloc(elem_filter.getSize(), 1, type, gt); - - Array & mat_renumbering = material_local_new_numbering(type, gt); - const Array & renumbering = new_numbering(type, gt); - Array elem_filter_tmp; - UInt ni = 0; - Element el; - el.type = type; - el.ghost_type = gt; - el.kind = Mesh::getKind(type); - for (UInt i = 0; i < elem_filter.getSize(); ++i) { - el.element = elem_filter(i); - if(std::find(el_begin, el_end, el) == el_end) { - UInt new_el = renumbering(el.element); - AKANTU_DEBUG_ASSERT(new_el != UInt(-1), "A not removed element as been badly renumbered"); - elem_filter_tmp.push_back(new_el); - mat_renumbering(i) = ni; - - mat_indexes(new_el) = my_num; - mat_loc_num(new_el) = ni; - ++ni; - } else { - mat_renumbering(i) = UInt(-1); - } - } - - elem_filter.resize(elem_filter_tmp.getSize()); - elem_filter.copy(elem_filter_tmp); + Array & elem_filter = element_filter(type, gt); + + Array & mat_indexes = this->model->getMaterialByElement (*it, gt); + Array & mat_loc_num = this->model->getMaterialLocalNumbering(*it, gt); + UInt nb_element = this->model->getMesh().getNbElement(type, gt); + + // all materials will resize of the same size... + mat_indexes.resize(nb_element); + mat_loc_num.resize(nb_element); + + if(!material_local_new_numbering.exists(type, gt)) + material_local_new_numbering.alloc(elem_filter.getSize(), 1, type, gt); + + Array & mat_renumbering = material_local_new_numbering(type, gt); + const Array & renumbering = new_numbering(type, gt); + Array elem_filter_tmp; + UInt ni = 0; + Element el; + el.type = type; + el.ghost_type = gt; + el.kind = Mesh::getKind(type); + for (UInt i = 0; i < elem_filter.getSize(); ++i) { + el.element = elem_filter(i); + if(std::find(el_begin, el_end, el) == el_end) { + UInt new_el = renumbering(el.element); + AKANTU_DEBUG_ASSERT(new_el != UInt(-1), "A not removed element as been badly renumbered"); + elem_filter_tmp.push_back(new_el); + mat_renumbering(i) = ni; + + mat_indexes(new_el) = my_num; + mat_loc_num(new_el) = ni; + ++ni; + } else { + mat_renumbering(i) = UInt(-1); + } + } + + elem_filter.resize(elem_filter_tmp.getSize()); + elem_filter.copy(elem_filter_tmp); } } } for (std::map *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->removeQuadraturePoints(material_local_new_numbering); for (std::map *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->removeQuadraturePoints(material_local_new_numbering); for (std::map *>::iterator it = internal_vectors_bool.begin(); it != internal_vectors_bool.end(); ++it) it->second->removeQuadraturePoints(material_local_new_numbering); } /* -------------------------------------------------------------------------- */ void Material::onBeginningSolveStep(const AnalysisMethod & method) { this->savePreviousState(); } /* -------------------------------------------------------------------------- */ void Material::onEndSolveStep(const AnalysisMethod & method) { ElementTypeMapArray::type_iterator it = this->element_filter.firstType(_all_dimensions, _not_ghost, _ek_not_defined); ElementTypeMapArray::type_iterator end = element_filter.lastType(_all_dimensions, _not_ghost, _ek_not_defined); for(; it != end; ++it) { this->updateEnergies(*it, _not_ghost); } } /* -------------------------------------------------------------------------- */ void Material::onDamageIteration() { this->savePreviousState(); } /* -------------------------------------------------------------------------- */ void Material::onDamageUpdate() { ElementTypeMapArray::type_iterator it = this->element_filter.firstType(_all_dimensions, _not_ghost, _ek_not_defined); ElementTypeMapArray::type_iterator end = element_filter.lastType(_all_dimensions, _not_ghost, _ek_not_defined); for(; it != end; ++it) { if(!this->potential_energy.exists(*it, _not_ghost)) { UInt nb_element = this->element_filter(*it, _not_ghost).getSize(); UInt nb_quadrature_points = this->fem->getNbQuadraturePoints(*it, _not_ghost); this->potential_energy.alloc(nb_element * nb_quadrature_points, 1, - *it, _not_ghost); + *it, _not_ghost); } this->updateEnergiesAfterDamage(*it, _not_ghost); } } /* -------------------------------------------------------------------------- */ void Material::onDump(){ if(this->isFiniteDeformation()) this->computeAllCauchyStresses(_not_ghost); } /* -------------------------------------------------------------------------- */ void Material::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); std::string type = getID().substr(getID().find_last_of(":") + 1); stream << space << "Material " << type << " [" << std::endl; Parsable::printself(stream, indent); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ inline ElementTypeMap Material::getInternalDataPerElem(const ID & id, const ElementKind & element_kind, const ID & fe_engine_id) const { std::map *>::const_iterator internal_array = internal_vectors_real.find(this->getID()+":"+id); if (internal_array == internal_vectors_real.end() || internal_array->second->getElementKind() != element_kind) AKANTU_EXCEPTION("Cannot find internal field " << id << " in material " << this->name); InternalField & internal = *internal_array->second; InternalField::type_iterator it = internal.firstType(internal.getSpatialDimension(), - _not_ghost, element_kind); + _not_ghost, element_kind); InternalField::type_iterator last_type = internal.lastType(internal.getSpatialDimension(), - _not_ghost, element_kind); + _not_ghost, element_kind); ElementTypeMap res; for(; it != last_type; ++it) { UInt nb_quadrature_points = 0; nb_quadrature_points = model->getFEEngine(fe_engine_id).getNbQuadraturePoints(*it); res(*it) = internal.getNbComponent() * nb_quadrature_points; } return res; } /* -------------------------------------------------------------------------- */ void Material::flattenInternal(const std::string & field_id, - ElementTypeMapArray & internal_flat, - const GhostType ghost_type, - ElementKind element_kind) const { + ElementTypeMapArray & internal_flat, + const GhostType ghost_type, + ElementKind element_kind) const { this->flattenInternalIntern(field_id, internal_flat, - this->spatial_dimension, - ghost_type, element_kind); + this->spatial_dimension, + ghost_type, element_kind); } /* -------------------------------------------------------------------------- */ void Material::flattenInternalIntern(const std::string & field_id, - ElementTypeMapArray & internal_flat, - UInt spatial_dimension, - const GhostType ghost_type, - ElementKind element_kind, - const ElementTypeMapArray * element_filter, - const Mesh * mesh) const { + ElementTypeMapArray & internal_flat, + UInt spatial_dimension, + const GhostType ghost_type, + ElementKind element_kind, + const ElementTypeMapArray * element_filter, + const Mesh * mesh) const { typedef ElementTypeMapArray::type_iterator iterator; if(element_filter == NULL) element_filter = &(this->element_filter); if(mesh == NULL) mesh = &(this->model->mesh); iterator tit = element_filter->firstType(spatial_dimension, - ghost_type, - element_kind); + ghost_type, + element_kind); iterator end = element_filter->lastType(spatial_dimension, - ghost_type, - element_kind); + ghost_type, + element_kind); for (; tit != end; ++tit) { ElementType type = *tit; try { __attribute__((unused)) const Array & src_vect - = this->getArray(field_id, type, ghost_type); + = this->getArray(field_id, type, ghost_type); } catch(debug::Exception & e) { continue; } const Array & src_vect = this->getArray(field_id, type, ghost_type); const Array & filter = (*element_filter)(type, ghost_type); // total number of elements for a given type UInt nb_element = mesh->getNbElement(type,ghost_type); // number of filtered elements UInt nb_element_src = filter.getSize(); // number of quadrature points per elem UInt nb_quad_per_elem = 0; // number of data per quadrature point UInt nb_data_per_quad = src_vect.getNbComponent(); if (!internal_flat.exists(type,ghost_type)) { internal_flat.alloc(nb_element * nb_quad_per_elem, - nb_data_per_quad, - type, - ghost_type); + nb_data_per_quad, + type, + ghost_type); } if (nb_element_src == 0) continue; nb_quad_per_elem = (src_vect.getSize() / nb_element_src); // number of data per element UInt nb_data = nb_quad_per_elem * src_vect.getNbComponent(); Array & dst_vect = internal_flat(type,ghost_type); dst_vect.resize(nb_element*nb_quad_per_elem); Array::const_scalar_iterator it = filter.begin(); Array::const_scalar_iterator end = filter.end(); Array::const_vector_iterator it_src = src_vect.begin_reinterpret(nb_data, nb_element_src); Array::vector_iterator it_dst = dst_vect.begin_reinterpret(nb_data, nb_element); for (; it != end ; ++it,++it_src) { it_dst[*it] = *it_src; } } }; /* -------------------------------------------------------------------------- */ /// extrapolate internal values void Material::extrapolateInternal(const ID & id, const Element & element, const Matrix & point, Matrix & extrapolated) { if (this->isInternal(id, element.kind)) { UInt nb_element = this->element_filter(element.type, element.ghost_type).getSize(); const ID name = this->getID() + ":" + id; UInt nb_quads = this->internal_vectors_real[name]->getFEEngine().getNbQuadraturePoints(element.type, element.ghost_type); const Array & internal = this->getArray(id, element.type, element.ghost_type); UInt nb_component = internal.getNbComponent(); Array::const_matrix_iterator internal_it = internal.begin_reinterpret(nb_component, nb_quads, nb_element); Element local_element = this->convertToLocalElement(element); /// instead of really extrapolating, here the value of the first GP /// is copied into the result vector. This works only for linear /// elements /// @todo extrapolate!!!! const Matrix & values = internal_it[local_element.element]; UInt index = 0; Vector tmp(nb_component); for (UInt j = 0; j < values.cols(); ++j) { tmp = values(j); if (tmp.norm() > 0) { - index = j; - continue; + index = j; + continue; } } for (UInt i = 0; i < extrapolated.size(); ++i) { extrapolated(i) = values(index); } } else { Matrix default_values(extrapolated.rows(), extrapolated.cols(), 0.); extrapolated = default_values; } } __END_AKANTU__ diff --git a/src/model/solid_mechanics/solid_mechanics_model.cc b/src/model/solid_mechanics/solid_mechanics_model.cc index 5b5a93082..635e203e4 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.cc +++ b/src/model/solid_mechanics/solid_mechanics_model.cc @@ -1,1400 +1,1366 @@ /** * @file solid_mechanics_model.cc * * @author Guillaume Anciaux * @author David Simon Kammer * @author Aurelia Isabel Cuba Ramos * @author Daniel Pino Muñoz * @author Nicolas Richart * * @date creation: Tue Jul 27 2010 * @date last modification: Fri Sep 19 2014 * * @brief Implementation of the SolidMechanicsModel class * * @section LICENSE * * Copyright (©) 2010-2012, 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 "aka_math.hh" #include "aka_common.hh" #include "solid_mechanics_model.hh" + #include "group_manager_inline_impl.cc" -#include "dumpable_inline_impl.hh" -#include "integration_scheme_2nd_order.hh" #include "element_group.hh" - #include "static_communicator.hh" -#include "dof_synchronizer.hh" -#include "element_group.hh" - -#include - +#include "dumpable_inline_impl.hh" #ifdef AKANTU_USE_IOHELPER # include "dumper_field.hh" # include "dumper_paraview.hh" # include "dumper_homogenizing_field.hh" # include "dumper_material_internal_field.hh" # include "dumper_elemental_field.hh" # include "dumper_material_padders.hh" # include "dumper_element_partition.hh" # include "dumper_iohelper.hh" #endif +/* -------------------------------------------------------------------------- */ +#include +/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ __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), - BoundaryCondition(), - time_step(NAN), f_m2a(1.0), - mass_matrix(NULL), - velocity_damping_matrix(NULL), - stiffness_matrix(NULL), - jacobian_matrix(NULL), - material_index("material index", id), - material_local_numbering("material local numbering", id), - material_selector(new DefaultMaterialSelector(material_index)), - is_default_material_selector(true), - increment_flag(false), synch_parallel(NULL), - are_materials_instantiated(false) { - +SolidMechanicsModel::SolidMechanicsModel(Mesh & mesh, UInt dim, const ID & id, + const MemoryID & memory_id) + : Model(mesh, dim, id, memory_id), BoundaryCondition(), + time_step(NAN), f_m2a(1.0), displacement(NULL), + previous_displacement(NULL), increment(NULL), mass(NULL), velocity(NULL), + acceleration(NULL), increment_acceleration(NULL), external_force(NULL), + internal_force(NULL), blocked_dofs(NULL), current_position(NULL), + material_index("material index", id), + material_local_numbering("material local numbering", id), materials(0), + material_selector(new DefaultMaterialSelector(material_index)), + is_default_material_selector(true), increment_flag(false), + synch_parallel(NULL), are_materials_instantiated(false) { AKANTU_DEBUG_IN(); - createSynchronizerRegistry(this); + this->createSynchronizerRegistry(this); - registerFEEngineObject("SolidMechanicsFEEngine", mesh, spatial_dimension); + this->registerFEEngineObject("SolidMechanicsFEEngine", mesh, + spatial_dimension); - this->displacement = NULL; - this->mass = NULL; - this->velocity = NULL; - this->acceleration = NULL; - this->force = NULL; - this->internal_force = NULL; - this->residual = NULL; - this->blocked_dofs = NULL; - - this->increment = NULL; - this->increment_acceleration = NULL; - - this->dof_synchronizer = NULL; - - this->previous_displacement = NULL; - - materials.clear(); - - mesh.registerEventHandler(*this); + this->mesh.registerEventHandler(*this); #if defined(AKANTU_USE_IOHELPER) this->mesh.registerDumper("paraview_all", id, true); this->mesh.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 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) this->mesh.getDumper().setTimeStep(time_step); #endif } /* -------------------------------------------------------------------------- */ /* Initialization */ /* -------------------------------------------------------------------------- */ /** * This function groups many of the initialization in on function. For most of * basics case the function should be enough. The functions initialize the * model, the internal vectors, set them to 0, and depending on the parameters * it also initialize the explicit or implicit solver. * * @param material_file the file containing the materials to use * @param method the analysis method wanted. See the akantu::AnalysisMethod for * the different possibilities */ void SolidMechanicsModel::initFull(const ModelOptions & options) { Model::initFull(options); const SolidMechanicsModelOptions & smm_options = dynamic_cast(options); method = smm_options.analysis_method; // initialize the vectors initArrays(); // set the initial condition to 0 - force->clear(); + external_force->clear(); velocity->clear(); acceleration->clear(); displacement->clear(); // initialize pbc 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(this->parser->getLastParsedFile() != "") { instantiateMaterials(); } if(!smm_options.no_init_materials) { initMaterials(); } if(increment_flag) - initBC(*this, *displacement, *increment, *force); + this->initBC(*this, *displacement, *increment, *external_force); else - initBC(*this, *displacement, *force); + this->initBC(*this, *displacement, *external_force); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initParallel(MeshPartition * partition, - DataAccessor * data_accessor) { + 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); synch_registry->registerSynchronizer(*synch_parallel, _gst_for_dump); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initFEEngineBoundary() { FEEngine & fem_boundary = getFEEngineBoundary(); fem_boundary.initShapeFunctions(_not_ghost); fem_boundary.initShapeFunctions(_ghost); fem_boundary.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_ifor; sstr_forc << id << ":internal_force"; - std::stringstream sstr_resi; sstr_resi << id << ":residual"; std::stringstream sstr_boun; sstr_boun << id << ":blocked_dofs"; - 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)); - internal_force = &(alloc(sstr_ifor.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); - residual = &(alloc(sstr_resi.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); - blocked_dofs = &(alloc(sstr_boun.str(), nb_nodes, spatial_dimension, false)); + /* ------------------------------------------------------------------------ */ + //for static + this->displacement = &(alloc(sstr_disp.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); + this->internal_force = &(alloc(sstr_ifor.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); + this->external_force = &(alloc(sstr_forc.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); + this->blocked_dofs = &(alloc(sstr_boun.str(), nb_nodes, spatial_dimension, false)); + + this->getDOFManager().registerDOFs("displacements", *this->displacement, _dst_nodal); + this->getDOFManager().registerBlockedDOFs("displacements", *this->blocked_dofs); std::stringstream sstr_curp; sstr_curp << id << ":current_position"; - current_position = &(alloc(sstr_curp.str(), 0, spatial_dimension, REAL_INIT_VALUE)); + this->current_position = &(alloc(sstr_curp.str(), 0, spatial_dimension, REAL_INIT_VALUE)); + + /* ------------------------------------------------------------------------ */ + // for dynamic + std::stringstream sstr_velo; sstr_velo << id << ":velocity"; + std::stringstream sstr_acce; sstr_acce << id << ":acceleration"; + this->velocity = &(alloc(sstr_velo.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); + this->acceleration = &(alloc(sstr_acce.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); + + this->getDOFManager().registerDOFsDerivative("displacements", 1, *this->velocity); + this->getDOFManager().registerDOFsDerivative("displacements", 2, *this->acceleration); 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); - material_index.alloc(nb_element, 1, *it, gt); - material_local_numbering.alloc(nb_element, 1, *it, gt); + this->material_index.alloc(nb_element, 1, *it, gt); + this->material_local_numbering.alloc(nb_element, 1, *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 getFEEngine().initShapeFunctions(_not_ghost); getFEEngine().initShapeFunctions(_ghost); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initPBC() { Model::initPBC(); registerPBCSynchronizer(); // as long as there are ones on the diagonal of the matrix, we can put boudandary true for slaves std::map::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); synch_registry->registerSynchronizer(*synch, _gst_for_dump); 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(); + this->current_position->copy(this->mesh.getNodes()); + + Array::vector_iterator cpos_it = this->current_position->begin(spatial_dimension); + Array::vector_iterator cpos_end = this->current_position->end(spatial_dimension); + Array::const_vector_iterator disp_it = this->displacement->begin(spatial_dimension); - /// 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++; + for (; cpos_it != cpos_end; ++cpos_it, ++disp_it) { + *cpos_it += *disp_it; } + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initializeUpdateResidualData() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); - residual->resize(nb_nodes); + internal_force->resize(nb_nodes); /// copy the forces in residual for boundary conditions - memcpy(residual->storage(), force->storage(), nb_nodes*spatial_dimension*sizeof(Real)); + this->getDOFManager().assembleToResidual("displacements", *this->external_force); // start synchronization synch_registry->asynchronousSynchronize(_gst_smm_uv); synch_registry->waitEndSynchronize(_gst_smm_uv); - updateCurrentPosition(); + this->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); } + this->getDOFManager().assembleToResidual("displacements", *this->internal_force); + 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); } } } /* -------------------------------------------------------------------------- */ /* Implicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ // /** // * Initialize the solver and create the sparse matrices needed. // * // */ // void SolidMechanicsModel::initSolver(__attribute__((unused)) // SolverOptions & options) { // UInt nb_global_nodes = mesh.getNbGlobalNodes(); // jacobian_matrix = &(this->getDOFManager().getNewMatrix("jacobian", _symmetric)); // // jacobian_matrix->buildProfile(mesh, *dof_synchronizer, spatial_dimension); // if (!isExplicit()) { // delete stiffness_matrix; // std::stringstream sstr_sti; // sstr_sti << id << ":stiffness_matrix"; // stiffness_matrix = &(this->getDOFManager().getNewMatrix("stiffness", _symmetric)); // } // if (solver) solver->initialize(options); // } // /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::initJacobianMatrix() { // // @todo make it more flexible: this is an ugly patch to treat the case of non // // fix profile of the K matrix // delete jacobian_matrix; // jacobian_matrix = &(this->getDOFManager().getNewMatrix("jacobian", "stiffness")); // std::stringstream sstr_solv; sstr_solv << id << ":solver"; // delete solver; // solver = new SolverMumps(*jacobian_matrix, sstr_solv.str()); // if(solver) // solver->initialize(_solver_no_options); // } /* -------------------------------------------------------------------------- */ /** * Initialize the implicit solver, either for dynamic or static cases, * * @param dynamic */ void SolidMechanicsModel::initImplicit(bool dynamic) { AKANTU_DEBUG_IN(); method = dynamic ? _implicit_dynamic : _static; if (!increment) setIncrementFlagOn(); initSolver(); // if(method == _implicit_dynamic) { // if(integrator) delete integrator; // integrator = new TrapezoidalRule2(); // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleStiffnessMatrix() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the new stiffness matrix."); // 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(); } /* -------------------------------------------------------------------------- */ SparseMatrix & SolidMechanicsModel::initVelocityDampingMatrix() { - if(!velocity_damping_matrix) - velocity_damping_matrix = &(this->getDOFManager().getNewMatrix("velocity_damping", "jacobian")); - - return *velocity_damping_matrix; + return this->getDOFManager().getNewMatrix("velocity_damping", "jacobian"); } // /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::implicitPred() { // AKANTU_DEBUG_IN(); // if(previous_displacement) previous_displacement->copy(*displacement); // if(method == _implicit_dynamic) // integrator->integrationSchemePred(time_step, -// *displacement, -// *velocity, -// *acceleration, -// *blocked_dofs); +// *displacement, +// *velocity, +// *acceleration, +// *blocked_dofs); // AKANTU_DEBUG_OUT(); // } // /* -------------------------------------------------------------------------- */ // void SolidMechanicsModel::implicitCorr() { // AKANTU_DEBUG_IN(); // if(method == _implicit_dynamic) { // integrator->integrationSchemeCorrDispl(time_step, -// *displacement, -// *velocity, -// *acceleration, -// *blocked_dofs, -// *increment); +// *displacement, +// *velocity, +// *acceleration, +// *blocked_dofs, +// *increment); // } else { // UInt nb_nodes = displacement->getSize(); // UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes; // Real * incr_val = increment->storage(); // Real * disp_val = displacement->storage(); // bool * boun_val = blocked_dofs->storage(); // for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++disp_val, ++incr_val, ++boun_val){ // *incr_val *= (1. - *boun_val); // *disp_val += *incr_val; // } // } // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateIncrement() { AKANTU_DEBUG_IN(); 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::const_scalar_iterator mat_indexes = material_index(*it, ghost_type).begin(); Array::const_scalar_iterator mat_loc_num = material_local_numbering(*it, ghost_type).begin(); Array X(0, nb_nodes_per_element*spatial_dimension); FEEngine::extractNodalToElementField(mesh, *current_position, - X, *it, _not_ghost); + 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, ++mat_indexes, ++mat_loc_num) { elem.element = *mat_loc_num; Real el_h = getFEEngine().getElementInradius(*X_el, *it); Real el_c = mat_val[*mat_indexes]->getCelerity(elem); Real el_dt = el_h / el_c; min_dt = std::min(min_dt, el_dt); } } AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy() { AKANTU_DEBUG_IN(); - if (!mass && !mass_matrix) - AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix."); - + if (!mass) + AKANTU_DEBUG_ERROR("No function called to assemble the mass."); 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 = !isPBCSlaveNode(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; + 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 = getFEEngine().getNbQuadraturePoints(type); Array vel_on_quad(nb_quadrature_points, spatial_dimension); Array filter_element(1, 1, index); getFEEngine().interpolateOnQuadraturePoints(*velocity, vel_on_quad, - spatial_dimension, - type, _not_ghost, - filter_element); + 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[material_index(type)(index)]->getRho(); for (UInt q = 0; vit != vend; ++vit, ++q) { rho_v2(q) = rho * vit->dot(*vit); } AKANTU_DEBUG_OUT(); return .5*getFEEngine().integrate(rho_v2, type, index); } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getExternalWork() { AKANTU_DEBUG_IN(); Real * velo = velocity->storage(); - Real * forc = force->storage(); - Real * resi = residual->storage(); + Real * forc = external_force->storage(); + Real * resi = internal_force->storage(); bool * boun = blocked_dofs->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 = !isPBCSlaveNode(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; + 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){ + const ElementType & type, + UInt index){ AKANTU_DEBUG_IN(); if (energy_id == "kinetic") { return getKineticEnergy(type, index); } std::vector::iterator mat_it; UInt mat_index = this->material_index(type, _not_ghost)(index); UInt mat_loc_num = this->material_local_numbering(type, _not_ghost)(index); Real energy = this->materials[mat_index]->getEnergy(energy_id, type, mat_loc_num); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onElementsAdded(const Array & element_list, - const NewElementsEvent & event) { + const NewElementsEvent & event) { AKANTU_DEBUG_IN(); this->getFEEngine().initShapeFunctions(_not_ghost); this->getFEEngine().initShapeFunctions(_ghost); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; Mesh::type_iterator it = this->mesh.firstType(spatial_dimension, gt, _ek_not_defined); Mesh::type_iterator end = this->mesh.lastType(spatial_dimension, gt, _ek_not_defined); for(; it != end; ++it) { UInt nb_element = this->mesh.getNbElement(*it, gt); if(!material_index.exists(*it, gt)) { - this->material_index .alloc(nb_element, 1, *it, gt); - this->material_local_numbering.alloc(nb_element, 1, *it, gt); + this->material_index .alloc(nb_element, 1, *it, gt); + this->material_local_numbering.alloc(nb_element, 1, *it, gt); } else { - this->material_index (*it, gt).resize(nb_element); - this->material_local_numbering(*it, gt).resize(nb_element); + this->material_index (*it, gt).resize(nb_element); + this->material_local_numbering(*it, gt).resize(nb_element); } } } Array::const_iterator it = element_list.begin(); Array::const_iterator end = element_list.end(); ElementTypeMapArray filter("new_element_filter", this->getID()); for (UInt el = 0; it != end; ++it, ++el) { const Element & elem = *it; if(!filter.exists(elem.type, elem.ghost_type)) filter.alloc(0, 1, elem.type, elem.ghost_type); filter(elem.type, elem.ghost_type).push_back(elem.element); } this->assignMaterialToElements(&filter); 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) this->assembleMassLumped(); if (method != _explicit_lumped_mass) { this->initSolver(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onElementsRemoved(__attribute__((unused)) const Array & element_list, - const ElementTypeMapArray & new_numbering, - const RemovedElementsEvent & event) { + const ElementTypeMapArray & new_numbering, + const RemovedElementsEvent & event) { this->getFEEngine().initShapeFunctions(_not_ghost); this->getFEEngine().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::onNodesAdded(const Array & nodes_list, - __attribute__((unused)) const NewNodesEvent & event) { + __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(blocked_dofs) blocked_dofs->resize(nb_nodes); + 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(external_force) external_force->resize(nb_nodes); + if(internal_force) internal_force->resize(nb_nodes); + if(blocked_dofs) blocked_dofs ->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); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onNodesRemoved(__attribute__((unused)) const Array & element_list, - const Array & new_numbering, - __attribute__((unused)) const RemovedNodesEvent & event) { + 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(internal_force) mesh.removeNodesFromArray(*internal_force, new_numbering); + if(external_force) mesh.removeNodesFromArray(*external_force, new_numbering); if(blocked_dofs) mesh.removeNodesFromArray(*blocked_dofs, new_numbering); if(increment_acceleration) mesh.removeNodesFromArray(*increment_acceleration, new_numbering); if(increment) mesh.removeNodesFromArray(*increment , new_numbering); - delete dof_synchronizer; - dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension); - dof_synchronizer->initLocalDOFEquationNumbers(); - dof_synchronizer->initGlobalDOFEquationNumbers(); - if (method != _explicit_lumped_mass) { this->initSolver(); } - } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::isInternal(const std::string & field_name, - const ElementKind & element_kind){ + const ElementKind & element_kind){ 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_name, element_kind); } return is_internal; } /* -------------------------------------------------------------------------- */ ElementTypeMap SolidMechanicsModel::getInternalDataPerElem(const std::string & field_name, - const ElementKind & element_kind){ + const ElementKind & element_kind){ if (!(this->isInternal(field_name,element_kind))) AKANTU_EXCEPTION("unknown internal " << field_name); for (UInt m = 0; m < materials.size() ; ++m) { if (materials[m]->isInternal(field_name, element_kind)) return materials[m]->getInternalDataPerElem(field_name, element_kind); } return ElementTypeMap(); } /* -------------------------------------------------------------------------- */ ElementTypeMapArray & SolidMechanicsModel::flattenInternal(const std::string & field_name, - const ElementKind & kind, - const GhostType ghost_type){ + const ElementKind & kind, + const GhostType ghost_type){ std::pair key(field_name,kind); if (this->registered_internals.count(key) == 0){ this->registered_internals[key] = new ElementTypeMapArray(field_name, this->id); } ElementTypeMapArray * internal_flat = this->registered_internals[key]; typedef ElementTypeMapArray::type_iterator iterator; iterator tit = internal_flat->firstType(spatial_dimension, - ghost_type, - kind); + ghost_type, + kind); iterator end = internal_flat->lastType(spatial_dimension, - ghost_type, - kind); + ghost_type, + kind); for (; tit != end; ++tit) { ElementType type = *tit; (*internal_flat)(type,ghost_type).clear(); } - + for (UInt m = 0; m < materials.size(); ++m) { if (materials[m]->isInternal(field_name, kind)) materials[m]->flattenInternal(field_name, *internal_flat, ghost_type, kind); } return *internal_flat; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::flattenAllRegisteredInternals(const ElementKind & kind){ std::map, - ElementTypeMapArray *>::iterator it = this->registered_internals.begin(); + ElementTypeMapArray *>::iterator it = this->registered_internals.begin(); std::map, - ElementTypeMapArray *>::iterator end = this->registered_internals.end(); + ElementTypeMapArray *>::iterator end = this->registered_internals.end(); while (it != end){ if (kind == it->first.second) this->flattenInternal(it->first.first, kind); ++it; } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onDump(){ this->flattenAllRegisteredInternals(_ek_regular); } /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER - -dumper::Field * SolidMechanicsModel -::createElementalField(const std::string & field_name, - const std::string & group_name, - bool padding_flag, - const UInt & spatial_dimension, - const ElementKind & kind) { +dumper::Field * SolidMechanicsModel::createElementalField( + const std::string & field_name, const std::string & group_name, + bool padding_flag, const UInt & spatial_dimension, + const ElementKind & kind) { dumper::Field * field = NULL; - if(field_name == "partitions") - field = mesh.createElementalField(mesh.getConnectivities(),group_name,spatial_dimension,kind); - else if(field_name == "material_index") - field = mesh.createElementalField(material_index,group_name,spatial_dimension,kind); + if (field_name == "partitions") + field = mesh.createElementalField( + mesh.getConnectivities(), group_name, spatial_dimension, kind); + else if (field_name == "material_index") + field = mesh.createElementalField( + material_index, group_name, spatial_dimension, kind); else { // this copy of field_name is used to compute derivated data such as // strain and von mises stress that are based on grad_u and stress std::string field_name_copy(field_name); - if (field_name == "strain" - || field_name == "Green strain" - || field_name == "principal strain" - || field_name == "principal Green strain") + if (field_name == "strain" || field_name == "Green strain" || + field_name == "principal strain" || + field_name == "principal Green strain") field_name_copy = "grad_u"; else if (field_name == "Von Mises stress") field_name_copy = "stress"; - bool is_internal = this->isInternal(field_name_copy,kind); + bool is_internal = this->isInternal(field_name_copy, kind); if (is_internal) { - ElementTypeMap nb_data_per_elem = this->getInternalDataPerElem(field_name_copy, kind); - ElementTypeMapArray & internal_flat = this->flattenInternal(field_name_copy,kind); - field = mesh.createElementalField(internal_flat, - group_name, - spatial_dimension,kind,nb_data_per_elem); - if (field_name == "strain"){ - dumper::ComputeStrain * foo = new dumper::ComputeStrain(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); + ElementTypeMap nb_data_per_elem = + this->getInternalDataPerElem(field_name_copy, kind); + ElementTypeMapArray & internal_flat = + this->flattenInternal(field_name_copy, kind); + field = mesh.createElementalField( + internal_flat, group_name, spatial_dimension, kind, nb_data_per_elem); + if (field_name == "strain") { + dumper::ComputeStrain * foo = + new dumper::ComputeStrain(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } else if (field_name == "Von Mises stress") { - dumper::ComputeVonMisesStress * foo = new dumper::ComputeVonMisesStress(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); + dumper::ComputeVonMisesStress * foo = + new dumper::ComputeVonMisesStress(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } else if (field_name == "Green strain") { - dumper::ComputeStrain * foo = new dumper::ComputeStrain(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); + dumper::ComputeStrain * foo = + new dumper::ComputeStrain(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } else if (field_name == "principal strain") { - dumper::ComputePrincipalStrain * foo = new dumper::ComputePrincipalStrain(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); + dumper::ComputePrincipalStrain * foo = + new dumper::ComputePrincipalStrain(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } else if (field_name == "principal Green strain") { - dumper::ComputePrincipalStrain * foo = new dumper::ComputePrincipalStrain(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); + dumper::ComputePrincipalStrain * foo = + new dumper::ComputePrincipalStrain(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } - //treat the paddings - if (padding_flag){ - if (field_name == "stress"){ - if (spatial_dimension == 2) { - dumper::StressPadder<2> * foo = new dumper::StressPadder<2>(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); - } - } else if (field_name == "strain" || field_name == "Green strain"){ - if (spatial_dimension == 2) { - dumper::StrainPadder<2> * foo = new dumper::StrainPadder<2>(*this); - field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); - } - } + // treat the paddings + if (padding_flag) { + if (field_name == "stress") { + if (spatial_dimension == 2) { + dumper::StressPadder<2> * foo = new dumper::StressPadder<2>(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); + } + } else if (field_name == "strain" || field_name == "Green strain") { + if (spatial_dimension == 2) { + dumper::StrainPadder<2> * foo = new dumper::StrainPadder<2>(*this); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); + } + } } // homogenize the field dumper::ComputeFunctorInterface * foo = - dumper::HomogenizerProxy::createHomogenizer(*field); - - field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); + dumper::HomogenizerProxy::createHomogenizer(*field); + field = dumper::FieldComputeProxy::createFieldCompute(field, *foo); } } return field; } /* -------------------------------------------------------------------------- */ +dumper::Field * +SolidMechanicsModel::createNodalFieldReal(const std::string & field_name, + const std::string & group_name, + bool padding_flag) { -dumper::Field * SolidMechanicsModel::createNodalFieldReal(const std::string & field_name, - const std::string & group_name, - bool padding_flag) { - - std::map* > real_nodal_fields; - real_nodal_fields["displacement" ] = displacement; - real_nodal_fields["mass" ] = mass; - real_nodal_fields["velocity" ] = velocity; - real_nodal_fields["acceleration" ] = acceleration; - real_nodal_fields["force" ] = force; - real_nodal_fields["residual" ] = residual; - real_nodal_fields["increment" ] = increment; + std::map *> real_nodal_fields; + real_nodal_fields["displacement"] = this->displacement; + real_nodal_fields["mass"] = this->mass; + real_nodal_fields["velocity"] = this->velocity; + real_nodal_fields["acceleration"] = this->acceleration; + real_nodal_fields["force"] = this->external_force; + real_nodal_fields["residual"] = this->internal_force; + real_nodal_fields["increment"] = this->increment; dumper::Field * field = NULL; if (padding_flag) - field = mesh.createNodalField(real_nodal_fields[field_name],group_name, 3); + field = this->mesh.createNodalField(real_nodal_fields[field_name], group_name, 3); else - field = mesh.createNodalField(real_nodal_fields[field_name],group_name); + field = this->mesh.createNodalField(real_nodal_fields[field_name], group_name); return field; } -/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createNodalFieldBool(const std::string & field_name, - const std::string & group_name, + const std::string & group_name, bool padding_flag) { std::map* > uint_nodal_fields; uint_nodal_fields["blocked_dofs" ] = blocked_dofs; dumper::Field * field = NULL; field = mesh.createNodalField(uint_nodal_fields[field_name],group_name); return field; } /* -------------------------------------------------------------------------- */ #else /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel ::createElementalField(const std::string & field_name, - const std::string & group_name, - bool padding_flag, - const UInt & spatial_dimension, - const ElementKind & kind){ + const std::string & group_name, + bool padding_flag, + const UInt & spatial_dimension, + const ElementKind & kind){ return NULL; } /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createNodalFieldReal(const std::string & field_name, - const std::string & group_name, - bool padding_flag) { + const std::string & group_name, + bool padding_flag) { return NULL; } /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createNodalFieldBool(const std::string & field_name, - const std::string & group_name, + const std::string & group_name, bool padding_flag) { return NULL; } #endif /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(dumper_name); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name, UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(dumper_name, step); } /* ------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name, Real time, UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(dumper_name, time, step); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump() { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(step); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(Real time, UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(time, step); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::computeCauchyStresses() { AKANTU_DEBUG_IN(); // call compute stiffness matrix on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; if(mat.isFiniteDeformation()) mat.computeAllCauchyStresses(_not_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::saveStressAndStrainBeforeDamage() { EventManager::sendEvent(SolidMechanicsModelEvent::BeginningOfDamageIterationEvent()); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateEnergiesAfterDamage() { EventManager::sendEvent(SolidMechanicsModelEvent::AfterDamageEvent()); } /* -------------------------------------------------------------------------- */ 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; getFEEngine().printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + nodals information [" << std::endl; displacement->printself(stream, indent + 2); mass ->printself(stream, indent + 2); velocity ->printself(stream, indent + 2); acceleration->printself(stream, indent + 2); - force ->printself(stream, indent + 2); - residual ->printself(stream, indent + 2); + external_force->printself(stream, indent + 2); + internal_force->printself(stream, indent + 2); blocked_dofs->printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + material information [" << std::endl; material_index.printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + materials [" << std::endl; std::vector::const_iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { const Material & mat = *(*mat_it); mat.printself(stream, indent + 1); } 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 726e2462d..2130d4c5d 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.hh +++ b/src/model/solid_mechanics/solid_mechanics_model.hh @@ -1,722 +1,712 @@ /** * @file solid_mechanics_model.hh * * @author Guillaume Anciaux * @author Daniel Pino Muñoz * @author Nicolas Richart * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Sep 16 2014 * * @brief Model of Solid Mechanics * * @section LICENSE * * Copyright (©) 2010-2012, 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 . * */ /* -------------------------------------------------------------------------- */ #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 "material_selector.hh" #include "solid_mechanics_model_event_handler.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class Material; class DumperIOHelper; } /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ struct SolidMechanicsModelOptions : public ModelOptions { SolidMechanicsModelOptions(AnalysisMethod analysis_method = _explicit_lumped_mass, - bool no_init_materials = false) : + 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 BoundaryCondition, - public EventHandlerManager { + public DataAccessor, + public MeshEventHandler, + 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 FEEngineTemplate MyFEEngineType; protected: typedef EventHandlerManager EventManager; public: SolidMechanicsModel(Mesh & mesh, - UInt spatial_dimension = _all_dimensions, - const ID & id = "solid_mechanics_model", - const MemoryID & memory_id = 0); + 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(const ModelOptions & options = default_solid_mechanics_model_options); /// initialize the fem object needed for boundary conditions void initFEEngineBoundary(); /// register the tags associated with the parallel synchronizer void initParallel(MeshPartition *partition, DataAccessor *data_accessor = NULL); /// allocate all vectors virtual void initArrays(); /// allocate all vectors void initArraysPreviousDisplacment(); /// initialize all internal arrays for materials virtual void initMaterials(); /// initialize the model 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; - /// re-initialize model to set fields to 0 - void reInitialize(); - /* ------------------------------------------------------------------------ */ /* 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(); void saveStressAndStrainBeforeDamage(); void updateEnergiesAfterDamage(); /// 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 & blocked_dofs, - Real alpha); + const Array & A, + const Array & b, + const Array & blocked_dofs, + Real alpha); /// explicit integration predictor void explicitPred(); /// explicit integration corrector void explicitCorr(); public: void solveStep(); /* ------------------------------------------------------------------------ */ /* Implicit */ /* ------------------------------------------------------------------------ */ public: /// initialize the solver and the jacobian_matrix (called by initImplicit) void initSolver(); /// initialize the stuff for the implicit solver void initImplicit(bool dynamic = false); /// solve Ma = f to get the initial acceleration void initialAcceleration(); /// assemble the stiffness matrix void assembleStiffnessMatrix(); public: /** * solve a step (predictor + convergence loop + corrector) using the * the given convergence method (see akantu::SolveConvergenceMethod) * and the given convergence criteria (see * akantu::SolveConvergenceCriteria) **/ template bool solveStep(Real tolerance, UInt max_iteration = 100); template bool solveStep(Real tolerance, - Real & error, - UInt max_iteration = 100, - bool do_not_factorize = false); + Real & error, + UInt max_iteration = 100, + bool do_not_factorize = false); public: /** * solve Ku = f using the the given convergence method (see * akantu::SolveConvergenceMethod) and the given convergence * criteria (see akantu::SolveConvergenceCriteria) **/ template bool solveStatic(Real tolerance, UInt max_iteration, - bool do_not_factorize = false); + bool do_not_factorize = false); /// create and return the velocity damping matrix SparseMatrix & initVelocityDampingMatrix(); /// implicit time integration predictor void implicitPred(); /// implicit time integration corrector void implicitCorr(); /// compute the Cauchy stress on user demand. void computeCauchyStresses(); // /// compute A and solve @f[ A\delta u = f_ext - f_int @f] // template // void solve(Array &increment, Real block_val = 1., // bool need_factorize = true, bool has_profile_changed = false); protected: /// finish the computation of residual to solve in increment void updateResidualInternal(); /// compute the support reaction and store it in force void updateSupportReaction(); private: /// re-initialize the J matrix (to use if the profile of K changed) void initJacobianMatrix(); /* ------------------------------------------------------------------------ */ /* 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 virtual 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(); /// set the element_id_by_material and add the elements to the good materials void assignMaterialToElements(const ElementTypeMapArray * filter = NULL); /* ------------------------------------------------------------------------ */ /* 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); + ElementType type, + GhostType ghost_type); /// compute the kinetic energy Real getKineticEnergy(); Real getKineticEnergy(const ElementType & type, UInt index); /// compute the external work (for impose displacement, the velocity should be given too) Real getExternalWork(); /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ public: inline virtual UInt getNbDataForElements(const Array & elements, - SynchronizationTag tag) const; + SynchronizationTag tag) const; inline virtual void packElementData(CommunicationBuffer & buffer, - const Array & elements, - SynchronizationTag tag) const; + const Array & elements, + SynchronizationTag tag) const; inline virtual void unpackElementData(CommunicationBuffer & buffer, - const Array & elements, - SynchronizationTag tag); + 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; + const UInt index, + SynchronizationTag tag) const; inline virtual void unpackData(CommunicationBuffer & buffer, - const UInt index, - SynchronizationTag tag); + const UInt index, + SynchronizationTag tag); protected: inline void splitElementByMaterial(const Array & elements, - Array * elements_per_mat) const; + Array * elements_per_mat) const; /* ------------------------------------------------------------------------ */ /* Mesh Event Handler inherited members */ /* ------------------------------------------------------------------------ */ protected: virtual void onNodesAdded(const Array & nodes_list, - const NewNodesEvent & event); + const NewNodesEvent & event); virtual void onNodesRemoved(const Array & element_list, - const Array & new_numbering, - const RemovedNodesEvent & event); + const Array & new_numbering, + const RemovedNodesEvent & event); virtual void onElementsAdded(const Array & nodes_list, - const NewElementsEvent & event); + const NewElementsEvent & event); virtual void onElementsRemoved(const Array & element_list, - const ElementTypeMapArray & new_numbering, - const RemovedElementsEvent & event); + const ElementTypeMapArray & new_numbering, + const RemovedElementsEvent & event); /* ------------------------------------------------------------------------ */ /* Dumpable interface (kept for convenience) and dumper relative functions */ /* ------------------------------------------------------------------------ */ public: virtual void onDump(); //! decide wether a field is a material internal or not bool isInternal(const std::string & field_name, const ElementKind & element_kind); #ifndef SWIG //! give the amount of data per element virtual ElementTypeMap getInternalDataPerElem(const std::string & field_name, - const ElementKind & kind); + const ElementKind & kind); //! flatten a given material internal field ElementTypeMapArray & flattenInternal(const std::string & field_name, - const ElementKind & kind, - const GhostType ghost_type = _not_ghost); + const ElementKind & kind, + const GhostType ghost_type = _not_ghost); //! flatten all the registered material internals void flattenAllRegisteredInternals(const ElementKind & kind); #endif virtual dumper::Field * createNodalFieldReal(const std::string & field_name, - const std::string & group_name, - bool padding_flag); + const std::string & group_name, + bool padding_flag); virtual dumper::Field * createNodalFieldBool(const std::string & field_name, - const std::string & group_name, - bool padding_flag); + const std::string & group_name, + bool padding_flag); virtual dumper::Field * createElementalField(const std::string & field_name, - const std::string & group_name, - bool padding_flag, - const UInt & spatial_dimension, - const ElementKind & kind); + const std::string & group_name, + bool padding_flag, + const UInt & spatial_dimension, + const ElementKind & kind); 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); /// return the of iterations done in the last solveStep AKANTU_GET_MACRO(NumberIter, n_iter, UInt); /// get the value of the conversion from forces/ mass to acceleration AKANTU_GET_MACRO(F_M2A, f_m2a, Real); /// set the value of the conversion from forces/ mass to acceleration AKANTU_SET_MACRO(F_M2A, f_m2a, Real); /// get the SolidMechanicsModel::displacement vector AKANTU_GET_MACRO(Displacement, *displacement, Array &); /// 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 (external forces) - AKANTU_GET_MACRO(Force, *force, Array &); + AKANTU_GET_MACRO(Force, *external_force, Array &); /// get the SolidMechanicsModel::internal_force vector (internal forces) AKANTU_GET_MACRO(InternalForce, *internal_force, Array &); - /// get the SolidMechanicsModel::residual vector, computed by - /// SolidMechanicsModel::updateResidual - AKANTU_GET_MACRO(Residual, *residual, Array &); - /// get the SolidMechanicsModel::blocked_dofs vector AKANTU_GET_MACRO(BlockedDOFs, *blocked_dofs, 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(); /// get the energies Real getEnergy(const std::string & energy_id); /// compute the energy for energy Real getEnergy(const std::string & energy_id, const ElementType & type, UInt index); /** * @brief set the SolidMechanicsModel::increment_flag to on, the activate the * update of the SolidMechanicsModel::increment vector */ void setIncrementFlagOn(); - /// get the stiffness matrix - AKANTU_GET_MACRO(StiffnessMatrix, *stiffness_matrix, SparseMatrix &); + // /// get the 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 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 mass matrix + // AKANTU_GET_MACRO(MassMatrix, *mass_matrix, SparseMatrix &); - /// get the velocity damping matrix - AKANTU_GET_MACRO(VelocityDampingMatrix, *velocity_damping_matrix, SparseMatrix &); + // /// get the velocity damping matrix + // AKANTU_GET_MACRO(VelocityDampingMatrix, *velocity_damping_matrix, SparseMatrix &); /// get the FEEngine object to integrate or interpolate on the boundary inline FEEngine & getFEEngineBoundary(const ID & name = ""); // /// get integrator // AKANTU_GET_MACRO(Integrator, *integrator, const IntegrationScheme2ndOrder &); /// get synchronizer AKANTU_GET_MACRO(Synchronizer, *synch_parallel, const DistributedSynchronizer &); AKANTU_GET_MACRO(MaterialByElement, material_index, const ElementTypeMapArray &); /// vectors containing local material element index for each global element index AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialByElement, material_index, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialByElement, material_index, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialLocalNumbering, material_local_numbering, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialLocalNumbering, material_local_numbering, UInt); /// Get the type of analysis method used AKANTU_GET_MACRO(AnalysisMethod, method, AnalysisMethod); template friend struct ContactData; template friend class ContactResolution; protected: friend class Material; protected: /// compute the stable time step Real getStableTimeStep(const GhostType & ghost_type); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// number of iterations UInt n_iter; /// time step Real time_step; /// conversion coefficient form force/mass to acceleration Real f_m2a; /// displacements array Array *displacement; /// displacements array at the previous time step (used in finite deformation) Array *previous_displacement; + /// increment of displacement + Array *increment; + /// lumped mass array Array *mass; /// velocities array Array *velocity; /// accelerations array Array *acceleration; /// accelerations array Array *increment_acceleration; /// external forces array - Array *force; + Array *external_force; /// internal forces array Array *internal_force; - /// residuals array - Array *residual; - /// array specifing if a degree of freedom is blocked or not Array *blocked_dofs; /// array of current position used during update residual Array *current_position; - /// mass matrix - SparseMatrix *mass_matrix; + // /// mass matrix + // SparseMatrix *mass_matrix; - /// velocity damping matrix - SparseMatrix *velocity_damping_matrix; + // /// velocity damping matrix + // SparseMatrix *velocity_damping_matrix; - /// stiffness matrix - SparseMatrix *stiffness_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; + // /// jacobian matrix @f[A = cM + dD + K@f] with @f[c = \frac{1}{\beta \Delta + // /// t^2}, d = \frac{\gamma}{\beta \Delta t} @f] + // SparseMatrix *jacobian_matrix; /// Arrays containing the material index for each element ElementTypeMapArray material_index; /// Arrays containing the position in the element filter of the material (material's local numbering) ElementTypeMapArray material_local_numbering; /// 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; /// 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; /// map a registered internals to be flattened for dump purposes std::map,ElementTypeMapArray *> registered_internals; }; /* -------------------------------------------------------------------------- */ namespace BC { namespace Neumann { typedef FromHigherDim FromStress; typedef FromSameDim FromTraction; } } __END_AKANTU__ /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "parser.hh" #include "material.hh" __BEGIN_AKANTU__ #include "solid_mechanics_model_tmpl.hh" #include "solid_mechanics_model_inline_impl.cc" /// 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_inline_impl.cc b/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc index 9ed57a342..226ed6a52 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_inline_impl.cc @@ -1,436 +1,436 @@ /** * @file solid_mechanics_model_inline_impl.cc * * @author Guillaume Anciaux * @author Daniel Pino Muñoz * @author Nicolas Richart * * @date creation: Wed Aug 04 2010 * @date last modification: Mon Sep 15 2014 * * @brief Implementation of the inline functions of the SolidMechanicsModel class * * @section LICENSE * * Copyright (©) 2010-2012, 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 . * */ /* -------------------------------------------------------------------------- */ inline Material & SolidMechanicsModel::getMaterial(UInt mat_index) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(mat_index < materials.size(), "The model " << id << " has no material no "<< mat_index); AKANTU_DEBUG_OUT(); return *materials[mat_index]; } /* -------------------------------------------------------------------------- */ inline const Material & SolidMechanicsModel::getMaterial(UInt mat_index) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(mat_index < materials.size(), "The model " << id << " has no material no "<< mat_index); AKANTU_DEBUG_OUT(); return *materials[mat_index]; } /* -------------------------------------------------------------------------- */ inline Material & SolidMechanicsModel::getMaterial(const std::string & name) { AKANTU_DEBUG_IN(); std::map::const_iterator it = materials_names_to_id.find(name); AKANTU_DEBUG_ASSERT(it != materials_names_to_id.end(), "The model " << id << " has no material named "<< name); AKANTU_DEBUG_OUT(); return *materials[it->second]; } /* -------------------------------------------------------------------------- */ inline UInt SolidMechanicsModel::getMaterialIndex(const std::string & name) const { AKANTU_DEBUG_IN(); std::map::const_iterator it = materials_names_to_id.find(name); AKANTU_DEBUG_ASSERT(it != materials_names_to_id.end(), "The model " << id << " has no material named "<< name); AKANTU_DEBUG_OUT(); return it->second; } /* -------------------------------------------------------------------------- */ inline const Material & SolidMechanicsModel::getMaterial(const std::string & name) const { AKANTU_DEBUG_IN(); std::map::const_iterator it = materials_names_to_id.find(name); AKANTU_DEBUG_ASSERT(it != materials_names_to_id.end(), "The model " << id << " has no material named "<< name); AKANTU_DEBUG_OUT(); return *materials[it->second]; } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::setMaterialSelector(MaterialSelector & selector) { if(is_default_material_selector) delete material_selector; material_selector = &selector; is_default_material_selector = false; } /* -------------------------------------------------------------------------- */ inline FEEngine & SolidMechanicsModel::getFEEngineBoundary(const ID & name) { return dynamic_cast(getFEEngineClassBoundary(name)); } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::splitElementByMaterial(const Array & elements, Array * elements_per_mat) const { ElementType current_element_type = _not_defined; GhostType current_ghost_type = _casper; const Array * mat_indexes = NULL; const Array * mat_loc_num = NULL; Array::const_iterator it = elements.begin(); Array::const_iterator end = elements.end(); for (; it != end; ++it) { Element el = *it; if(el.type != current_element_type || el.ghost_type != current_ghost_type) { current_element_type = el.type; current_ghost_type = el.ghost_type; mat_indexes = &(this->material_index(el.type, el.ghost_type)); mat_loc_num = &(this->material_local_numbering(el.type, el.ghost_type)); } UInt old_id = el.element; el.element = (*mat_loc_num)(old_id); elements_per_mat[(*mat_indexes)(old_id)].push_back(el); } } /* -------------------------------------------------------------------------- */ inline UInt SolidMechanicsModel::getNbDataForElements(const Array & elements, SynchronizationTag tag) const { AKANTU_DEBUG_IN(); UInt size = 0; UInt nb_nodes_per_element = 0; Array::const_iterator it = elements.begin(); Array::const_iterator end = elements.end(); for (; it != end; ++it) { const Element & el = *it; nb_nodes_per_element += Mesh::getNbNodesPerElement(el.type); } switch(tag) { case _gst_material_id: { size += elements.getSize() * sizeof(UInt); break; } case _gst_smm_mass: { size += nb_nodes_per_element * sizeof(Real) * spatial_dimension; // mass vector break; } case _gst_smm_for_gradu: { size += nb_nodes_per_element * spatial_dimension * sizeof(Real); // displacement break; } case _gst_smm_boundary: { // force, displacement, boundary size += nb_nodes_per_element * spatial_dimension * (2 * sizeof(Real) + sizeof(bool)); break; } case _gst_for_dump: { // displacement, velocity, acceleration, residual, force size += nb_nodes_per_element * spatial_dimension * sizeof(Real) * 5; break; } default: { } } if(tag != _gst_material_id) { Array * elements_per_mat = new Array[materials.size()]; this->splitElementByMaterial(elements, elements_per_mat); for (UInt i = 0; i < materials.size(); ++i) { size += materials[i]->getNbDataForElements(elements_per_mat[i], tag); } delete [] elements_per_mat; } AKANTU_DEBUG_OUT(); return size; } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::packElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag) const { AKANTU_DEBUG_IN(); switch(tag) { case _gst_material_id: { packElementalDataHelper(material_index, buffer, elements, false, getFEEngine()); break; } case _gst_smm_mass: { packNodalDataHelper(*mass, buffer, elements, mesh); break; } case _gst_smm_for_gradu: { packNodalDataHelper(*displacement, buffer, elements, mesh); break; } case _gst_for_dump: { packNodalDataHelper(*displacement, buffer, elements, mesh); packNodalDataHelper(*velocity, buffer, elements, mesh); packNodalDataHelper(*acceleration, buffer, elements, mesh); - packNodalDataHelper(*residual, buffer, elements, mesh); - packNodalDataHelper(*force, buffer, elements, mesh); + packNodalDataHelper(*internal_force, buffer, elements, mesh); + packNodalDataHelper(*external_force, buffer, elements, mesh); break; } case _gst_smm_boundary: { - packNodalDataHelper(*force, buffer, elements, mesh); + packNodalDataHelper(*external_force, buffer, elements, mesh); packNodalDataHelper(*velocity, buffer, elements, mesh); packNodalDataHelper(*blocked_dofs, buffer, elements, mesh); break; } default: { } } if(tag != _gst_material_id) { Array * elements_per_mat = new Array[materials.size()]; splitElementByMaterial(elements, elements_per_mat); for (UInt i = 0; i < materials.size(); ++i) { materials[i]->packElementData(buffer, elements_per_mat[i], tag); } delete [] elements_per_mat; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::unpackElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag) { AKANTU_DEBUG_IN(); switch(tag) { case _gst_material_id: { unpackElementalDataHelper(material_index, buffer, elements, false, getFEEngine()); break; } case _gst_smm_mass: { unpackNodalDataHelper(*mass, buffer, elements, mesh); break; } case _gst_smm_for_gradu: { unpackNodalDataHelper(*displacement, buffer, elements, mesh); break; } case _gst_for_dump: { unpackNodalDataHelper(*displacement, buffer, elements, mesh); unpackNodalDataHelper(*velocity, buffer, elements, mesh); unpackNodalDataHelper(*acceleration, buffer, elements, mesh); - unpackNodalDataHelper(*residual, buffer, elements, mesh); - unpackNodalDataHelper(*force, buffer, elements, mesh); + unpackNodalDataHelper(*internal_force, buffer, elements, mesh); + unpackNodalDataHelper(*external_force, buffer, elements, mesh); break; } case _gst_smm_boundary: { - unpackNodalDataHelper(*force, buffer, elements, mesh); + unpackNodalDataHelper(*external_force, buffer, elements, mesh); unpackNodalDataHelper(*velocity, buffer, elements, mesh); unpackNodalDataHelper(*blocked_dofs, buffer, elements, mesh); break; } default: { } } if(tag != _gst_material_id) { Array * elements_per_mat = new Array[materials.size()]; splitElementByMaterial(elements, elements_per_mat); for (UInt i = 0; i < materials.size(); ++i) { materials[i]->unpackElementData(buffer, elements_per_mat[i], tag); } delete [] elements_per_mat; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline UInt SolidMechanicsModel::getNbDataToPack(SynchronizationTag tag) const { AKANTU_DEBUG_IN(); UInt size = 0; // UInt nb_nodes = mesh.getNbNodes(); switch(tag) { case _gst_smm_uv: { size += sizeof(Real) * spatial_dimension * 2; break; } case _gst_smm_res: { size += sizeof(Real) * spatial_dimension; break; } case _gst_smm_mass: { size += sizeof(Real) * spatial_dimension; break; } case _gst_for_dump: { size += sizeof(Real) * spatial_dimension * 5; break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); return size; } /* -------------------------------------------------------------------------- */ inline UInt SolidMechanicsModel::getNbDataToUnpack(SynchronizationTag tag) const { AKANTU_DEBUG_IN(); UInt size = 0; // UInt nb_nodes = mesh.getNbNodes(); switch(tag) { case _gst_smm_uv: { size += sizeof(Real) * spatial_dimension * 2; break; } case _gst_smm_res: { size += sizeof(Real) * spatial_dimension; break; } case _gst_smm_mass: { size += sizeof(Real) * spatial_dimension; break; } case _gst_for_dump: { size += sizeof(Real) * spatial_dimension * 5; break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); return size; } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::packData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const { AKANTU_DEBUG_IN(); switch(tag) { case _gst_smm_uv: { Array::const_vector_iterator it_disp = displacement->begin(spatial_dimension); Array::const_vector_iterator it_velo = velocity->begin(spatial_dimension); Vector disp(it_disp[index]); buffer << disp; Vector velo(it_velo[index]); buffer << velo; break; } case _gst_smm_res: { - Array::const_vector_iterator it_res = residual->begin(spatial_dimension); + Array::const_vector_iterator it_res = internal_force->begin(spatial_dimension); Vector resi(it_res[index]); buffer << resi; break; } case _gst_smm_mass: { AKANTU_DEBUG_INFO("pack mass of node " << index << " which is " << (*mass)(index,0)); Array::const_vector_iterator it_mass = mass->begin(spatial_dimension); Vector mass(it_mass[index]); buffer << mass; break; } case _gst_for_dump: { Array::const_vector_iterator it_disp = displacement->begin(spatial_dimension); Array::const_vector_iterator it_velo = velocity->begin(spatial_dimension); Array::const_vector_iterator it_acce = acceleration->begin(spatial_dimension); - Array::const_vector_iterator it_resi = residual->begin(spatial_dimension); - Array::const_vector_iterator it_forc = force->begin(spatial_dimension); + Array::const_vector_iterator it_resi = internal_force->begin(spatial_dimension); + Array::const_vector_iterator it_forc = external_force->begin(spatial_dimension); Vector disp(it_disp[index]); buffer << disp; Vector velo(it_velo[index]); buffer << velo; Vector acce(it_acce[index]); buffer << acce; Vector resi(it_resi[index]); buffer << resi; Vector forc(it_forc[index]); buffer << forc; break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::unpackData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) { AKANTU_DEBUG_IN(); switch(tag) { case _gst_smm_uv: { Array::vector_iterator it_disp = displacement->begin(spatial_dimension); Array::vector_iterator it_velo = velocity->begin(spatial_dimension); Vector disp(it_disp[index]); buffer >> disp; Vector velo(it_velo[index]); buffer >> velo; break; } case _gst_smm_res: { - Array::vector_iterator it_res = residual->begin(spatial_dimension); + Array::vector_iterator it_res = internal_force->begin(spatial_dimension); Vector res(it_res[index]); buffer >> res; break; } case _gst_smm_mass: { AKANTU_DEBUG_INFO("mass of node " << index << " was " << (*mass)(index,0)); Array::vector_iterator it_mass = mass->begin(spatial_dimension); Vector mass_v(it_mass[index]); buffer >> mass_v; AKANTU_DEBUG_INFO("mass of node " << index << " is now " << (*mass)(index,0)); break; } case _gst_for_dump: { Array::vector_iterator it_disp = displacement->begin(spatial_dimension); Array::vector_iterator it_velo = velocity->begin(spatial_dimension); Array::vector_iterator it_acce = acceleration->begin(spatial_dimension); - Array::vector_iterator it_resi = residual->begin(spatial_dimension); - Array::vector_iterator it_forc = force->begin(spatial_dimension); + Array::vector_iterator it_resi = internal_force->begin(spatial_dimension); + Array::vector_iterator it_forc = external_force->begin(spatial_dimension); Vector disp(it_disp[index]); buffer >> disp; Vector velo(it_velo[index]); buffer >> velo; Vector acce(it_acce[index]); buffer >> acce; Vector resi(it_resi[index]); buffer >> resi; Vector forc(it_forc[index]); buffer >> forc; break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_mass.cc b/src/model/solid_mechanics/solid_mechanics_model_mass.cc index 8ad9e9495..f49a29750 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_mass.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_mass.cc @@ -1,158 +1,152 @@ /** * @file solid_mechanics_model_mass.cc * * @author Nicolas Richart * * @date creation: Tue Oct 05 2010 * @date last modification: Thu Jun 05 2014 * * @brief function handling mass computation * * @section LICENSE * * Copyright (©) 2010-2012, 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 "solid_mechanics_model.hh" #include "material.hh" #include "model_solver.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMassLumped() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); if (!mass) { std::stringstream sstr_mass; sstr_mass << id << ":mass"; mass = &(alloc(sstr_mass.str(), nb_nodes, spatial_dimension, 0)); } else mass->clear(); assembleMassLumped(_not_ghost); assembleMassLumped(_ghost); /// for not connected nodes put mass to one in order to avoid /// wrong range in paraview Real * mass_values = mass->storage(); for (UInt i = 0; i < nb_nodes; ++i) { if (fabs(mass_values[i]) < std::numeric_limits::epsilon() || Math::isnan(mass_values[i])) mass_values[i] = 1.; } synch_registry->synchronize(_gst_smm_mass); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMassLumped(GhostType ghost_type) { AKANTU_DEBUG_IN(); FEEngine & fem = getFEEngine(); Array rho(0, spatial_dimension); 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; computeRho(rho, type, ghost_type); - AKANTU_DEBUG_ASSERT(dof_synchronizer, - "DOFSynchronizer number must not be initialized"); - fem.assembleFieldLumped(rho, spatial_dimension, *mass, - dof_synchronizer->getLocalDOFEquationNumbers(), + fem.assembleFieldLumped(rho, *mass, type, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMass() { AKANTU_DEBUG_IN(); - if (!mass_matrix) { - mass_matrix = &(this->getDOFManager().getNewMatrix("mass", "jacobian")); - } - + this->getDOFManager().getNewMatrix("mass", "jacobian"); assembleMass(_not_ghost); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMass(GhostType ghost_type) { AKANTU_DEBUG_IN(); MyFEEngineType & fem = getFEEngineClass(); Array rho(0, spatial_dimension); // UInt nb_element; // this->getDOFManager().getMatrix("mass").clear(); 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; computeRho(rho, type, ghost_type); fem.assembleFieldMatrix(rho, "mass", "displacement", this->getDOFManager(), type, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::computeRho(Array & rho, ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Material ** mat_val = &(this->materials.at(0)); FEEngine & fem = this->getFEEngine(); UInt nb_element = fem.getMesh().getNbElement(type, ghost_type); Array & mat_indexes = this->material_index(type, ghost_type); UInt nb_quadrature_points = fem.getNbQuadraturePoints(type); rho.resize(nb_element * nb_quadrature_points); Array::vector_iterator rho_it = rho.begin(spatial_dimension); /// compute @f$ rho @f$ for each nodes of each element for (UInt el = 0; el < nb_element; ++el) { Real mat_rho = mat_val[mat_indexes(el)]->getParam( "rho"); /// here rho is constant in an element for (UInt n = 0; n < nb_quadrature_points; ++n, ++rho_it) { *rho_it = mat_rho; } } AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/src/model/time_step_solver.hh b/src/model/time_step_solver.hh index c0e980e42..ccc0dc157 100644 --- a/src/model/time_step_solver.hh +++ b/src/model/time_step_solver.hh @@ -1,101 +1,92 @@ /** * @file time_step_solver.hh * * @author Nicolas Richart * * @date Mon Aug 24 12:42:04 2015 * * @brief This corresponding to the time step evolution solver * * @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_memory.hh" #include "aka_array.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_TIME_STEP_SOLVER_HH__ #define __AKANTU_TIME_STEP_SOLVER_HH__ namespace akantu { class DOFManager; } __BEGIN_AKANTU__ -class TimeStepSolver { +class TimeStepSolver : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - TimeStepSolver(const TimeStepSolverType & time_step_solver_type); + TimeStepSolver(DOFManager & dof_manager, const ID & dof_id, + const TimeStepSolverType & type, const ID & id, + UInt memory_id); virtual ~TimeStepSolver(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void solveStep(); private: virtual void predictor() = 0; virtual void corrector() = 0; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Underlying dof manager containing the dof to treat - DOFManager & dof_manager; + DOFManager & _dof_manager; /// The dof to make evolve ID dof_id; + /// Type of solver + TimeStepSolverType type; + /// The increment of the dof from @f[ u_{n+1} = u_{n} + inc @f] Array increment; /// The time step for this solver Real time_step; }; -// /// standard output stream operator -// inline std::ostream & operator <<(std::ostream & stream, const TimeStepSolver & _this) -// { -// _this.printself(stream); -// return stream; -// } - __END_AKANTU__ -/* -------------------------------------------------------------------------- */ -/* inline functions */ -/* -------------------------------------------------------------------------- */ - -//#include "time_step_solver_inline_impl.cc" - - #endif /* __AKANTU_TIME_STEP_SOLVER_HH__ */ diff --git a/src/model/time_step_solvers/time_step_solver.cc b/src/model/time_step_solvers/time_step_solver.cc new file mode 100644 index 000000000..8616755a7 --- /dev/null +++ b/src/model/time_step_solvers/time_step_solver.cc @@ -0,0 +1,42 @@ +/** + * @file time_step_solver.cc + * + * @author Nicolas Richart + * + * @date Mon Oct 12 16:56:43 2015 + * + * @brief Implementation of common part of TimeStepSolvers + * + * @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 "time_step_solver.hh" +/* -------------------------------------------------------------------------- */ + +__BEGIN_AKANTU__ + +TimeStepSolver::TimeStepSolver(DOFManager & dof_manager, const ID & dof_id, + const TimeStepSolverType & type, const ID & id, + UInt memory_id) + : Memory(id, memory_id), _dof_manager(dof_manager), dof_id(dof_id), + type(type) {} + +__END_AKANTU__ diff --git a/src/model/time_step_solvers/time_step_solver_default.cc b/src/model/time_step_solvers/time_step_solver_default.cc index f576de483..7620d8e33 100644 --- a/src/model/time_step_solvers/time_step_solver_default.cc +++ b/src/model/time_step_solvers/time_step_solver_default.cc @@ -1,190 +1,218 @@ /** * @file time_step_solver_default.cc * * @author Nicolas Richart * * @date Wed Sep 16 10:20:55 2015 * * @brief Default implementation of the time step solver * * @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 "time_step_solver_default.hh" -#include "dof_manager.hh" +#include "dof_manager_default.hh" #include "integration_scheme_1st_order.hh" #include "integration_scheme_2nd_order.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ // void TimeStepSolverDefault::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, *blocked_dofs, // f_m2a); // } else if (method == _explicit_consistent_mass) { // solve(*increment_acceleration); // } // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ -TimeStepSolverDefault::TimeStepSolverDefault(const TimeStepSolverType & type) : - TimeStepSolver(type) { - switch(type) { - case _tsst_forward_euler: +TimeStepSolverDefault::TimeStepSolverDefault(DOFManagerDefault & dof_manager, + const ID & dof_id, + const TimeStepSolverType & type, + const ID & id, UInt memory_id) + : TimeStepSolver(dof_manager, dof_id, type, id, memory_id), + dof_manager(dof_manager) { + switch (type) { + case _tsst_forward_euler: { this->integration_scheme = new ForwardEuler(); - case _tsst_trapezoidal_rule_1: + break; + } + case _tsst_trapezoidal_rule_1: { this->integration_scheme = new TrapezoidalRule1(); - case _tsst_backward_euler: + break; + } + case _tsst_backward_euler: { this->integration_scheme = new BackwardEuler(); - case _tsst_central_difference: + break; + } + case _tsst_central_difference: { this->integration_scheme = new CentralDifference(); - case _tsst_trapezoidal_rule_2: + break; + } + case _tsst_fox_goodwin: { + this->integration_scheme = new FoxGoodwin(); + break; + } + case _tsst_trapezoidal_rule_2: { this->integration_scheme = new TrapezoidalRule2(); + break; + } + case _tsst_linear_acceleration: { + this->integration_scheme = new LinearAceleration(); + break; + } + // Write a c++11 version of the constructor with initializer list that + // contains the arguments for the integration scheme + case _tsst_generalized_trapezoidal: + case _tsst_newmark_beta: + AKANTU_EXCEPTION( + "This time step solvers cannot be created with this constructor"); } } /* -------------------------------------------------------------------------- */ TimeStepSolverDefault::~TimeStepSolverDefault() { delete this->integration_scheme; } /* -------------------------------------------------------------------------- */ void TimeStepSolverDefault::predictor() { AKANTU_DEBUG_IN(); Array & u = this->dof_manager.getDOFs(this->dof_id); const Array & blocked_dofs = this->dof_manager.getBlockedDOFs(this->dof_id); // increment.copy(u); if (this->integration_scheme->getOrder() == 1) { Array & u_dot = dof_manager.getDOFsDerivatives(this->dof_id, 1); IntegrationScheme1stOrder & int_scheme = *dynamic_cast(this->integration_scheme); int_scheme.integrationSchemePred(this->time_step, u, u_dot, blocked_dofs); } else if (this->integration_scheme->getOrder() == 2) { Array & u_dot = dof_manager.getDOFsDerivatives(this->dof_id, 1); Array & u_dot_dot = dof_manager.getDOFsDerivatives(this->dof_id, 2); IntegrationScheme2ndOrder & int_scheme = *dynamic_cast(this->integration_scheme); int_scheme.integrationSchemePred(this->time_step, u, u_dot, u_dot_dot, blocked_dofs); } // UInt nb_degree_of_freedom = u.getSize() * u.getNbComponent(); // Array::scalar_iterator incr_it = // increment.begin_reinterpret(nb_degree_of_freedom); // Array::const_scalar_iterator u_it = // u.begin_reinterpret(nb_degree_of_freedom); // Array::const_scalar_iterator u_end = // u.end_reinterpret(nb_degree_of_freedom); // for (; u_it != u_end; ++u_it, ++incr_it) { // *incr_it = *u_it - *incr_it; // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void TimeStepSolverDefault::corrector() { AKANTU_DEBUG_IN(); Array & u = this->dof_manager.getDOFs(this->dof_id); const Array & solution = this->dof_manager.getSolution(this->dof_id); const Array & blocked_dofs = this->dof_manager.getBlockedDOFs(this->dof_id); // increment.copy(u); if (this->integration_scheme->getOrder() == 1) { Array & u_dot = dof_manager.getDOFsDerivatives(this->dof_id, 1); IntegrationScheme1stOrder & int_scheme = *dynamic_cast(this->integration_scheme); switch (this->corrector_type) { case IntegrationScheme1stOrder::_temperature_corrector: int_scheme.integrationSchemeCorrTemp(this->time_step, u, u_dot, blocked_dofs, solution); break; case IntegrationScheme1stOrder::_temperature_rate_corrector: int_scheme.integrationSchemeCorrTempRate(this->time_step, u, u_dot, blocked_dofs, solution); break; } } else if (this->integration_scheme->getOrder() == 2) { Array & u_dot = dof_manager.getDOFsDerivatives(this->dof_id, 1); Array & u_dot_dot = dof_manager.getDOFsDerivatives(this->dof_id, 2); IntegrationScheme2ndOrder & int_scheme = *dynamic_cast(this->integration_scheme); switch (this->corrector_type) { case IntegrationScheme2ndOrder::_displacement_corrector: int_scheme.integrationSchemeCorrDispl(this->time_step, u, u_dot, u_dot_dot, blocked_dofs, solution); break; case IntegrationScheme2ndOrder::_velocity_corrector: int_scheme.integrationSchemeCorrVeloc(this->time_step, u, u_dot, u_dot_dot, blocked_dofs, solution); break; case IntegrationScheme2ndOrder::_acceleration_corrector: int_scheme.integrationSchemeCorrAccel(this->time_step, u, u_dot, u_dot_dot, blocked_dofs, solution); break; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void TimeStepSolverDefault::solveStep() { AKANTU_DEBUG_IN(); // EventManager::sendEvent( // SolidMechanicsModelEvent::BeforeSolveStepEvent(method)); // this->predictor(); // this->solver->solve(); // this->corrector(); // EventManager::sendEvent( // SolidMechanicsModelEvent::AfterSolveStepEvent(method)); AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/src/model/time_step_solvers/time_step_solver_default.hh b/src/model/time_step_solvers/time_step_solver_default.hh index 65685771f..8b310740d 100644 --- a/src/model/time_step_solvers/time_step_solver_default.hh +++ b/src/model/time_step_solvers/time_step_solver_default.hh @@ -1,82 +1,87 @@ /** * @file time_step_solver_default.hh * * @author Nicolas Richart * * @date Mon Aug 24 17:10:29 2015 * * @brief Default implementation for the time stepper * * @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 "time_step_solver.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_TIME_STEP_SOLVER_DEFAULT_HH__ #define __AKANTU_TIME_STEP_SOLVER_DEFAULT_HH__ namespace akantu { - class IntegrationScheme; +class IntegrationScheme; +class DOFManagerDefault; } __BEGIN_AKANTU__ class TimeStepSolverDefault : public TimeStepSolver { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - TimeStepSolverDefault(const TimeStepSolverType & type); + TimeStepSolverDefault(DOFManagerDefault & dof_manager, const ID & dof_id, + const TimeStepSolverType & type, const ID & id, + UInt memory_id); + virtual ~TimeStepSolverDefault(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// implementation of the TimeStepSolver::predictor() virtual void predictor(); /// implementation of the TimeStepSolver::corrector() virtual void corrector(); /// implementation of the generic TimeStepSolver::solveStep() virtual void solveStep(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: + /// DOFManager with its real type + DOFManagerDefault & dof_manager; + /// Underlying integration scheme IntegrationScheme * integration_scheme; /// Type of corrector to use UInt corrector_type; }; __END_AKANTU__ - #endif /* __AKANTU_TIME_STEP_SOLVER_DEFAULT_HH__ */ diff --git a/src/solver/solver_mumps.cc b/src/solver/solver_mumps.cc index 78139f664..c90606c1c 100644 --- a/src/solver/solver_mumps.cc +++ b/src/solver/solver_mumps.cc @@ -1,379 +1,365 @@ /** * @file sparse_solver_mumps.cc * * @author Nicolas Richart * * @date creation: Mon Dec 13 2010 * @date last modification: Mon Sep 15 2014 * * @brief implem of SparseSolverMumps class * * @section LICENSE * * Copyright (©) 2010-2012, 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 . * * @section DESCRIPTION * * @subsection Ctrl_param Control parameters * * ICNTL(1), * ICNTL(2), * ICNTL(3) : output streams for error, diagnostics, and global messages * * ICNTL(4) : verbose level : 0 no message - 4 all messages * * ICNTL(5) : type of matrix, 0 assembled, 1 elementary * * ICNTL(6) : control the permutation and scaling(default 7) see mumps doc for * more information * * ICNTL(7) : determine the pivot order (default 7) see mumps doc for more * information * * ICNTL(8) : describe the scaling method used * * ICNTL(9) : 1 solve A x = b, 0 solve At x = b * * ICNTL(10) : number of iterative refinement when NRHS = 1 * * ICNTL(11) : > 0 return statistics * * ICNTL(12) : only used for SYM = 2, ordering strategy * * ICNTL(13) : * * ICNTL(14) : percentage of increase of the estimated working space * * ICNTL(15-17) : not used * * ICNTL(18) : only used if ICNTL(5) = 0, 0 matrix centralized, 1 structure on * host and mumps give the mapping, 2 structure on host and distributed matrix * for facto, 3 distributed matrix * * ICNTL(19) : > 0, Shur complement returned * * ICNTL(20) : 0 rhs dense, 1 rhs sparse * * ICNTL(21) : 0 solution in rhs, 1 solution distributed in ISOL_loc and SOL_loc * allocated by user * * ICNTL(22) : 0 in-core, 1 out-of-core * * ICNTL(23) : maximum memory allocatable by mumps pre proc * * ICNTL(24) : controls the detection of "null pivot rows" * * ICNTL(25) : * * ICNTL(26) : * * ICNTL(27) : * * ICNTL(28) : 0 automatic choice, 1 sequential analysis, 2 parallel analysis * * ICNTL(29) : 0 automatic choice, 1 PT-Scotch, 2 ParMetis */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "dof_manager_default.hh" #include "sparse_matrix_aij.hh" #if defined(AKANTU_USE_MPI) #include "static_communicator_mpi.hh" #include "mpi_type_wrapper.hh" #endif #include "solver_mumps.hh" #include "dof_synchronizer.hh" /* -------------------------------------------------------------------------- */ // static std::ostream & operator <<(std::ostream & stream, const DMUMPS_STRUC_C // & _this) { // stream << "DMUMPS Data [" << std::endl; // stream << " + job : " << _this.job << std::endl; // stream << " + par : " << _this.par << std::endl; // stream << " + sym : " << _this.sym << std::endl; // stream << " + comm_fortran : " << _this.comm_fortran << std::endl; // stream << " + nz : " << _this.nz << std::endl; // stream << " + irn : " << _this.irn << std::endl; // stream << " + jcn : " << _this.jcn << std::endl; // stream << " + nz_loc : " << _this.nz_loc << std::endl; // stream << " + irn_loc : " << _this.irn_loc << std::endl; // stream << " + jcn_loc : " << _this.jcn_loc << std::endl; // stream << "]"; // return stream; // } __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ SparseSolverMumps::SparseSolverMumps(DOFManagerDefault & dof_manager, const ID & matrix_id, const ID & id, const MemoryID & memory_id) : SparseSolver(dof_manager, matrix_id, id, memory_id), dof_manager(dof_manager), matrix(dof_manager.getMatrix(matrix_id)), - rhs(dof_manager.getRHS()), master_rhs_solution(0, 1), - is_mumps_data_initialized(false), - communicator(StaticCommunicator::getStaticCommunicator()), - prank(communicator.whoAmI()) { + rhs(dof_manager.getResidual()), master_rhs_solution(0, 1) { AKANTU_DEBUG_IN(); + StaticCommunicator & communicator = StaticCommunicator::getStaticCommunicator(); + this->prank = communicator.whoAmI(); + #ifdef AKANTU_USE_MPI this->parallel_method = _fully_distributed; #else // AKANTU_USE_MPI this->parallel_method = _not_parallel; #endif // AKANTU_USE_MPI this->mumps_data.par = 1; // The host is part of computations switch (this->parallel_method) { case _not_parallel: break; case _master_slave_distributed: this->mumps_data.par = 0; // The host is not part of the computations case _fully_distributed: #ifdef AKANTU_USE_MPI const StaticCommunicatorMPI & mpi_st_comm = dynamic_cast( communicator.getRealStaticCommunicator()); this->mumps_data.comm_fortran = MPI_Comm_c2f(mpi_st_comm.getMPITypeWrapper().getMPICommunicator()); #else AKANTU_DEBUG_ERROR( "You cannot use parallel method to solve without activating MPI"); #endif break; } this->mumps_data.sym = 2 * (matrix.getMatrixType() == _symmetric); this->prank = communicator.whoAmI(); this->mumps_data.job = _smj_initialize; // initialize dmumps_c(&this->mumps_data); - this->is_mumps_data_initialized = true; - /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ // Output setup if (AKANTU_DEBUG_TEST(dblTrace)) { icntl(1) = 6; icntl(2) = 2; icntl(3) = 2; icntl(4) = 4; } else { /// No outputs icntl(1) = 6; // error output icntl(2) = 0; // dignostics output icntl(3) = 0; // informations icntl(4) = 0; // no outputs } if (AKANTU_DEBUG_TEST(dblDump)) { strcpy(this->mumps_data.write_problem, "mumps_matrix.mtx"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseSolverMumps::~SparseSolverMumps() { AKANTU_DEBUG_IN(); - this->destroyInternalData(); - - AKANTU_DEBUG_OUT(); -} - -/* -------------------------------------------------------------------------- */ -void SparseSolverMumps::destroyInternalData() { - AKANTU_DEBUG_IN(); - - if (this->is_mumps_data_initialized) { - this->mumps_data.job = _smj_destroy; // destroy - dmumps_c(&this->mumps_data); - this->is_mumps_data_initialized = false; - } + this->mumps_data.job = _smj_destroy; // destroy + dmumps_c(&this->mumps_data); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::initMumpsData() { // Default Scaling icntl(8) = 77; // Assembled matrix icntl(5) = 0; /// Default centralized dense second member icntl(20) = 0; icntl(21) = 0; // automatic choice for analysis icntl(28) = 0; UInt size = matrix.getSize(); if (prank == 0) { this->master_rhs_solution.resize(size); } this->mumps_data.nz_alloc = 0; this->mumps_data.n = size; switch (this->parallel_method) { case _fully_distributed: icntl(18) = 3; // fully distributed this->mumps_data.nz_loc = matrix.getNbNonZero(); this->mumps_data.irn_loc = matrix.getIRN().storage(); this->mumps_data.jcn_loc = matrix.getJCN().storage(); break; case _not_parallel: case _master_slave_distributed: icntl(18) = 0; // centralized if (prank == 0) { this->mumps_data.nz = matrix.getNbNonZero(); this->mumps_data.irn = matrix.getIRN().storage(); this->mumps_data.jcn = matrix.getJCN().storage(); } else { this->mumps_data.nz = 0; this->mumps_data.irn = NULL; this->mumps_data.jcn = NULL; } break; default: AKANTU_DEBUG_ERROR("This case should not happen!!"); } } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::initialize() { AKANTU_DEBUG_IN(); this->analysis(); // icntl(14) = 80; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::analysis() { AKANTU_DEBUG_IN(); initMumpsData(); this->mumps_data.job = _smj_analyze; // analyze dmumps_c(&this->mumps_data); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::factorize() { AKANTU_DEBUG_IN(); this->mumps_data.rhs = this->rhs.storage(); if (parallel_method == _fully_distributed) this->mumps_data.a_loc = this->matrix.getA().storage(); else { if (prank == 0) this->mumps_data.a = this->matrix.getA().storage(); } this->mumps_data.job = _smj_factorize; // factorize dmumps_c(&this->mumps_data); this->printError(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::solve() { AKANTU_DEBUG_IN(); // if (prank == 0) { // // deactivate debug messages // DebugLevel dbl = debug::getDebugLevel(); // debug::setDebugLevel(dblError); // matrix.getDOFSynchronizer().gather(this->rhs, 0, this->master_rhs_solution); // // reactivate debug messages // debug::setDebugLevel(dbl); // } else { // this->matrix.getDOFSynchronizer().gather(this->rhs, 0); // } if (prank == 0) this->mumps_data.rhs = this->master_rhs_solution.storage(); this->mumps_data.job = _smj_solve; // solve dmumps_c(&this->mumps_data); this->printError(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolverMumps::printError() { Int _info_v[2]; _info_v[0] = info(1); // to get errors _info_v[1] = -info(1); // to get warnings - communicator.allReduce(_info_v, 2, _so_min); + StaticCommunicator::getStaticCommunicator().allReduce(_info_v, 2, _so_min); _info_v[1] = -_info_v[1]; if (_info_v[0] < 0) { // < 0 is an error switch (_info_v[0]) { case -10: AKANTU_DEBUG_ERROR("The matrix is singular"); break; case -9: { icntl(14) += 10; if (icntl(14) != 90) { // std::cout << "Dynamic memory increase of 10%" << std::endl; AKANTU_DEBUG_WARNING( "MUMPS dynamic memory is insufficient it will be increased of 10%"); this->analysis(); this->factorize(); this->solve(); } else { AKANTU_DEBUG_ERROR("The MUMPS workarray is too small INFO(2)=" << info(2) << "No further increase possible"); break; } } default: AKANTU_DEBUG_ERROR("Error in mumps during solve process, check mumps " "user guide INFO(1) = " << _info_v[1]); } } else if (_info_v[1] > 0) { AKANTU_DEBUG_WARNING("Warning in mumps during solve process, check mumps " "user guide INFO(1) = " << _info_v[1]); } } __END_AKANTU__ diff --git a/src/solver/solver_mumps.hh b/src/solver/solver_mumps.hh index f3ea01c7a..be9e63cc4 100644 --- a/src/solver/solver_mumps.hh +++ b/src/solver/solver_mumps.hh @@ -1,153 +1,147 @@ /** * @file sparse_solver_mumps.hh * * @author Nicolas Richart * * @date creation: Mon Dec 13 2010 * @date last modification: Mon Sep 15 2014 * * @brief Solver class implementation for the mumps solver * * @section LICENSE * * Copyright (©) 2010-2012, 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 "sparse_solver.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLVER_MUMPS_HH__ #define __AKANTU_SOLVER_MUMPS_HH__ namespace akantu { class DOFManagerDefault; class SparseMatrixAIJ; } __BEGIN_AKANTU__ class SparseSolverMumps : public SparseSolver { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SparseSolverMumps(DOFManagerDefault & dof_manager, const ID & matrix_id, const ID & id = "sparse_solver_mumps", const MemoryID & memory_id = 0); virtual ~SparseSolverMumps(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// build the profile and do the analysis part virtual void initialize(); // void initializeSlave(SolverOptions & options = _solver_no_options); /// analysis (symbolic facto + permutations) virtual void analysis(); /// factorize the matrix virtual void factorize(); /// solve the system virtual void solve(); private: /// print the error if any happened in mumps void printError(); /// clean the mumps info virtual void destroyInternalData(); /// set internal values; void initMumpsData(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ private: /// access the control variable inline Int & icntl(UInt i) { return mumps_data.icntl[i - 1]; } /// access the results info inline Int & info(UInt i) { return mumps_data.info[i - 1]; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// DOFManager used by the Mumps implementation of the SparseSolver DOFManagerDefault & dof_manager; /// AIJ Matrix, usualy the jacobian matrix SparseMatrixAIJ & matrix; /// Right hand side per processors const Array & rhs; /// Full right hand side on the master processors and solution after solve Array master_rhs_solution; /// mumps data DMUMPS_STRUC_C mumps_data; - /// specify if the mumps_data are initialized or not - bool is_mumps_data_initialized; - - /// Communicator used for the solver - StaticCommunicator &communicator; - /// Rank of the current process UInt prank; /* ------------------------------------------------------------------------ */ /* Local types */ /* ------------------------------------------------------------------------ */ private: SolverParallelMethod parallel_method; bool rhs_is_local; enum SolverMumpsJob { _smj_initialize = -1, _smj_analyze = 1, _smj_factorize = 2, _smj_solve = 3, _smj_analyze_factorize = 4, _smj_factorize_solve = 5, _smj_complete = 6, // analyze, factorize, solve _smj_destroy = -2 }; }; __END_AKANTU__ #endif /* __AKANTU_SOLVER_MUMPS_HH__ */ diff --git a/src/solver/solver_petsc.cc b/src/solver/solver_petsc.cc index 68a47e1fd..b7daa92b8 100644 --- a/src/solver/solver_petsc.cc +++ b/src/solver/solver_petsc.cc @@ -1,1109 +1,1106 @@ /** * @file solver_petsc.cc * * @author Nicolas Richart # @author Alejandro M. Aragón * @author Aurelia Cuba Ramos * * @date Mon Dec 13 10:48:06 2010 * * @brief Solver class implementation for the petsc solver * * @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 "solver_petsc.hh" - #include "dof_manager_petsc.hh" #include "sparse_matrix_petsc.hh" - #include "mpi_type_wrapper.hh" - /* -------------------------------------------------------------------------- */ -#include #include +//#include /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ SolverPETSc::SolverPETSc(DOFManagerPETSc & dof_manager, const ID & matrix_id, const ID & id, const MemoryID & memory_id) : SparseSolver(dof_manager, matrix_id, id, memory_id), dof_manager(dof_manager), matrix(dof_manager.getMatrix(matrix_id)), is_petsc_data_initialized(false) { PetscErrorCode ierr; /// create a solver context - KSPCreate(PETSC_COMM_WORLD, &this->ksp); + ierr = KSPCreate(PETSC_COMM_WORLD, &this->ksp); CHKERRXX(ierr); } /* -------------------------------------------------------------------------- */ SolverPETSc::~SolverPETSc() { AKANTU_DEBUG_IN(); this->destroyInternalData(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolverPETSc::destroyInternalData() { AKANTU_DEBUG_IN(); if (this->is_petsc_data_initialized) { PetscErrorCode ierr; ierr = KSPDestroy(&(this->ksp)); CHKERRXX(ierr); this->is_petsc_data_initialized = false; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolverPETSc::initialize() { AKANTU_DEBUG_IN(); this->is_petsc_data_initialized = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolverPETSc::solve() { AKANTU_DEBUG_IN(); Vec & rhs = this->dof_manager.getResidual(); - Vec & solution = this->dof_manager.getSolution(); + Vec & solution = this->dof_manager.getGlobalSolution(); PetscErrorCode ierr; ierr = KSPSolve(this->ksp, rhs, solution); CHKERRXX(ierr); AKANTU_DEBUG_OUT(); } // /* -------------------------------------------------------------------------- */ // void SolverPETSc::solve(Array & solution) { // AKANTU_DEBUG_IN(); // this->solution = &solution; // this->solve(); // PetscErrorCode ierr; // PETScMatrix * petsc_matrix = static_cast(this->matrix); // // ierr = VecGetOwnershipRange(this->petsc_solver_wrapper->solution, // // solution_begin, solution_end); CHKERRXX(ierr); // // ierr = VecGetArray(this->petsc_solver_wrapper->solution, PetscScalar // // **array); CHKERRXX(ierr); // UInt nb_component = solution.getNbComponent(); // UInt size = solution.getSize(); // for (UInt i = 0; i < size; ++i) { // for (UInt j = 0; j < nb_component; ++j) { // UInt i_local = i * nb_component + j; // if (this->matrix->getDOFSynchronizer().isLocalOrMasterDOF(i_local)) { // Int i_global = // this->matrix->getDOFSynchronizer().getDOFGlobalID(i_local); // ierr = AOApplicationToPetsc(petsc_matrix->getPETScMatrixWrapper()->ao, // 1, &(i_global)); // CHKERRXX(ierr); // ierr = VecGetValues(this->petsc_solver_wrapper->solution, 1, &i_global, // &solution(i, j)); // CHKERRXX(ierr); // } // } // } // synch_registry->synchronize(_gst_solver_solution); // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void SolverPETSc::setOperators() { AKANTU_DEBUG_IN(); PetscErrorCode ierr; /// set the matrix that defines the linear system and the matrix for /// preconditioning (here they are the same) #if PETSC_VERSION_MAJOR >= 3 && PETSC_VERSION_MINOR >= 5 ierr = KSPSetOperators(this->ksp, this->matrix.getPETScMat(), this->matrix.getPETScMat()); CHKERRXX(ierr); #else ierr = KSPSetOperators(this->ksp, this->matrix.getPETScMat(), this->matrix.getPETScMat(), SAME_NONZERO_PATTERN); CHKERRXX(ierr); #endif /// If this is not called the solution vector is zeroed in the call to /// KSPSolve(). ierr = KSPSetInitialGuessNonzero(this->ksp, PETSC_TRUE); KSPSetFromOptions(this->ksp); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ // void finalize_petsc() { // static bool finalized = false; // if (!finalized) { // cout<<"*** INFO *** PETSc is finalizing..."<first; // ierr = VecSetValues(b, 1, &row, &it->second, ADD_VALUES); // } // #ifdef CPPUTILS_VERBOSE // out<<" Right hand side set... "< subs = AA.unhash(it->first); // PetscInt row = subs.first; // PetscInt col = subs.second; // ierr = MatSetValues(A_, 1, &row, 1, &col, &it->second, // ADD_VALUES);CHKERRCONTINUE(ierr); // } // #ifdef CPPUTILS_VERBOSE // out<<" Filled sparse matrix... "< -pc_type -ksp_monitor -ksp_rtol // // These options will override those specified above as long as // // KSPSetFromOptions() is called _after_ any other customization // // routines. // // */ // // ierr = KSPSetFromOptions(ksp);CHKERRCONTINUE(ierr); // #ifdef CPPUTILS_VERBOSE // out<<" Solving system... "<first; // ierr = VecGetValues(x_all, 1, &row, &val); // if (val != zero) // xx[row] = val; // } // #ifdef CPPUTILS_VERBOSE // out<<" Solution vector copied... "< Kpf_nz = KKpf.non_zero_off_diagonal(); // std::pair Kpp_nz = KKpp.non_zero_off_diagonal(); // ierr = MatMPIAIJSetPreallocation(Kpf, Kpf_nz.first, PETSC_NULL, // Kpf_nz.second, PETSC_NULL); CHKERRCONTINUE(ierr); // ierr = MatMPIAIJSetPreallocation(Kpp, Kpp_nz.first, PETSC_NULL, // Kpp_nz.second, PETSC_NULL); CHKERRCONTINUE(ierr); // ierr = MatSeqAIJSetPreallocation(Kpf, Kpf_nz.first, PETSC_NULL); // CHKERRCONTINUE(ierr); // ierr = MatSeqAIJSetPreallocation(Kpp, Kpp_nz.first, PETSC_NULL); // CHKERRCONTINUE(ierr); // for (sparse_matrix_type::const_hash_iterator it = KKpf.map_.begin(); it != // KKpf.map_.end(); ++it) { // // get subscripts // std::pair subs = KKpf.unhash(it->first); // int row = subs.first; // int col = subs.second; // ierr = MatSetValues(Kpf, 1, &row, 1, &col, &it->second, // ADD_VALUES);CHKERRCONTINUE(ierr); // } // for (sparse_matrix_type::const_hash_iterator it = KKpp.map_.begin(); it != // KKpp.map_.end(); ++it) { // // get subscripts // std::pair subs = KKpp.unhash(it->first); // int row = subs.first; // int col = subs.second; // ierr = MatSetValues(Kpf, 1, &row, 1, &col, &it->second, // ADD_VALUES);CHKERRCONTINUE(ierr); // } // #ifdef CPPUTILS_VERBOSE // out<<" Filled sparse matrices... "<first; // ierr = VecSetValues(Up, 1, &row, &it->second, ADD_VALUES); // } // /* // Assemble vector, using the 2-step process: // VecAssemblyBegin(), VecAssemblyEnd() // Computations can be done while messages are in transition // by placing code between these two statements. // */ // ierr = VecAssemblyBegin(Up);CHKERRCONTINUE(ierr); // ierr = VecAssemblyEnd(Up);CHKERRCONTINUE(ierr); // // add Kpf*Uf // ierr = MatMult(Kpf, x_, Pf); // // add Kpp*Up // ierr = MatMultAdd(Kpp, Up, Pf, Pp); // #ifdef CPPUTILS_VERBOSE // out<<" Matrices multiplied... "<first; // ierr = VecSetValues(r, 1, &row, &it->second, ADD_VALUES); // } // for (sparse_vector_type::const_hash_iterator it = bb.map_.begin(); it != // bb.map_.end(); ++it) { // int row = it->first; // ierr = VecSetValues(r, 1, &row, &it->second, ADD_VALUES); // } // /* // Assemble vector, using the 2-step process: // VecAssemblyBegin(), VecAssemblyEnd() // Computations can be done while messages are in transition // by placing code between these two statements. // */ // ierr = VecAssemblyBegin(r);CHKERRCONTINUE(ierr); // ierr = VecAssemblyEnd(r);CHKERRCONTINUE(ierr); // sparse_vector_type rr(aa.size()); // for (sparse_vector_type::const_hash_iterator it = aa.map_.begin(); it != // aa.map_.end(); ++it) { // int row = it->first; // ierr = VecGetValues(r, 1, &row, &rr[row]); // } // for (sparse_vector_type::const_hash_iterator it = bb.map_.begin(); it != // bb.map_.end(); ++it) { // int row = it->first; // ierr = VecGetValues(r, 1, &row, &rr[row]); // } // #ifdef CPPUTILS_VERBOSE // out<<" Vector copied... "< subs = aa.unhash(it->first); // int row = subs.first; // int col = subs.second; // if (flag == Add_t) // ierr = MatSetValues(r, 1, &row, 1, &col, &it->second, ADD_VALUES); // else if (flag == Insert_t) // ierr = MatSetValues(r, 1, &row, 1, &col, &it->second, INSERT_VALUES); // CHKERRCONTINUE(ierr); // } // #ifdef CPPUTILS_VERBOSE // out<<" Matrix filled..."<first; // if (flag == Add_t) // ierr = VecSetValues(r, 1, &row, &it->second, ADD_VALUES); // else if (flag == Insert_t) // ierr = VecSetValues(r, 1, &row, &it->second, INSERT_VALUES); // CHKERRCONTINUE(ierr); // } // #ifdef CPPUTILS_VERBOSE // out<<" Vector filled..."<(comm.getRealStaticCommunicator()); // // if(mumps_data.comm_fortran == // MPI_Comm_c2f(comm_mpi.getMPICommunicator())) // // destroyMumpsData(); // // } catch(...) {} // // // // AKANTU_DEBUG_OUT(); // //} // // // ///* // -------------------------------------------------------------------------- */ // //void SolverMumps::initMumpsData(SolverMumpsOptions::ParallelMethod // parallel_method) { // // switch(parallel_method) { // // case SolverMumpsOptions::_fully_distributed: // // icntl(18) = 3; //fully distributed // // icntl(28) = 0; //automatic choice // // // // mumps_data.nz_loc = matrix->getNbNonZero(); // // mumps_data.irn_loc = matrix->getIRN().values; // // mumps_data.jcn_loc = matrix->getJCN().values; // // break; // // case SolverMumpsOptions::_master_slave_distributed: // // if(prank == 0) { // // mumps_data.nz = matrix->getNbNonZero(); // // mumps_data.irn = matrix->getIRN().values; // // mumps_data.jcn = matrix->getJCN().values; // // } else { // // mumps_data.nz = 0; // // mumps_data.irn = NULL; // // mumps_data.jcn = NULL; // // // // icntl(18) = 0; //centralized // // icntl(28) = 0; //sequential analysis // // } // // break; // // } // //} // // // ///* // -------------------------------------------------------------------------- */ // //void SolverMumps::initialize(SolverOptions & options) { // // AKANTU_DEBUG_IN(); // // // // mumps_data.par = 1; // // // // if(SolverMumpsOptions * opt = dynamic_cast(&options)) { // // if(opt->parallel_method == // SolverMumpsOptions::_master_slave_distributed) { // // mumps_data.par = 0; // // } // // } // // // // mumps_data.sym = 2 * (matrix->getSparseMatrixType() == _symmetric); // // prank = communicator.whoAmI(); // //#ifdef AKANTU_USE_MPI // // mumps_data.comm_fortran = MPI_Comm_c2f(dynamic_cast(communicator.getRealStaticCommunicator()).getMPICommunicator()); // //#endif // // // // if(AKANTU_DEBUG_TEST(dblTrace)) { // // icntl(1) = 2; // // icntl(2) = 2; // // icntl(3) = 2; // // icntl(4) = 4; // // } // // // // mumps_data.job = _smj_initialize; //initialize // // dmumps_c(&mumps_data); // // is_mumps_data_initialized = true; // // // // /* // ------------------------------------------------------------------------ */ // // UInt size = matrix->getSize(); // // // // if(prank == 0) { // // std::stringstream sstr_rhs; sstr_rhs << id << ":rhs"; // // rhs = &(alloc(sstr_rhs.str(), size, 1, REAL_INIT_VALUE)); // // } else { // // rhs = NULL; // // } // // // // /// No outputs // // icntl(1) = 0; // // icntl(2) = 0; // // icntl(3) = 0; // // icntl(4) = 0; // // mumps_data.nz_alloc = 0; // // // // if (AKANTU_DEBUG_TEST(dblDump)) icntl(4) = 4; // // // // mumps_data.n = size; // // // // if(AKANTU_DEBUG_TEST(dblDump)) { // // strcpy(mumps_data.write_problem, "mumps_matrix.mtx"); // // } // // // // /* // ------------------------------------------------------------------------ */ // // // Default Scaling // // icntl(8) = 77; // // // // icntl(5) = 0; // Assembled matrix // // // // SolverMumpsOptions * opt = dynamic_cast(&options); // // if(opt) // // parallel_method = opt->parallel_method; // // // // initMumpsData(parallel_method); // // // // mumps_data.job = _smj_analyze; //analyze // // dmumps_c(&mumps_data); // // // // AKANTU_DEBUG_OUT(); // //} // // // ///* // -------------------------------------------------------------------------- */ // //void SolverMumps::setRHS(Array & rhs) { // // if(prank == 0) { // // matrix->getDOFSynchronizer().gather(rhs, 0, this->rhs); // // } else { // // matrix->getDOFSynchronizer().gather(rhs, 0); // // } // //} // // // ///* // -------------------------------------------------------------------------- */ // //void SolverMumps::solve() { // // AKANTU_DEBUG_IN(); // // // // if(parallel_method == SolverMumpsOptions::_fully_distributed) // // mumps_data.a_loc = matrix->getA().values; // // else // // if(prank == 0) { // // mumps_data.a = matrix->getA().values; // // } // // // // if(prank == 0) { // // mumps_data.rhs = rhs->values; // // } // // // // /// Default centralized dense second member // // icntl(20) = 0; // // icntl(21) = 0; // // // // mumps_data.job = _smj_factorize_solve; //solve // // dmumps_c(&mumps_data); // // // // AKANTU_DEBUG_ASSERT(info(1) != -10, "Singular matrix"); // // AKANTU_DEBUG_ASSERT(info(1) == 0, // // "Error in mumps during solve process, check mumps // user guide INFO(1) =" // // << info(1)); // // // // AKANTU_DEBUG_OUT(); // //} // // // ///* // -------------------------------------------------------------------------- */ // //void SolverMumps::solve(Array & solution) { // // AKANTU_DEBUG_IN(); // // // // solve(); // // // // if(prank == 0) { // // matrix->getDOFSynchronizer().scatter(solution, 0, this->rhs); // // } else { // // matrix->getDOFSynchronizer().scatter(solution, 0); // // } // // // // AKANTU_DEBUG_OUT(); // //} __END_AKANTU__ diff --git a/src/solver/sparse_matrix.cc b/src/solver/sparse_matrix.cc index b89e40f8d..ae3e805c4 100644 --- a/src/solver/sparse_matrix.cc +++ b/src/solver/sparse_matrix.cc @@ -1,89 +1,68 @@ /** * @file sparse_matrix.cc * * @author Nicolas Richart * * @date creation: Mon Dec 13 2010 * @date last modification: Mon Sep 15 2014 * * @brief implementation of the SparseMatrix class * * @section LICENSE * * Copyright (©) 2010-2012, 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 "sparse_matrix.hh" #include "static_communicator.hh" #include "dof_manager.hh" /* -------------------------------------------------------------------------- */ - __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ SparseMatrix::SparseMatrix(DOFManager & dof_manager, - const MatrixType & matrix_type, - const ID & id, - const MemoryID & memory_id) : - Memory(id, memory_id), - dof_manager(dof_manager), - matrix_type(matrix_type), - size(dof_manager.getSystemSize()), - nb_non_zero(0) { + const MatrixType & matrix_type, const ID & id, + const MemoryID & memory_id) + : Memory(id, memory_id), dof_manager(dof_manager), matrix_type(matrix_type), + size(dof_manager.getSystemSize()), nb_non_zero(0), matrix_release(1) { AKANTU_DEBUG_IN(); - this->offset = 1; - StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); this->nb_proc = comm.getNbProc(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -SparseMatrix::SparseMatrix(const SparseMatrix & matrix, - const ID & id, - const MemoryID & memory_id) : - Memory(id, memory_id), - dof_manager(matrix.dof_manager), - matrix_type(matrix.matrix_type), - size(matrix.size), - nb_proc(matrix.nb_proc), - nb_non_zero(matrix.nb_non_zero) { - AKANTU_DEBUG_IN(); - - this->offset = 1; - - AKANTU_DEBUG_OUT(); -} - +SparseMatrix::SparseMatrix(const SparseMatrix & matrix, const ID & id, + const MemoryID & memory_id) + : Memory(id, memory_id), dof_manager(matrix.dof_manager), + matrix_type(matrix.matrix_type), size(matrix.size), + nb_proc(matrix.nb_proc), nb_non_zero(matrix.nb_non_zero), + matrix_release(1) {} /* -------------------------------------------------------------------------- */ -SparseMatrix::~SparseMatrix() { - AKANTU_DEBUG_IN(); - - AKANTU_DEBUG_OUT(); -} +SparseMatrix::~SparseMatrix() {} /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/solver/sparse_matrix.hh b/src/solver/sparse_matrix.hh index f288c4198..c9e4efb20 100644 --- a/src/solver/sparse_matrix.hh +++ b/src/solver/sparse_matrix.hh @@ -1,138 +1,137 @@ /** * @file sparse_matrix.hh * * @author Nicolas Richart * * @date creation: Mon Dec 13 2010 * @date last modification: Mon Sep 15 2014 * * @brief sparse matrix storage class (distributed assembled matrix) * This is a COO format (Coordinate List) * * @section LICENSE * * Copyright (©) 2010-2012, 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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SPARSE_MATRIX_HH__ #define __AKANTU_SPARSE_MATRIX_HH__ /* -------------------------------------------------------------------------- */ #include "dof_manager.hh" #include "mesh.hh" __BEGIN_AKANTU__ class SparseMatrix : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SparseMatrix(DOFManager & dof_manager, const MatrixType & matrix_type, const ID & id = "sparse_matrix", const MemoryID & memory_id = 0); SparseMatrix(const SparseMatrix & matrix, const ID & id = "sparse_matrix", const MemoryID & memory_id = 0); virtual ~SparseMatrix(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// remove the existing profile virtual void clearProfile(); /// set the matrix to 0 virtual void clear(); /// add a non-zero element to the profile virtual inline UInt addToProfile(UInt i, UInt j) = 0; /// assemble a local matrix in the sparse one virtual inline void addToMatrix(UInt i, UInt j, Real value) = 0; /// save the profil in a file using the MatrixMarket file format virtual void saveProfile(const std::string & filename) const; /// save the matrix in a file using the MatrixMarket file format virtual void saveMatrix(const std::string & filename) const; /// copy assuming the profile are the same virtual void copyContent(const SparseMatrix & matrix); /// add matrix assuming the profile are the same virtual void add(const SparseMatrix & matrix, Real alpha); /// modify the matrix to "remove" the blocked dof virtual void applyBoundary(const Array & boundary, Real block_val = 1.); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// return the values at potition i, j virtual inline Real operator()(UInt i, UInt j) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// return the values at potition i, j virtual inline Real & operator()(UInt i, UInt j) { AKANTU_DEBUG_TO_IMPLEMENT(); } AKANTU_GET_MACRO(NbNonZero, nb_non_zero, UInt); AKANTU_GET_MACRO(Size, size, UInt); AKANTU_GET_MACRO(MatrixType, matrix_type, const MatrixType &); - AKANTU_GET_MACRO(Offset, offset, UInt); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Underlying dof manager DOFManager & dof_manager; /// sparce matrix type MatrixType matrix_type; /// Size of the matrix UInt size; /// number of processors UInt nb_proc; /// number of non zero element UInt nb_non_zero; - /// Offset indexes - UInt offset; + /// matrix definition releasez + UInt matrix_release; }; Array & operator*=(Array & vect, const SparseMatrix & mat); __END_AKANTU__ /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "sparse_matrix_inline_impl.cc" #endif /* __AKANTU_SPARSE_MATRIX_HH__ */ diff --git a/src/solver/sparse_matrix_aij.cc b/src/solver/sparse_matrix_aij.cc index 816282ba4..667191f40 100644 --- a/src/solver/sparse_matrix_aij.cc +++ b/src/solver/sparse_matrix_aij.cc @@ -1,284 +1,309 @@ /** * @file sparse_matrix_aij.cc * * @author Nicolas Richart * * @date Tue Aug 18 16:31:23 2015 * * @brief Implementation of the AIJ sparse 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 "sparse_matrix_aij.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ +/* -------------------------------------------------------------------------- */ +SparseMatrixAIJ::SparseMatrixAIJ(DOFManager & dof_manager, + const MatrixType & matrix_type, const ID & id, + const MemoryID & memory_id) + : SparseMatrix(dof_manager, matrix_type, id, memory_id), + irn(0, 1, id + ":irn"), jcn(0, 1, id + ":jcn"), a(0, 1, id + ":a"), + profile_release(0), value_release(0) {} + +/* -------------------------------------------------------------------------- */ +SparseMatrixAIJ::SparseMatrixAIJ(const SparseMatrixAIJ & matrix, const ID & id, + const MemoryID & memory_id) + : SparseMatrix(matrix, id, memory_id), irn(matrix.irn, true, id + ":irn"), + jcn(matrix.jcn, true, id + ":jcn"), a(matrix.a, true, id + ":a"), + profile_release(0), value_release(0) {} + +/* -------------------------------------------------------------------------- */ +SparseMatrixAIJ::~SparseMatrixAIJ() {} + // /* -------------------------------------------------------------------------- // */ // void SparseMatrixAIJ::buildProfile(const Mesh & mesh, // const DOFSynchronizer & dof_synchronizer, // UInt nb_degree_of_freedom) { // AKANTU_DEBUG_IN(); // // if(irn_jcn_to_k) delete irn_jcn_to_k; // // irn_jcn_to_k = new std::map, UInt>; // clearProfile(); // this->dof_synchronizer = &const_cast(dof_synchronizer); // coordinate_list_map::iterator irn_jcn_k_it; // Int * eq_nb_val = dof_synchronizer.getGlobalDOFEquationNumbers().storage(); // Mesh::type_iterator it = // mesh.firstType(mesh.getSpatialDimension(), _not_ghost, // _ek_not_defined); // Mesh::type_iterator end = // mesh.lastType(mesh.getSpatialDimension(), _not_ghost, _ek_not_defined); // for (; it != end; ++it) { // UInt nb_element = mesh.getNbElement(*it); // UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); // UInt size_mat = nb_nodes_per_element * nb_degree_of_freedom; // UInt * conn_val = mesh.getConnectivity(*it, _not_ghost).storage(); // Int * local_eq_nb_val = // new Int[nb_degree_of_freedom * nb_nodes_per_element]; // for (UInt e = 0; e < nb_element; ++e) { // Int * tmp_local_eq_nb_val = local_eq_nb_val; // for (UInt i = 0; i < nb_nodes_per_element; ++i) { // UInt n = conn_val[i]; // for (UInt d = 0; d < nb_degree_of_freedom; ++d) { // *tmp_local_eq_nb_val++ = eq_nb_val[n * nb_degree_of_freedom + d]; // } // // memcpy(tmp_local_eq_nb_val, eq_nb_val + n * nb_degree_of_freedom, // // nb_degree_of_freedom * sizeof(Int)); // // tmp_local_eq_nb_val += nb_degree_of_freedom; // } // for (UInt i = 0; i < size_mat; ++i) { // UInt c_irn = local_eq_nb_val[i]; // if (c_irn < this->size) { // UInt j_start = (sparse_matrix_type == _symmetric) ? i : 0; // for (UInt j = j_start; j < size_mat; ++j) { // UInt c_jcn = local_eq_nb_val[j]; // if (c_jcn < this->size) { // KeyCOO irn_jcn = key(c_irn, c_jcn); // irn_jcn_k_it = irn_jcn_k.find(irn_jcn); // if (irn_jcn_k_it == irn_jcn_k.end()) { // irn_jcn_k[irn_jcn] = nb_non_zero; // irn.push_back(c_irn + 1); // jcn.push_back(c_jcn + 1); // nb_non_zero++; // } // } // } // } // } // conn_val += nb_nodes_per_element; // } // delete[] local_eq_nb_val; // } // /// for pbc @todo correct it for parallel // if (StaticCommunicator::getStaticCommunicator().getNbProc() == 1) { // for (UInt i = 0; i < size; ++i) { // KeyCOO irn_jcn = key(i, i); // irn_jcn_k_it = irn_jcn_k.find(irn_jcn); // if (irn_jcn_k_it == irn_jcn_k.end()) { // irn_jcn_k[irn_jcn] = nb_non_zero; // irn.push_back(i + 1); // jcn.push_back(i + 1); // nb_non_zero++; // } // } // } // a.resize(nb_non_zero); // AKANTU_DEBUG_OUT(); // } // /* -------------------------------------------------------------------------- // */ // void SparseMatrixAIJ::applyBoundary(const Array & boundary, // Real block_val) { // AKANTU_DEBUG_IN(); // const DOFSynchronizer::GlobalEquationNumberMap & local_eq_num_to_global = // dof_synchronizer->getGlobalEquationNumberToLocal(); // Int * irn_val = irn.storage(); // Int * jcn_val = jcn.storage(); // Real * a_val = a.storage(); // for (UInt i = 0; i < nb_non_zero; ++i) { // /// @todo fix this hack, put here for the implementation of augmented // /// lagrangian contact // if (local_eq_num_to_global.find(*irn_val - 1) == // local_eq_num_to_global.end()) // continue; // if (local_eq_num_to_global.find(*jcn_val - 1) == // local_eq_num_to_global.end()) // continue; // UInt ni = local_eq_num_to_global.find(*irn_val - 1)->second; // UInt nj = local_eq_num_to_global.find(*jcn_val - 1)->second; // if (boundary.storage()[ni] || boundary.storage()[nj]) { // if (*irn_val != *jcn_val) { *a_val = 0; } else { // if (dof_synchronizer->getDOFTypes()(ni) >= 0) { *a_val = 0; } else { // *a_val = block_val; // } // } // } // irn_val++; // jcn_val++; // a_val++; // } // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::saveProfile(const std::string & filename) const { AKANTU_DEBUG_IN(); std::ofstream outfile; outfile.open(filename.c_str()); outfile << "%%MatrixMarket matrix coordinate pattern"; if (this->matrix_type == _symmetric) outfile << " symmetric"; else outfile << " general"; outfile << std::endl; UInt m = this->size; outfile << m << " " << m << " " << this->nb_non_zero << std::endl; for (UInt i = 0; i < this->nb_non_zero; ++i) { outfile << this->irn.storage()[i] << " " << this->jcn.storage()[i] << " 1" << std::endl; } outfile.close(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::saveMatrix(const std::string & filename) const { AKANTU_DEBUG_IN(); std::ofstream outfile; outfile.precision(std::numeric_limits::digits10); outfile.open(filename.c_str()); outfile << "%%MatrixMarket matrix coordinate real"; if (this->matrix_type == _symmetric) outfile << " symmetric"; else outfile << " general"; outfile << std::endl; outfile << this->size << " " << this->size << " " << this->nb_non_zero << std::endl; for (UInt i = 0; i < this->nb_non_zero; ++i) { outfile << this->irn(i) << " " << this->jcn(i) << " " << this->a(i) << std::endl; } outfile.close(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::matVecMul(const Array & x, Array & y, Real alpha, Real beta) { AKANTU_DEBUG_IN(); y *= beta; Array::const_scalar_iterator i_it = this->irn.storage(); Array::const_scalar_iterator j_it = this->jcn.storage(); Array::const_scalar_iterator a_it = this->a.storage(); Array::const_scalar_iterator x_it = x.storage(); Array::scalar_iterator y_it = y.storage(); for (UInt k = 0; k < this->nb_non_zero; ++k, ++i_it, ++j_it, ++a_it) { const Int & i = *i_it; const Int & j = *j_it; const Real & A = *a_it; y_it[i] += alpha * A * x_it[j]; if ((this->matrix_type == _symmetric) && (i != j)) y_it[j] += alpha * A * x_it[i]; } // if (dof_synchronizer) // dof_synchronizer->reduceSynchronize(vect); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::copyContent(const SparseMatrix & matrix) { AKANTU_DEBUG_IN(); const SparseMatrixAIJ & mat = dynamic_cast(matrix); AKANTU_DEBUG_ASSERT(nb_non_zero == mat.getNbNonZero(), "The to matrix don't have the same profiles"); memcpy(a.storage(), mat.getA().storage(), nb_non_zero * sizeof(Real)); + + this->value_release++; + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::add(const SparseMatrix & B, Real alpha) { Array::scalar_iterator a_it = this->a.storage(); Array::const_scalar_iterator i_it = this->irn.storage(); Array::const_scalar_iterator j_it = this->jcn.storage(); for (UInt n = 0; n < this->nb_non_zero; ++n, ++a_it, ++i_it, ++j_it) { const Int & i = *i_it; const Int & j = *j_it; Real & A_ij = *a_it; A_ij += alpha * B(i - 1, j - 1); } + + this->value_release++; } /* -------------------------------------------------------------------------- */ void SparseMatrixAIJ::clear() { memset(a.storage(), 0, nb_non_zero * sizeof(Real)); + + this->value_release++; } __END_AKANTU__ diff --git a/src/solver/sparse_matrix_aij.hh b/src/solver/sparse_matrix_aij.hh index 118db3b2f..7cb8746b8 100644 --- a/src/solver/sparse_matrix_aij.hh +++ b/src/solver/sparse_matrix_aij.hh @@ -1,182 +1,187 @@ /** * @file sparse_matrix_aij.hh * * @author Nicolas Richart * * @date Mon Aug 17 21:22:57 2015 * * @brief AIJ implementation of the SparseMatrix (this the format used by Mumps) * * @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 "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SPARSE_MATRIX_AIJ_HH__ #define __AKANTU_SPARSE_MATRIX_AIJ_HH__ /* -------------------------------------------------------------------------- */ #if defined(AKANTU_UNORDERED_MAP_IS_CXX11) __BEGIN_AKANTU_UNORDERED_MAP__ #if AKANTU_INTEGER_SIZE == 4 #define AKANTU_HASH_COMBINE_MAGIC_NUMBER 0x9e3779b9 #elif AKANTU_INTEGER_SIZE == 8 #define AKANTU_HASH_COMBINE_MAGIC_NUMBER 0x9e3779b97f4a7c13LL #endif /** * Hashing function for pairs based on hash_combine from boost The magic number * is coming from the golden number @f[\phi = \frac{1 + \sqrt5}{2}@f] * @f[\frac{2^32}{\phi} = 0x9e3779b9@f] * http://stackoverflow.com/questions/4948780/magic-number-in-boosthash-combine * http://burtleburtle.net/bob/hash/doobs.html */ template struct hash > { public: hash() : ah(), bh() {} size_t operator()(const std::pair & p) const { size_t seed = ah(p.first); return bh(p.second) + AKANTU_HASH_COMBINE_MAGIC_NUMBER + (seed << 6) + (seed >> 2); } private: const hash ah; const hash bh; }; __END_AKANTU_UNORDERED_MAP__ #endif __BEGIN_AKANTU__ class SparseMatrixAIJ : public SparseMatrix { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SparseMatrixAIJ(DOFManager & dof_manager, const MatrixType & matrix_type, const ID & id = "sparse_matrix_aij", const MemoryID & memory_id = 0); - SparseMatrixAIJ(const SparseMatrix & matrix, const ID & id = "sparse_matrix_aij", + SparseMatrixAIJ(const SparseMatrixAIJ & matrix, const ID & id = "sparse_matrix_aij", const MemoryID & memory_id = 0); virtual ~SparseMatrixAIJ(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// remove the existing profile inline void clearProfile(); /// add a non-zero element virtual UInt addToProfile(UInt i, UInt j); /// set the matrix to 0 virtual void clear(); /// assemble a local matrix in the sparse one inline void addToMatrix(UInt i, UInt j, Real value); /// set the size of the matrix void resize(UInt size) { this->size = size; } /// modify the matrix to "remove" the blocked dof virtual void applyBoundary(const Array & boundary, Real block_val = 1.); /// save the profil in a file using the MatrixMarket file format virtual void saveProfile(const std::string & filename) const; /// save the matrix in a file using the MatrixMarket file format virtual void saveMatrix(const std::string & filename) const; /// copy assuming the profile are the same virtual void copyContent(const SparseMatrix & matrix); /// add matrix assuming the profile are the same virtual void add(const SparseMatrix & matrix, Real alpha); /// Equivalent of *gemv in blas virtual void matVecMul(const Array & x, Array & y, Real alpha = 1., Real beta = 0.); /* ------------------------------------------------------------------------ */ /// accessor to A_{ij} - if (i, j) not present it returns 0 inline Real operator()(UInt i, UInt j) const; /// accessor to A_{ij} - if (i, j) not present it fails, (i, j) should be /// first added to the profile inline Real & operator()(UInt i, UInt j); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(IRN, irn, const Array &); AKANTU_GET_MACRO(JCN, jcn, const Array &); AKANTU_GET_MACRO(A, a, const Array &); protected: typedef std::pair KeyCOO; typedef unordered_map::type coordinate_list_map; /// get the pair corresponding to (i, j) inline KeyCOO key(UInt i, UInt j) const { if (this->matrix_type == _symmetric && (i > j)) return std::make_pair(j, i); return std::make_pair(i, j); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// row indexes Array irn; /// column indexes Array jcn; /// values : A[k] = Matrix[irn[k]][jcn[k]] Array a; + /// Profile release + UInt profile_release; + /// Value release + UInt value_release; + /* * map for (i, j) -> k correspondence */ coordinate_list_map irn_jcn_k; }; __END_AKANTU__ /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "sparse_matrix_aij_inline_impl.cc" #endif /* __AKANTU_SPARSE_MATRIX_AIJ_HH__ */ diff --git a/src/solver/sparse_matrix_aij_inline_impl.cc b/src/solver/sparse_matrix_aij_inline_impl.cc index 963027f4e..518a36610 100644 --- a/src/solver/sparse_matrix_aij_inline_impl.cc +++ b/src/solver/sparse_matrix_aij_inline_impl.cc @@ -1,95 +1,102 @@ /** * @file sparse_matrix_aij_inline_impl.cc * * @author Nicolas Richart * * @date Tue Aug 18 00:42:45 2015 * * @brief Implementation of inline functions of SparseMatrixAIJ * * @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 . * */ /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ inline UInt SparseMatrixAIJ::addToProfile(UInt i, UInt j) { KeyCOO jcn_irn = this->key(i, j); coordinate_list_map::iterator it = this->irn_jcn_k.find(jcn_irn); if (!(it == this->irn_jcn_k.end())) return it->second; this->irn.push_back(i + 1); this->jcn.push_back(j + 1); this->a.push_back(0.); this->irn_jcn_k[jcn_irn] = this->nb_non_zero; (this->nb_non_zero)++; + this->profile_release++; + return (this->nb_non_zero - 1); } /* -------------------------------------------------------------------------- */ inline void SparseMatrixAIJ::clearProfile() { SparseMatrix::clearProfile(); this->irn_jcn_k.clear(); this->irn.resize(0); this->jcn.resize(0); this->a.resize(0); + + this->profile_release++; } /* -------------------------------------------------------------------------- */ inline void SparseMatrixAIJ::addToMatrix(UInt i, UInt j, Real value) { KeyCOO jcn_irn = this->key(i, j); coordinate_list_map::iterator irn_jcn_k_it = this->irn_jcn_k.find(jcn_irn); AKANTU_DEBUG_ASSERT(irn_jcn_k_it != this->irn_jcn_k.end(), "Couple (i,j) = (" << i << "," << j << ") does not exist in the profile"); this->a(irn_jcn_k_it->second) += value; + this->value_release++; } /* -------------------------------------------------------------------------- */ inline Real SparseMatrixAIJ::operator()(UInt i, UInt j) const { KeyCOO jcn_irn = this->key(i, j); coordinate_list_map::const_iterator irn_jcn_k_it = this->irn_jcn_k.find(jcn_irn); if (irn_jcn_k_it == this->irn_jcn_k.end()) return 0.; return this->a(irn_jcn_k_it->second); } /* -------------------------------------------------------------------------- */ inline Real & SparseMatrixAIJ::operator()(UInt i, UInt j) { KeyCOO jcn_irn = this->key(i, j); coordinate_list_map::iterator irn_jcn_k_it = this->irn_jcn_k.find(jcn_irn); AKANTU_DEBUG_ASSERT(irn_jcn_k_it != this->irn_jcn_k.end(), "Couple (i,j) = (" << i << "," << j << ") does not exist in the profile"); + this->value_release++; + return this->a(irn_jcn_k_it->second); } __END_AKANTU__ diff --git a/src/solver/sparse_matrix_petsc.cc b/src/solver/sparse_matrix_petsc.cc index a8d6d4e40..e6705e7c8 100644 --- a/src/solver/sparse_matrix_petsc.cc +++ b/src/solver/sparse_matrix_petsc.cc @@ -1,406 +1,404 @@ /** * @file petsc_matrix.cc * @author Aurelia Cuba Ramos * @date Mon Jul 21 17:40:41 2014 * * @brief Implementation of PETSc matrix 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 "sparse_matrix_petsc.hh" #include "mpi_type_wrapper.hh" #include "dof_manager_petsc.hh" -#include "petsc_wrapper.hh" +#include "static_communicator.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ #if not defined(PETSC_CLANGUAGE_CXX) int aka_PETScError(int ierr) { CHKERRQ(ierr); return 0; } #endif /* -------------------------------------------------------------------------- */ SparseMatrixPETSc::SparseMatrixPETSc(DOFManagerPETSc & dof_manager, const MatrixType & sparse_matrix_type, const ID & id, const MemoryID & memory_id) : SparseMatrix(dof_manager, matrix_type, id, memory_id), dof_manager(dof_manager), d_nnz(0, 1, "dnnz"), o_nnz(0, 1, "onnz"), first_global_index(0) { AKANTU_DEBUG_IN(); PetscErrorCode ierr; // create the PETSc matrix object ierr = MatCreate(PETSC_COMM_WORLD, &this->mat); CHKERRXX(ierr); /** * Set the matrix type * @todo PETSc does currently not support a straightforward way to * apply Dirichlet boundary conditions for MPISBAIJ * matrices. Therefore always the entire matrix is allocated. It * would be possible to use MATSBAIJ for sequential matrices in case * memory becomes critical. Also, block matrices would give a much * better performance. Modify this in the future! */ ierr = MatSetType(this->mat, MATAIJ); CHKERRXX(ierr); - this->offset = 0; - AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseMatrixPETSc::~SparseMatrixPETSc() { AKANTU_DEBUG_IN(); /// destroy all the PETSc data structures used for this matrix PetscErrorCode ierr; ierr = MatDestroy(&this->mat); CHKERRXX(ierr); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * With this method each processor computes the dimensions of the * local matrix, i.e. the part of the global matrix it is storing. * @param dof_synchronizer dof synchronizer that maps the local * dofs to the global dofs and the equation numbers, i.e., the * position at which the dof is assembled in the matrix */ void SparseMatrixPETSc::setSize() { AKANTU_DEBUG_IN(); // PetscErrorCode ierr; /// find the number of dofs corresponding to master or local nodes UInt nb_dofs = this->dof_manager.getLocalSystemSize(); // UInt nb_local_master_dofs = 0; /// create array to store the global equation number of all local and master /// dofs Array local_master_eq_nbs(nb_dofs); Array::scalar_iterator it_eq_nb = local_master_eq_nbs.begin(); throw; /// get the pointer to the global equation number array // Int * eq_nb_val = // this->dof_synchronizer->getGlobalDOFEquationNumbers().storage(); // for (UInt i = 0; i < nb_dofs; ++i) { // if (this->dof_synchronizer->isLocalOrMasterDOF(i)) { // *it_eq_nb = eq_nb_val[i]; // ++it_eq_nb; // ++nb_local_master_dofs; // } // } // local_master_eq_nbs.resize(nb_local_master_dofs); // /// set the local size // this->local_size = nb_local_master_dofs; // /// resize PETSc matrix // #if defined(AKANTU_USE_MPI) // ierr = MatSetSizes(this->petsc_matrix_wrapper->mat, this->local_size, // this->local_size, this->size, this->size); // CHKERRXX(ierr); // #else // ierr = MatSetSizes(this->petsc_matrix_wrapper->mat, this->local_size, // this->local_size); // CHKERRXX(ierr); // #endif // /// create mapping from akantu global numbering to petsc global numbering // this->createGlobalAkantuToPETScMap(local_master_eq_nbs.storage()); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * This method generates a mapping from the global Akantu equation * numbering to the global PETSc dof ordering * @param local_master_eq_nbs_ptr Int pointer to the array of equation * numbers of all local or master dofs, i.e. the row indices of the * local matrix */ void SparseMatrixPETSc::createGlobalAkantuToPETScMap(Int * local_master_eq_nbs_ptr) { AKANTU_DEBUG_IN(); PetscErrorCode ierr; StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); UInt rank = comm.whoAmI(); // initialize vector to store the number of local and master nodes that are // assigned to each processor Vector master_local_ndofs_per_proc(nb_proc); /// store the nb of master and local dofs on each processor master_local_ndofs_per_proc(rank) = this->local_size; /// exchange the information among all processors comm.allGather(master_local_ndofs_per_proc.storage(), 1); /// each processor creates a map for his akantu global dofs to the /// corresponding petsc global dofs /// determine the PETSc-index for the first dof on each processor for (UInt i = 0; i < rank; ++i) { this->first_global_index += master_local_ndofs_per_proc(i); } /// create array for petsc ordering Array petsc_dofs(this->local_size); Array::scalar_iterator it_petsc_dofs = petsc_dofs.begin(); for (Int i = this->first_global_index; i < this->first_global_index + this->local_size; ++i, ++it_petsc_dofs) { *it_petsc_dofs = i; } ierr = AOCreateBasic(PETSC_COMM_WORLD, this->local_size, local_master_eq_nbs_ptr, petsc_dofs.storage(), &(this->ao)); CHKERRXX(ierr); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Method to save the nonzero pattern and the values stored at each position * @param filename name of the file in which the information will be stored */ void SparseMatrixPETSc::saveMatrix(const std::string & filename) const { AKANTU_DEBUG_IN(); PetscErrorCode ierr; /// create Petsc viewer PetscViewer viewer; ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD, filename.c_str(), &viewer); CHKERRXX(ierr); /// set the format PetscViewerSetFormat(viewer, PETSC_VIEWER_DEFAULT); CHKERRXX(ierr); /// save the matrix /// @todo Write should be done in serial -> might cause problems ierr = MatView(this->mat, viewer); CHKERRXX(ierr); /// destroy the viewer ierr = PetscViewerDestroy(&viewer); CHKERRXX(ierr); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Method to add an Akantu sparse matrix to the PETSc matrix * @param matrix Akantu sparse matrix to be added * @param alpha the factor specifying how many times the matrix should be added */ // void SparseMatrixPETSc::add(const SparseMatrix & matrix, Real alpha) { // PetscErrorCode ierr; // // AKANTU_DEBUG_ASSERT(nb_non_zero == matrix.getNbNonZero(), // // "The two matrix don't have the same profiles"); // Real val_to_add = 0; // Array index(2); // for (UInt n = 0; n < matrix.getNbNonZero(); ++n) { // UInt mat_to_add_offset = matrix.getOffset(); // index(0) = matrix.getIRN()(n) - mat_to_add_offset; // index(1) = matrix.getJCN()(n) - mat_to_add_offset; // AOApplicationToPetsc(this->petsc_matrix_wrapper->ao, 2, index.storage()); // if (this->sparse_matrix_type == _symmetric && index(0) > index(1)) // std::swap(index(0), index(1)); // val_to_add = matrix.getA()(n) * alpha; // /// MatSetValue might be very slow for MATBAIJ, might need to use // /// MatSetValuesBlocked // ierr = MatSetValue(this->petsc_matrix_wrapper->mat, index(0), index(1), // val_to_add, ADD_VALUES); // CHKERRXX(ierr); // /// chek if sparse matrix to be added is symmetric. In this case // /// the value also needs to be added at the transposed location in // /// the matrix because PETSc is using the full profile, also for symmetric // /// matrices // if (matrix.getSparseMatrixType() == _symmetric && index(0) != index(1)) // ierr = MatSetValue(this->petsc_matrix_wrapper->mat, index(1), index(0), // val_to_add, ADD_VALUES); // CHKERRXX(ierr); // } // this->performAssembly(); // } /* -------------------------------------------------------------------------- */ /** * Method to add another PETSc matrix to this PETSc matrix * @param matrix PETSc matrix to be added * @param alpha the factor specifying how many times the matrix should be added */ void SparseMatrixPETSc::add(const SparseMatrixPETSc & matrix, Real alpha) { PetscErrorCode ierr; ierr = MatAXPY(this->mat, alpha, matrix.mat, SAME_NONZERO_PATTERN); CHKERRXX(ierr); this->performAssembly(); } /* -------------------------------------------------------------------------- */ /** * MatSetValues() generally caches the values. The matrix is ready to * use only after MatAssemblyBegin() and MatAssemblyEnd() have been * called. (http://www.mcs.anl.gov/petsc/) */ void SparseMatrixPETSc::performAssembly() { this->beginAssembly(); this->endAssembly(); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::beginAssembly() { PetscErrorCode ierr; ierr = MatAssemblyBegin(this->mat, MAT_FINAL_ASSEMBLY); CHKERRXX(ierr); ierr = MatAssemblyEnd(this->mat, MAT_FINAL_ASSEMBLY); CHKERRXX(ierr); } /* -------------------------------------------------------------------------- */ void SparseMatrixPETSc::endAssembly() { PetscErrorCode ierr; ierr = MatAssemblyEnd(this->mat, MAT_FINAL_ASSEMBLY); CHKERRXX(ierr); } /* -------------------------------------------------------------------------- */ /// access K(i, j). Works only for dofs on this processor!!!! Real SparseMatrixPETSc::operator()(UInt i, UInt j) const { AKANTU_DEBUG_IN(); // AKANTU_DEBUG_ASSERT(this->dof_synchronizer->isLocalOrMasterDOF(i) && // this->dof_synchronizer->isLocalOrMasterDOF(j), // "Operator works only for dofs on this processor"); // Array index(2, 1); // index(0) = this->dof_synchronizer->getDOFGlobalID(i); // index(1) = this->dof_synchronizer->getDOFGlobalID(j); // AOApplicationToPetsc(this->petsc_matrix_wrapper->ao, 2, index.storage()); // Real value = 0; // PetscErrorCode ierr; // /// @todo MatGetValue might be very slow for MATBAIJ, might need to use // /// MatGetValuesBlocked // ierr = MatGetValues(this->petsc_matrix_wrapper->mat, 1, &index(0), 1, // &index(1), &value); // CHKERRXX(ierr); // AKANTU_DEBUG_OUT(); // return value; return 0.; } /* -------------------------------------------------------------------------- */ /** * Apply Dirichlet boundary conditions by zeroing the rows and columns which * correspond to blocked dofs * @param boundary array of booleans which are true if the dof at this position * is blocked * @param block_val the value in the diagonal entry of blocked rows */ void SparseMatrixPETSc::applyBoundary(const Array & boundary, Real block_val) { AKANTU_DEBUG_IN(); // PetscErrorCode ierr; // /// get the global equation numbers to find the rows that need to be zeroed // /// for the blocked dofs // Int * eq_nb_val = dof_synchronizer->getGlobalDOFEquationNumbers().storage(); // /// every processor calls the MatSetZero() only for his local or master dofs. // /// This assures that not two processors or more try to zero the same row // UInt nb_component = boundary.getNbComponent(); // UInt size = boundary.getSize(); // Int nb_blocked_local_master_eq_nb = 0; // Array blocked_local_master_eq_nb(this->local_size); // Int * blocked_lm_eq_nb_ptr = blocked_local_master_eq_nb.storage(); // for (UInt i = 0; i < size; ++i) { // for (UInt j = 0; j < nb_component; ++j) { // UInt local_dof = i * nb_component + j; // if (boundary(i, j) == true && // this->dof_synchronizer->isLocalOrMasterDOF(local_dof)) { // Int global_eq_nb = *eq_nb_val; // *blocked_lm_eq_nb_ptr = global_eq_nb; // ++nb_blocked_local_master_eq_nb; // ++blocked_lm_eq_nb_ptr; // } // ++eq_nb_val; // } // } // blocked_local_master_eq_nb.resize(nb_blocked_local_master_eq_nb); // ierr = AOApplicationToPetsc(this->petsc_matrix_wrapper->ao, // nb_blocked_local_master_eq_nb, // blocked_local_master_eq_nb.storage()); // CHKERRXX(ierr); // ierr = MatZeroRowsColumns( // this->petsc_matrix_wrapper->mat, nb_blocked_local_master_eq_nb, // blocked_local_master_eq_nb.storage(), block_val, 0, 0); // CHKERRXX(ierr); // this->performAssembly(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /// set all entries to zero while keeping the same nonzero pattern void SparseMatrixPETSc::clear() { MatZeroEntries(this->mat); } __END_AKANTU__ diff --git a/src/solver/sparse_matrix_petsc.hh b/src/solver/sparse_matrix_petsc.hh index d15bae4e7..7ec7eaede 100644 --- a/src/solver/sparse_matrix_petsc.hh +++ b/src/solver/sparse_matrix_petsc.hh @@ -1,139 +1,138 @@ /** * @file petsc_matrix.hh * @author Aurelia Cuba Ramos * @date Mon Jul 21 14:49:49 2014 * * @brief Interface for PETSc matrices * * @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_PETSC_MATRIX_HH__ #define __AKANTU_PETSC_MATRIX_HH__ /* -------------------------------------------------------------------------- */ #include "sparse_matrix.hh" -#include "static_solver.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ namespace akantu { class DOFManagerPETSc; } __BEGIN_AKANTU__ class SparseMatrixPETSc : public SparseMatrix { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SparseMatrixPETSc(DOFManagerPETSc & dof_manager, const MatrixType & matrix_type, const ID & id = "sparse_matrix", const MemoryID & memory_id = 0); SparseMatrixPETSc(const SparseMatrix & matrix, const ID & id = "sparse_matrix_petsc", const MemoryID & memory_id = 0); virtual ~SparseMatrixPETSc(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// set the matrix to 0 virtual void clear(); /// modify the matrix to "remove" the blocked dof virtual void applyBoundary(const Array & boundary, Real block_val = 1.); /// save the matrix in a ASCII file format virtual void saveMatrix(const std::string & filename) const; /// add a sparse matrix assuming the profile are the same virtual void add(const SparseMatrix & matrix, Real alpha); /// add a petsc matrix assuming the profile are the same virtual void add(const SparseMatrixPETSc & matrix, Real alpha); Real operator()(UInt i, UInt j) const; protected: typedef std::pair KeyCOO; inline KeyCOO key(UInt i, UInt j) const { return std::make_pair(i, j); } private: virtual void destroyInternalData(); /// set the size of the PETSc matrix void setSize(); void createGlobalAkantuToPETScMap(Int * local_master_eq_nbs_ptr); void createLocalAkantuToPETScMap(); /// start to assemble the matrix void beginAssembly(); /// finishes to assemble the matrix void endAssembly(); /// perform the assembly stuff from petsc void performAssembly(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(PETScMat, mat, const Mat &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: // DOFManagerPETSc that contains the numbering for petsc DOFManagerPETSc & dof_manager; /// store the PETSc matrix Mat mat; AO ao; /// size of the diagonal part of the matrix partition Int local_size; /// number of nonzeros in every row of the diagonal part Array d_nnz; /// number of nonzeros in every row of the off-diagonal part Array o_nnz; /// the global index of the first local row Int first_global_index; /// bool to indicate if the matrix data has been initialized by calling /// MatCreate bool is_petsc_matrix_initialized; }; __END_AKANTU__ #endif /* __AKANTU_PETSC_MATRIX_HH__ */ diff --git a/src/solver/sparse_solver.cc b/src/solver/sparse_solver.cc index 6e6dca31f..138bc7787 100644 --- a/src/solver/sparse_solver.cc +++ b/src/solver/sparse_solver.cc @@ -1,84 +1,81 @@ /** * @file solver.cc * * @author Nicolas Richart * * @date creation: Mon Dec 13 2010 * @date last modification: Wed Nov 13 2013 * * @brief Solver interface class * * @section LICENSE * * Copyright (©) 2010-2012, 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 "sparse_solver.hh" #include "dof_synchronizer.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ SparseSolver::SparseSolver(DOFManager & dof_manager, const ID & matrix_id, const ID & id, const MemoryID & memory_id) - : Memory(id, memory_id), Parsable(_st_solver, id), StaticSolverEventHandler(), + : Memory(id, memory_id), Parsable(_st_solver, id), _dof_manager(dof_manager), matrix_id(matrix_id) { AKANTU_DEBUG_IN(); - StaticSolver::getStaticSolver().registerEventHandler(*this); - // createSynchronizerRegistry(); // this->synch_registry = new SynchronizerRegistry(*this); // synch_registry->registerSynchronizer(this->matrix->getDOFSynchronizer(), // _gst_solver_solution); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseSolver::~SparseSolver() { AKANTU_DEBUG_IN(); this->destroyInternalData(); // delete synch_registry; - StaticSolver::getStaticSolver().unregisterEventHandler(*this); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolver::beforeStaticSolverDestroy() { AKANTU_DEBUG_IN(); try { this->destroyInternalData(); } catch (...) { } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseSolver::createSynchronizerRegistry() { // this->synch_registry = new SynchronizerRegistry(this); } __END_AKANTU__ diff --git a/src/solver/sparse_solver.hh b/src/solver/sparse_solver.hh index 53f16bde0..5078db203 100644 --- a/src/solver/sparse_solver.hh +++ b/src/solver/sparse_solver.hh @@ -1,119 +1,116 @@ /** * @file sparse_solver.hh * * @author Nicolas Richart * @author Aurelia Cuba Ramos * * @date creation: Mon Dec 13 2010 * @date last modification: Mon Sep 15 2014 * * @brief interface for solvers * * @section LICENSE * * Copyright (©) 2010-2012, 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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLVER_HH__ #define __AKANTU_SOLVER_HH__ /* -------------------------------------------------------------------------- */ -#include "static_solver.hh" #include "data_accessor.hh" #include "parsable.hh" - /* -------------------------------------------------------------------------- */ enum SolverParallelMethod { _not_parallel, _fully_distributed, _master_slave_distributed }; namespace akantu { class DOFManager; } __BEGIN_AKANTU__ class SparseSolver : protected Memory, public Parsable, - public StaticSolverEventHandler, public DataAccessor { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SparseSolver(DOFManager & dof_manager, const ID & matrix_id, const ID & id = "solver", const MemoryID & memory_id = 0); virtual ~SparseSolver(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the solver virtual void initialize() = 0; virtual void analysis(){}; virtual void factorize(){}; virtual void solve(){}; protected: virtual void destroyInternalData(){}; public: virtual void beforeStaticSolverDestroy(); void createSynchronizerRegistry(); /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ public: // inline virtual UInt getNbDataForDOFs(const Array & dofs, // SynchronizationTag tag) const; // inline virtual void packDOFData(CommunicationBuffer & buffer, // const Array & dofs, // SynchronizationTag tag) const; // inline virtual void unpackDOFData(CommunicationBuffer & buffer, // const Array & dofs, // SynchronizationTag tag); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// manager handling the dofs for this SparseMatrix solver DOFManager & _dof_manager; /// The id of the associated matrix ID matrix_id; /// How to parallelize the solve SolverParallelMethod parallel_method; }; __END_AKANTU__ #endif /* __AKANTU_SOLVER_HH__ */ diff --git a/src/solver/static_solver.hh b/src/solver/static_solver.hh deleted file mode 100644 index 73923f221..000000000 --- a/src/solver/static_solver.hh +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file static_solver.hh - * @author Aurelia Cuba Ramos - * @date Wed Jul 30 14:44:12 2014 - * - * @brief Class handeling the initialization of external solvers - * - * @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 "static_communicator.hh" - - -#ifndef __AKANTU_STATIC_SOLVER_HH__ -#define __AKANTU_STATIC_SOLVER_HH__ - -__BEGIN_AKANTU__ - -namespace StaticSolverEvent { - struct BeforeStaticSolverDestroyEvent { - BeforeStaticSolverDestroyEvent() {} - }; -} - -class StaticSolverEventHandler { - /* ------------------------------------------------------------------------ */ - /* Constructors/Destructors */ - /* ------------------------------------------------------------------------ */ -public: - virtual ~StaticSolverEventHandler() {}; - - /* ------------------------------------------------------------------------ */ - /* Methods */ - /* ------------------------------------------------------------------------ */ -protected: - inline void sendEvent(const StaticSolverEvent::BeforeStaticSolverDestroyEvent & event) { - this->beforeStaticSolverDestroy(); - } - - template friend class EventHandlerManager; - - /* ------------------------------------------------------------------------ */ - /* Interface */ - /* ------------------------------------------------------------------------ */ -public: - virtual void beforeStaticSolverDestroy() {} -}; - - - -class StaticSolver : public CommunicatorEventHandler, - public EventHandlerManager { - typedef EventHandlerManager ParentEventHandler; - /* ------------------------------------------------------------------------ */ - /* Constructors */ - /* ------------------------------------------------------------------------ */ -private: - StaticSolver(); - -public: - ~StaticSolver(); - - /* ------------------------------------------------------------------------ */ - /// get an instance to the static solver - static StaticSolver & getStaticSolver(); - - /* ------------------------------------------------------------------------ */ - /* Methods */ - /* ------------------------------------------------------------------------ */ -public: - /// initialize what is needed for the compiled solver interfaces - void initialize(int & argc, char ** & argv); - - /// finalize what is needed for the compiled solver interfaces - void finalize(); - - /* ------------------------------------------------------------------------ */ - /* Members */ - /* ------------------------------------------------------------------------ */ -private: - bool is_initialized; - static UInt nb_references; - static StaticSolver * static_solver; -}; - -__END_AKANTU__ - - -#endif /* __AKANTU_STATIC_SOLVER_HH__ */