diff --git a/CMakeLists.txt b/CMakeLists.txt index f4d8f8e0c..747fcf9df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,319 +1,318 @@ #=============================================================================== # @file CMakeLists.txt # @author Nicolas Richart # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== #=============================================================================== # _ ,-, _ # ,--, /: :\/': :`\/: :\ # |`; ' `,' `.; `: | _ _ # | | | ' | |. | | | | # | : | F E | A S | T++ || __ _| | ____ _ _ __ | |_ _ _ # | :. | : | : | : | \ / _` | |/ / _` | '_ \| __| | | | # \__/: :.. : :.. | :.. | ) | (_| | < (_| | | | | |_| |_| | # `---',\___/,\___/ /' \__,_|_|\_\__,_|_| |_|\__|\__,_| # `==._ .. . /' # `-::-' #=============================================================================== #=============================================================================== # CMake Project #=============================================================================== cmake_minimum_required(VERSION 2.6) project(akantu) enable_language(CXX) #=============================================================================== # Misc. #=============================================================================== set(AKANTU_CMAKE_DIR "${CMAKE_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries.") include(${AKANTU_CMAKE_DIR}/AkantuMacros.cmake) #=============================================================================== # Version Number #=============================================================================== # AKANTU version number. An even minor number corresponds to releases. set(AKANTU_MAJOR_VERSION 0) set(AKANTU_MINOR_VERSION 1) set(AKANTU_PATCH_VERSION 0) find_package(Subversion) if (EXISTS ${CMAKE_SOURCE_DIR}/.svn) if(SUBVERSION_FOUND) subversion_wc_info(${CMAKE_SOURCE_DIR} MY) set(AKANTU_BUILD_VERSION ${MY_WC_REVISION}) set(AKANTU_VERSION "${AKANTU_MAJOR_VERSION}.${AKANTU_MINOR_VERSION}.${AKANTU_PATCH_VERSION}.${AKANTU_BUILD_VERSION}" ) file(WRITE VERSION "${AKANTU_VERSION}\n") else(SUBVERSION_FOUND) message("SVN control files were found but no subversion executable is present... ") set(AKANTU_VERSION 0) endif(SUBVERSION_FOUND) else(EXISTS ${CMAKE_SOURCE_DIR}/.svn) if(EXISTS ${CMAKE_SOURCE_DIR}/VERSION) file(STRINGS VERSION AKANTU_VERSION) else(EXISTS ${CMAKE_SOURCE_DIR}/VERSION) message("No SVN control file neither VERSION file could be found. How was this release made ?") endif(EXISTS ${CMAKE_SOURCE_DIR}/VERSION) endif(EXISTS ${CMAKE_SOURCE_DIR}/.svn) # Append the library version information to the library target properties if(NOT AKANTU_NO_LIBRARY_VERSION) set(AKANTU_LIBRARY_PROPERTIES ${AKANTU_LIBRARY_PROPERTIES} VERSION "${AKANTU_VERSION}" SOVERSION "${AKANTU_MAJOR_VERSION}.${AKANTU_MINOR_VERSION}" ) endif(NOT AKANTU_NO_LIBRARY_VERSION) #=============================================================================== # Options #=============================================================================== option(AKANTU_DEBUG "Compiles akantu with the debug messages" ON) option(AKANTU_DOCUMENTATION "Build source documentation using Doxygen." OFF) # features add_optional_package(BLAS "Use BLAS for arithmetic operations" OFF) if(BLAS_mkl_core_LIBRARY) set(AKANTU_USE_BLAS_MKL) endif() add_optional_package(LAPACK "Use LAPACK for arithmetic operations" OFF) # Debug if(NOT AKANTU_DEBUG) if(NOT CMAKE_CXX_FLAGS MATCHES "-Wno-return-type") set(CMAKE_CXX_FLAGS "-Wno-return-type ${CMAKE_CXX_FLAGS}" CACHE STRING "Flags used by the compiler during all build types." FORCE) endif() set(AKANTU_NDEBUG ON) else() string(REPLACE "-Wno-return-type " "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - message("TOTO ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "Flags used by the compiler during all build types." FORCE) endif(NOT AKANTU_DEBUG) if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall") set(CMAKE_CXX_FLAGS "-Wall ${CMAKE_CXX_FLAGS}" CACHE STRING "Flags used by the compiler during all build types." FORCE) endif() set(CMAKE_CXX_FLAGS_PROFILING "-g -pg" CACHE STRING "Flags used by the compiler during profiling builds") set(CMAKE_EXE_LINKER_FLAGS_PROFILING "-pg" CACHE STRING "Flags used by the linker during profiling builds") set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-pg" CACHE STRING "Flags used by the linker during profiling builds") mark_as_advanced(CMAKE_CXX_FLAGS_PROFILING) mark_as_advanced(CMAKE_EXE_LINKER_FLAGS_PROFILING) mark_as_advanced(CMAKE_SHARED_LINKER_FLAGS_PROFILING) #=============================================================================== # Dependencies #=============================================================================== find_package(Boost REQUIRED) if(Boost_FOUND) include_directories(${Boost_INCLUDE_DIRS}) endif() add_all_packages(${CMAKE_SOURCE_DIR}/packages) if(AKANTU_SCOTCH) set(AKANTU_PARTITIONER ON) else() set(AKANTU_PARTITIONER OFF) endif() if(AKANTU_MUMPS) set(AKANTU_SOLVER ON) else() set(AKANTU_SOLVER OFF) endif() #add_akantu_definitions() #=============================================================================== add_subdirectory(src) #=============================================================================== # Documentation #=============================================================================== if(AKANTU_DOCUMENTATION) find_package(Doxygen REQUIRED) if(DOXYGEN_FOUND) set(DOXYGEN_WARNINGS NO) set(DOXYGEN_QUIET YES) if(CMAKE_VERBOSE_MAKEFILE) set(DOXYGEN_WARNINGS YES) set(DOXYGEN_QUIET NO) endif(CMAKE_VERBOSE_MAKEFILE) add_subdirectory(doc/doxygen) endif(DOXYGEN_FOUND) endif(AKANTU_DOCUMENTATION) #=============================================================================== # Tests #=============================================================================== ENABLE_TESTING() INCLUDE(CTest) INCLUDE(${AKANTU_CMAKE_DIR}/AkantuTestAndExamples.cmake) option(AKANTU_TESTS "Activate tests" OFF) if(AKANTU_TESTS) include_directories( ${AKANTU_INCLUDE_DIRS} ${AKANTU_EXTERNAL_LIB_INCLUDE_DIR} ) find_package(GMSH REQUIRED) add_subdirectory(test) endif(AKANTU_TESTS) #=============================================================================== # Config gen for external packages #=============================================================================== export(TARGETS akantu FILE "${CMAKE_BINARY_DIR}/AkantuLibraryDepends.cmake") export(PACKAGE Akantu) configure_file(cmake/AkantuBuildTreeSettings.cmake.in "${CMAKE_BINARY_DIR}/AkantuBuildTreeSettings.cmake" @ONLY) file(WRITE "${CMAKE_BINARY_DIR}/AkantuConfigInclude.cmake" " #=============================================================================== # @file AkantuConfigInclude.cmake # @author Nicolas Richart # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== ") foreach(_option ${AKANTU_PACKAGE_NAMES_LIST_ALL}) list(FIND AKANTU_OPTION_LIST ${_option} _index) if (_index EQUAL -1) if(NOT "${_option}" STREQUAL "CORE") if(NOT AKANTU_${_option}) set(AKANTU_${_option} OFF) endif() file(APPEND "${CMAKE_BINARY_DIR}/AkantuConfigInclude.cmake" " set(AKANTU_HAS_${_option} ${AKANTU_${_option}})") endif() endif() endforeach() file(APPEND "${CMAKE_BINARY_DIR}/AkantuConfigInclude.cmake" " set(AKANTU_HAS_PARTITIONER ${AKANTU_PARTITIONER}) set(AKANTU_HAS_SOLVER ${AKANTU_SOLVER}) set(AKANTU_OPTION_LIST ${AKANTU_OPTION_LIST}) ") foreach(_option ${AKANTU_OPTION_LIST}) file(APPEND "${CMAKE_BINARY_DIR}/AkantuConfigInclude.cmake" " set(AKANTU_USE_${_option} ${AKANTU_${_option}}) set(AKANTU_${_option}_LIBRARIES ${AKANTU_${_option}_LIBRARIES}) set(AKANTU_${_option}_INCLUDE_DIR ${AKANTU_${_option}_INCLUDE_DIR}) ") endforeach() # Create the AkantuConfig.cmake and AkantuConfigVersion files get_filename_component(CONF_REL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}" ABSOLUTE) configure_file(cmake/AkantuConfig.cmake.in "${CMAKE_BINARY_DIR}/AkantuConfig.cmake" @ONLY) configure_file(cmake/AkantuConfigVersion.cmake.in "${CMAKE_BINARY_DIR}/AkantuConfigVersion.cmake" @ONLY) configure_file(cmake/AkantuUse.cmake "${CMAKE_BINARY_DIR}/AkantuUse.cmake" COPYONLY) # Install the export set for use with the install-tree install(EXPORT AkantuLibraryDepends DESTINATION lib/akantu COMPONENT dev) install(FILES ${CMAKE_BINARY_DIR}/AkantuConfig.cmake ${CMAKE_BINARY_DIR}/AkantuConfigInclude.cmake ${CMAKE_BINARY_DIR}/AkantuConfigVersion.cmake ${CMAKE_SOURCE_DIR}/cmake/AkantuUse.cmake DESTINATION lib/akantu COMPONENT dev) install(FILES ${CMAKE_SOURCE_DIR}/cmake/FindIOHelper.cmake ${CMAKE_SOURCE_DIR}/cmake/FindQVIEW.cmake ${CMAKE_SOURCE_DIR}/cmake/FindMumps.cmake ${CMAKE_SOURCE_DIR}/cmake/FindScotch.cmake ${CMAKE_SOURCE_DIR}/cmake/FindGMSH.cmake DESTINATION lib/akantu/cmake COMPONENT dev) #=============================================================================== # Package builder target module of CPack #=============================================================================== set(CPACK_GENERATOR "DEB;TGZ;TBZ2;STGZ") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "guillaume.anciaux@epfl.ch, nicolas.richart@epfl.ch") #message(${CPACK_DEBIAN_PACKAGE_DEPENDS}) if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64" CACHE STRING "Architecture of debian package generation") else() set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386" CACHE STRING "Architecture of debian package generation") endif() #message("CPACK_DEBIAN_PACKAGE_ARCHITECTURE = ${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "Akantu library") set(CPACK_PACKAGE_VENDOR "LSMS") set(PACKAGE_FILE_NAME "akantu" CACHE STRING "Name of package to be generated") set(CPACK_PACKAGE_FILE_NAME "${PACKAGE_FILE_NAME}-${AKANTU_VERSION}-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PACKAGE_FILE_NAME}-${AKANTU_VERSION}-src") set(CPACK_PACKAGE_VERSION "${AKANTU_VERSION}") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") list(APPEND CPACK_SOURCE_IGNORE_FILES ${AKANTU_EXCLUDE_SOURCE_FILE}) list(APPEND CPACK_SOURCE_IGNORE_FILES ${AKANTU_UNACTIVATED_PACKAGE_FILE}) list(APPEND CPACK_SOURCE_IGNORE_FILES "/.*build.*/;/CVS/;/\\\\.svn/;/\\\\.bzr/;/\\\\.hg/;/\\\\.git/;\\\\.swp$;\\\\.#;/#;~") include(CPack) diff --git a/doc/doxygen/CMakeLists.txt b/doc/doxygen/CMakeLists.txt index b41dc7227..f2dcfd861 100644 --- a/doc/doxygen/CMakeLists.txt +++ b/doc/doxygen/CMakeLists.txt @@ -1,54 +1,65 @@ #=============================================================================== # @file CMakeLists.txt # @author Nicolas Richart # @date Mon Sep 27 17:35:59 2010 # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== set(DOXYGEN_INPUT ${CMAKE_CURRENT_BINARY_DIR}/akantu.dox) set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/html) set(DOXYGEN_OUTPUT ${DOXYGEN_OUTPUT_DIR}/index.html) string(REGEX REPLACE ":" " " AKANTU_DOXYGEN_DEFINTIONS "${AKANTU_DEFINITIONS}") make_directory(${DOXYGEN_OUTPUT_DIR}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/akantu.dox.cmake ${CMAKE_CURRENT_BINARY_DIR}/akantu.dox) add_custom_command( - OUTPUT ${DOXYGEN_OUTPUT} + OUTPUT ${DOXYGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}/latex/refman.tex COMMAND ${CMAKE_COMMAND} -E echo "${DOXYGEN_EXECUTABLE} ${DOXYGEN_INPUT}" COMMAND ${CMAKE_COMMAND} -E echo_append "Building akantu Documentation..." COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_INPUT} COMMAND ${CMAKE_COMMAND} -E echo "Done." DEPENDS ${DOXYGEN_INPUT} ) +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/refman.pdf + COMMAND ${CMAKE_COMMAND} -E echo "Building akantu RefMan..." + COMMAND make -C ${CMAKE_CURRENT_BINARY_DIR}/latex + COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_BINARY_DIR}/latex/refman.pdf ${CMAKE_CURRENT_BINARY_DIR}/refman.pdf + COMMAND ${CMAKE_COMMAND} -E echo "Done." + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/latex/refman.tex +) + +add_custom_target(akantu-doc-pdf ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/refman.pdf) + add_custom_target(akantu-doc ALL DEPENDS ${DOXYGEN_OUTPUT}) add_custom_target(akantu-doc-forced COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_INPUT} ) install(DIRECTORY ${DOXYGEN_OUTPUT_DIR} DESTINATION share/akantu-${akantu_VERSION}/doc) diff --git a/src/common/aka_common.hh b/src/common/aka_common.hh index 2826e5e90..11feec775 100644 --- a/src/common/aka_common.hh +++ b/src/common/aka_common.hh @@ -1,412 +1,439 @@ /** * @file aka_common.hh * @author Nicolas Richart * @date Fri Jun 11 09:48:06 2010 * * @namespace akantu * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * * @section DESCRIPTION * * All common things to be included in the projects files * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COMMON_HH__ #define __AKANTU_COMMON_HH__ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #define __BEGIN_AKANTU__ namespace akantu { #define __END_AKANTU__ } /* -------------------------------------------------------------------------- */ #include "aka_config.hh" #include "aka_error.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Common types */ /* -------------------------------------------------------------------------- */ typedef double Real; typedef unsigned int UInt; typedef unsigned long long UInt64; typedef signed int Int; typedef std::string ID; static const Real UINT_INIT_VALUE = 0; #ifdef AKANTU_NDEBUG static const Real REAL_INIT_VALUE = 0; #else static const Real REAL_INIT_VALUE = std::numeric_limits::quiet_NaN(); #endif /* -------------------------------------------------------------------------- */ /* Memory types */ /* -------------------------------------------------------------------------- */ typedef UInt MemoryID; /* -------------------------------------------------------------------------- */ /* Mesh/FEM/Model types */ /* -------------------------------------------------------------------------- */ typedef UInt Surface; typedef std::pair SurfacePair; typedef std::list< SurfacePair > SurfacePairList; /* -------------------------------------------------------------------------- */ /// @boost sequence of element to loop on in global tasks #define AKANTU_REGULAR_ELEMENT_TYPE \ (_not_defined) \ (_segment_2) \ (_segment_3) \ (_triangle_3) \ (_triangle_6) \ (_tetrahedron_4) \ (_tetrahedron_10) \ (_quadrangle_4) \ (_quadrangle_8) \ (_hexahedron_8) \ (_point) \ (_bernoulli_beam_2) #define AKANTU_COHESIVE_ELEMENT_TYPE \ (_cohesive_2d_4) \ (_cohesive_2d_6) #define AKANTU_ALL_ELEMENT_TYPE \ AKANTU_REGULAR_ELEMENT_TYPE AKANTU_COHESIVE_ELEMENT_TYPE /// @enum ElementType type of element potentially contained in a Mesh enum ElementType { _not_defined = 0, _segment_2 = 1, /// first order segment _segment_3 = 2, /// second order segment _triangle_3 = 3, /// first order triangle _triangle_6 = 4, /// second order triangle _tetrahedron_4 = 5, /// first order tetrahedron _tetrahedron_10 = 6, /// second order tetrahedron @remark not implemented yet _quadrangle_4, /// first order quadrangle _quadrangle_8, /// second order quadrangle _hexahedron_8, /// first order hexahedron _point, /// point only for some algorithm to be generic like mesh partitioning _bernoulli_beam_2, /// bernoulli beam 2D _cohesive_2d_4, /// first order 2D cohesive _cohesive_2d_6, /// second order 2D cohesive _max_element_type }; enum ElementKind { _ek_not_defined, _ek_regular, _ek_cohesive }; /// enum AnalysisMethod type of solving method used to solve the equation of motion enum AnalysisMethod { _static, _implicit_dynamic, _explicit_dynamic }; /// 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 }; /// @enum SparseMatrixType type of sparse matrix used enum SparseMatrixType { _unsymmetric, _symmetric }; /* -------------------------------------------------------------------------- */ /* Contact */ /* -------------------------------------------------------------------------- */ typedef ID ContactID; typedef ID ContactSearchID; typedef ID ContactNeighborStructureID; enum ContactType { _ct_not_defined = 0, _ct_2d_expli = 1, _ct_3d_expli = 2, _ct_rigid = 3 }; enum ContactSearchType { _cst_not_defined = 0, _cst_2d_expli = 1, _cst_expli = 2 }; enum ContactNeighborStructureType { _cnst_not_defined = 0, _cnst_regular_grid = 1, _cnst_2d_grid = 2 }; /* -------------------------------------------------------------------------- */ /* Friction */ /* -------------------------------------------------------------------------- */ typedef ID FrictionID; /* -------------------------------------------------------------------------- */ /* Ghosts handling */ /* -------------------------------------------------------------------------- */ typedef ID SynchronizerID; /// @enum CommunicatorType type of communication method to use enum CommunicatorType { _communicator_mpi, _communicator_dummy }; /// @enum SynchronizationTag type of synchronizations enum SynchronizationTag { /// SolidMechanicsModel tags _gst_smm_mass, /// synchronization of the SolidMechanicsModel.mass _gst_smm_for_strain, /// synchronization of the SolidMechanicsModel.current_position _gst_smm_boundary, /// synchronization of the boundary, forces, velocities and displacement _gst_smm_uv, /// synchronization of the nodal velocities and displacement _gst_smm_res, /// synchronization of the nodal residual _gst_smm_init_mat, /// synchronization of the data to initialize materials /// 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 /// Material non local _gst_mnl_damage, /// synchronization of data to average in non local material /// Test tag _gst_test }; /// @enum GhostType type of ghost enum GhostType { _not_ghost, _ghost, _casper // not used but a real cute ghost }; /// @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 +/* -------------------------------------------------------------------------- */ +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_ELEMENT_TYPE_CONST(name, variable, type) \ inline const Vector & \ get##name (const ::akantu::ElementType & el_type, \ const GhostType & ghost_type = _not_ghost) const { \ AKANTU_DEBUG_IN(); \ \ AKANTU_DEBUG_OUT(); \ return variable(el_type, ghost_type); \ } #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE(name, variable, type) \ inline Vector & \ get##name (const ::akantu::ElementType & el_type, \ const GhostType & ghost_type = _not_ghost) { \ AKANTU_DEBUG_IN(); \ \ AKANTU_DEBUG_OUT(); \ return variable(el_type, ghost_type); \ } /* -------------------------------------------------------------------------- */ //! standard output stream operator for ElementType inline std::ostream & operator <<(std::ostream & stream, ElementType type) { switch(type) { case _segment_2 : stream << "segment_2" ; break; case _segment_3 : stream << "segment_3" ; break; case _triangle_3 : stream << "triangle_3" ; break; case _triangle_6 : stream << "triangle_6" ; break; case _tetrahedron_4 : stream << "tetrahedron_4" ; break; case _tetrahedron_10 : stream << "tetrahedron_10"; break; case _quadrangle_4 : stream << "quadrangle_4" ; break; case _quadrangle_8 : stream << "quadrangle_8" ; break; case _hexahedron_8 : stream << "hexahedron_8" ; break; case _bernoulli_beam_2 : stream << "bernoulli_beam_2"; break; case _cohesive_2d_4 : stream << "cohesive_2d_4" ; break; case _cohesive_2d_6 : stream << "cohesive_2d_6" ; break; case _not_defined : stream << "undefined" ; break; case _max_element_type : stream << "ElementType(" << (int) type << ")"; break; case _point : stream << "point"; break; } return stream; } /// standard output stream operator for GhostType inline std::ostream & operator <<(std::ostream & stream, GhostType type) { switch(type) { case _not_ghost : stream << "not_ghost"; break; case _ghost : stream << "ghost" ; break; case _casper : stream << "Casper the friendly ghost"; break; } return stream; } /* -------------------------------------------------------------------------- */ void initialize(int & argc, char ** & argv); /* -------------------------------------------------------------------------- */ void finalize (); /* -------------------------------------------------------------------------- */ /* * For intel compiler annoying remark */ #if defined(__INTEL_COMPILER) /// remark #981: operands are evaluated in unspecified order #pragma warning ( disable : 981 ) /// remark #383: value copied to temporary, reference to temporary used #pragma warning ( disable : 383 ) #endif //defined(__INTEL_COMPILER) /* -------------------------------------------------------------------------- */ /* string manipulation */ /* -------------------------------------------------------------------------- */ inline std::string to_lower(const std::string & str); /* -------------------------------------------------------------------------- */ inline std::string trim(const std::string & to_trim); __END_AKANTU__ #include "aka_common_inline_impl.cc" /* -------------------------------------------------------------------------- */ // BOOST PART: TOUCH ONLY IF YOU KNOW WHAT YOU ARE DOING #include #define AKANTU_EXCLUDE_ELEMENT_TYPE(type) \ AKANTU_DEBUG_ERROR("Type (" << type << ") not handled by this function") #define AKANTU_BOOST_CASE_MACRO(r,macro,type) \ case type : { macro(type); break; } #define AKANTU_BOOST_ELEMENT_SWITCH(macro1, list1, macro2, list2) \ do { \ switch(type) { \ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, macro1, list1) \ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, macro2, list2) \ case _max_element_type: { \ AKANTU_DEBUG_ERROR("Wrong type : " << type); \ break; \ } \ } \ } while(0) #define AKANTU_BOOST_ALL_ELEMENT_SWITCH(macro1) \ do { \ switch(type) { \ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, macro1, AKANTU_ALL_ELEMENT_TYPE) \ case _max_element_type: { \ AKANTU_DEBUG_ERROR("Wrong type : " << type); \ break; \ } \ } \ } while(0) #define AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(macro) \ AKANTU_BOOST_ELEMENT_SWITCH(macro, \ AKANTU_REGULAR_ELEMENT_TYPE, \ AKANTU_EXCLUDE_ELEMENT_TYPE, \ AKANTU_COHESIVE_ELEMENT_TYPE) #define AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(macro) \ AKANTU_BOOST_ELEMENT_SWITCH(macro, \ AKANTU_COHESIVE_ELEMENT_TYPE, \ AKANTU_EXCLUDE_ELEMENT_TYPE, \ AKANTU_REGULAR_ELEMENT_TYPE) #define AKANTU_BOOST_LIST_MACRO(r,macro,type) \ macro(type) #define AKANTU_BOOST_ELEMENT_LIST(macro,list) \ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_LIST_MACRO,macro,list) #define AKANTU_BOOST_ALL_ELEMENT_LIST(macro) \ AKANTU_BOOST_ELEMENT_LIST(macro, AKANTU_ALL_ELEMENT_TYPE) #define AKANTU_BOOST_REGULAR_ELEMENT_LIST(macro) \ AKANTU_BOOST_ELEMENT_LIST(macro, AKANTU_REGULAR_ELEMENT_TYPE) #define AKANTU_BOOST_COHESIVE_ELEMENT_LIST(macro) \ AKANTU_BOOST_ELEMENT_LIST(macro, AKANTU_COHESIVE_ELEMENT_TYPE) #endif /* __AKANTU_COMMON_HH__ */ diff --git a/src/common/aka_math.hh b/src/common/aka_math.hh index e0110c1f4..51434d3af 100644 --- a/src/common/aka_math.hh +++ b/src/common/aka_math.hh @@ -1,249 +1,249 @@ /** * @file aka_math.hh * @author Nicolas Richart * @date Wed Jul 28 11:51:56 2010 * * @brief mathematical operations * * @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_AKA_MATH_H__ #define __AKANTU_AKA_MATH_H__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ -template +template class Vector; class Math { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Matrix algebra */ /* ------------------------------------------------------------------------ */ /// @f$ y = A*x @f$ static void matrix_vector(UInt m, UInt n, - const Vector & A, - const Vector & x, - Vector & y, Real alpha = 1.); + const Vector & A, + const Vector & x, + Vector & y, Real alpha = 1.); /// @f$ y = A*x @f$ static inline void matrix_vector(UInt m, UInt n, const Real * A, const Real * x, Real * y, Real alpha = 1.); /// @f$ y = A^t*x @f$ static inline void matrixt_vector(UInt m, UInt n, const Real * A, const Real * x, Real * y, Real alpha = 1.); /// @f$ C = A*B @f$ static void matrix_matrix(UInt m, UInt n, UInt k, - const Vector & A, - const Vector & B, - Vector & C, Real alpha = 1.); + const Vector & A, + const Vector & B, + Vector & C, Real alpha = 1.); /// @f$ C = A*B^t @f$ static void matrix_matrixt(UInt m, UInt n, UInt k, - const Vector & A, - const Vector & B, - Vector & C, Real alpha = 1.); + const Vector & A, + const Vector & B, + Vector & C, Real alpha = 1.); /// @f$ C = A*B @f$ static inline void matrix_matrix(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C, Real alpha = 1.); /// @f$ C = A^t*B @f$ static inline void matrixt_matrix(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C, Real alpha = 1.); /// @f$ C = A*B^t @f$ static inline void matrix_matrixt(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C, Real alpha = 1.); /// @f$ C = A^t*B^t @f$ static inline void matrixt_matrixt(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C, Real alpha = 1.); template static inline void matMul(UInt m, UInt n, UInt k, Real alpha, const Real * A, const Real * B, Real beta, Real * C); template static inline void matVectMul(UInt m, UInt n, Real alpha, const Real * A, const Real * x, Real beta, Real * y); static inline void matrix33_eigenvalues(Real * A, Real * Adiag); static inline void matrix22_eigenvalues(Real * A, Real * Adiag); /// solve @f$ A x = \Lambda x @f$ and return d and V such as @f$ A V[i:] = d[i] V[i:]@f$ static void matrixEig(UInt n, Real * A, Real * d, Real * V = NULL); template static inline void eigenvalues(Real * A, Real * d); /// determinent of a 3x3 matrix static inline Real det3(const Real * mat); /// determinent of a 2x2 matrix static inline Real det2(const Real * mat); /// inverse a nxn matrix static inline void inv(UInt n, const Real * mat, Real * inv); /// inverse a 3x3 matrix static inline void inv3(const Real * mat, Real * inv); /// inverse a 2x2 matrix static inline void inv2(const Real * mat, Real * inv); /* ------------------------------------------------------------------------ */ /* Vector algebra */ /* ------------------------------------------------------------------------ */ /// vector cross product static inline void vectorProduct3(const Real * v1, const Real * v2, Real * res); /// compute normal a normal to a vector static inline void normal2(const Real * v1, Real * res); /// compute normal a normal to a vector static inline void normal3(const Real * v1,const Real * v2, Real * res); /// normalize a vector static inline void normalize2(Real * v); /// normalize a vector static inline void normalize3(Real * v); /// return norm of a 2-vector static inline Real norm2(const Real * v); /// return norm of a 3-vector static inline Real norm3(const Real * v); /// return norm of a vector static inline Real norm(UInt n, const Real * v); /// return the dot product between 2 vectors in 2d static inline Real vectorDot2(const Real * v1, const Real * v2); /// return the dot product between 2 vectors in 3d static inline Real vectorDot3(const Real * v1, const Real * v2); /// return the dot product between 2 vectors static __aka_inline__ Real vectorDot(const Real * v1, const Real * v2, UInt n); /* ------------------------------------------------------------------------ */ /* Geometry */ /* ------------------------------------------------------------------------ */ /// distance in 2D between x and y static inline Real distance_2d(const Real * x, const Real * y); /// distance in 3D between x and y static inline Real distance_3d(const Real * x, const Real * y); /// radius of the in-circle of a triangle static inline Real triangle_inradius(const Real * coord1, const Real * coord2, const Real * coord3); /// radius of the in-circle of a tetrahedron static inline Real tetrahedron_inradius(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4); /// volume of a tetrahedron static inline Real tetrahedron_volume(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4); /// compute the barycenter of n points static inline void barycenter(const Real * coord, UInt nb_points, UInt spatial_dimension, Real * barycenter); /// vector between x and y static inline void vector_2d(const Real * x, const Real * y, Real * vec); /// vector pointing from x to y in 3 spatial dimension static inline void vector_3d(const Real * x, const Real * y, Real * vec); /// test if two scalar are equal within a given tolerance static inline bool are_float_equal(Real x, Real y); /// test if two vectors are equal within a given tolerance static inline bool are_vector_equal(UInt n, Real * x, Real * y); #ifdef isnan # error "You probably included which is incompatible with aka_math please use\ or add a \"#undef isnan\" before akantu includes" #endif /// test if a real is a NaN static inline bool isnan(Real x); /// test if the line x and y intersects each other static inline bool intersects(Real x_min, Real x_max, Real y_min, Real y_max); /// test if a is in the range [x_min, x_max] static inline bool is_in_range(Real a, Real x_min, Real x_max); static inline Real getTolerance() { return tolerance; }; static inline void setTolerance(Real tol) { tolerance = tol; }; private: /// tolerance for functions that need one static Real tolerance; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "aka_math_tmpl.hh" __END_AKANTU__ #endif /* __AKANTU_AKA_MATH_H__ */ diff --git a/src/common/aka_math_tmpl.hh b/src/common/aka_math_tmpl.hh index 5e39efa03..0622ce34d 100644 --- a/src/common/aka_math_tmpl.hh +++ b/src/common/aka_math_tmpl.hh @@ -1,662 +1,662 @@ /** * @file aka_math_inline_impl.cc * @author Nicolas Richart * @date Wed Jul 28 13:20:35 2010 * * @brief Implementation of the inline functions of the math toolkit * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ __END_AKANTU__ #include #include #ifdef AKANTU_USE_BLAS # ifndef AKANTU_USE_BLAS_MKL # include # else // AKANTU_USE_BLAS_MKL # include # endif //AKANTU_USE_BLAS_MKL #endif //AKANTU_USE_BLAS #ifdef AKANTU_USE_LAPACK extern "C" { void dgeev_(char* jobvl, char* jobvr, int* n, double* a, int* lda, double* wr, double* wi, double* vl, int* ldvl, double* vr, int* ldvr, double* work, int* lwork, int* info); // LU decomposition of a general matrix void dgetrf_(int* m, int *n, double* a, int* lda, int* ipiv, int* info); // generate inverse of a matrix given its LU decomposition void dgetri_(int* n, double* a, int* lda, int* ipiv, double* work, int* lwork, int* info); } #endif __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ inline void Math::matrix_vector(UInt m, UInt n, const Real * A, const Real * x, Real * y, Real alpha) { #ifdef AKANTU_USE_BLAS /// y = alpha*op(A)*x + beta*y cblas_dgemv(CblasRowMajor, CblasNoTrans, m, n, alpha, A, n, x, 1, 0, y, 1); #else memset(y, 0, m*sizeof(Real)); for (UInt i = 0; i < m; ++i) { UInt A_i = i * n; for (UInt j = 0; j < n; ++j) { y[i] += A[A_i + j] * x[j]; } y[i] *= alpha; } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_vector(UInt m, UInt n, const Real * A, const Real * x, Real * y, Real alpha) { #ifdef AKANTU_USE_BLAS /// y = alpha*op(A)*x + beta*y cblas_dgemv(CblasRowMajor, CblasNoTrans, m, n, alpha, A, m, x, 1, 0, y, 1); #else memset(y, 0, m*sizeof(Real)); for (UInt i = 0; i < m; ++i) { for (UInt j = 0; j < n; ++j) { y[i] += A[i + j * m] * x[j]; } y[i] *= alpha; } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrix_matrix(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, n, k, alpha, A, k, B, n, 0, C, n); #else memset(C, 0, m*n*sizeof(Real)); for (UInt j = 0; j < n; ++j) { for (UInt i = 0; i < m; ++i) { UInt A_i = i * k; UInt C_i = i * n; for (UInt l = 0; l < k; ++l) { UInt B_l = l * n; C[C_i + j] += A[A_i + l] * B[B_l + j]; } C[C_i + j] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_matrix(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans, m, n, k, alpha, A, m, B, n, 0, C, n); #else memset(C, 0, m*n*sizeof(Real)); for (UInt i = 0; i < m; ++i) { // UInt A_i = i * k; UInt C_i = i * n; for (UInt j = 0; j < n; ++j) { for (UInt l = 0; l < k; ++l) { C[C_i + j] += A[l * m + i] * B[l * n + j]; } C[C_i + j] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrix_matrixt(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, m, n, k, alpha, A, k, B, k, 0, C, n); #else memset(C, 0, m*n*sizeof(Real)); for (UInt i = 0; i < m; ++i) { UInt A_i = i * k; UInt C_i = i * n; for (UInt j = 0; j < n; ++j) { UInt B_j = j * k; for (UInt l = 0; l < k; ++l) { C[C_i + j] += A[A_i + l] * B[B_j + l]; } C[C_i + j] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_matrixt(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C cblas_dgemm(CblasRowMajor, CblasTrans, CblasTrans, m, n, k, alpha, A, m, B, k, 0, C, n); #else memset(C, 0, m * n * sizeof(Real)); for (UInt i = 0; i < m; ++i) { UInt C_i = i * n; for (UInt j = 0; j < n; ++j) { UInt B_j = j * k; for (UInt l = 0; l < k; ++l) { C[C_i + j] += A[l * m + i] * B[B_j + l]; } C[C_i + j] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline Real Math::vectorDot(const Real * v1, const Real * v2, UInt n) { #ifdef AKANTU_USE_BLAS /// d := v1 . v2 cblas_ddot(n, v1, 1, v2, 1); #else Real d = 0; for (UInt i = 0; i < n; ++i) { d += v1[i] * v2[i]; } #endif return d; } /* -------------------------------------------------------------------------- */ template inline void Math::matMul(UInt m, UInt n, UInt k, Real alpha, const Real * A, const Real * B, __attribute__ ((unused)) Real beta, Real * C) { if(tr_A) { if(tr_B) matrixt_matrixt(m, n, k, A, B, C, alpha); else matrixt_matrix(m, n, k, A, B, C, alpha); } else { if(tr_B) matrix_matrixt(m, n, k, A, B, C, alpha); else matrix_matrix(m, n, k, A, B, C, alpha); } } /* -------------------------------------------------------------------------- */ template inline void Math::matVectMul(UInt m, UInt n, Real alpha, const Real * A, const Real * x, __attribute__ ((unused)) Real beta, Real * y) { if(tr_A) { matrixt_vector(m, n, A, x, y, alpha); } else { matrix_vector(m, n, A, x, y, alpha); } } /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_LAPACK inline void Math::matrixEig(UInt n, Real * A, Real * d, Real * V) { // Matrix A is row major, so the lapack function in fortran will process // A^t. Asking for the left eigenvectors of A^t will give the transposed right // eigenvectors of A so in the C++ code the right eigenvectors. char jobvl; if(V != NULL) jobvl = 'V'; // compute left eigenvectors else jobvl = 'N'; // compute left eigenvectors char jobvr('N'); // compute right eigenvectors double * di = new double[n]; // imaginary part of the eigenvalues int info; int N = n; double wkopt; int lwork = -1; // query and allocate the optimal workspace dgeev_(&jobvl, &jobvr, &N, A, &N, d, di, V, &N, NULL, &N, &wkopt, &lwork, &info); lwork = int(wkopt); double * work = new double[lwork]; // solve the eigenproblem dgeev_(&jobvl, &jobvr, &N, A, &N, d, di, V, &N, NULL, &N, work, &lwork, &info); AKANTU_DEBUG_ASSERT(info == 0, "Problem computing eigenvalues/vectors. DGEEV exited with the value " << info); delete [] work; delete [] di; // I hope for you that there was no complex eigenvalues !!! } #else inline void Math::matrixEig(__attribute__((unused)) UInt n, __attribute__((unused)) Real * A, __attribute__((unused)) Real * d, __attribute__((unused)) Real * V) { AKANTU_DEBUG_ERROR("You have to compile with the support of LAPACK activated to use this function!"); } #endif /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_LAPACK inline void Math::inv(UInt n, const Real * A, Real * invA) { int N = n; int info; int * ipiv = new int[N+1]; int lwork = N*N; double * work = new double[lwork]; std::copy(A, A + n*n, invA); dgetrf_(&N, &N, invA, &N, ipiv, &info); if(info > 0) { AKANTU_DEBUG_ERROR("Singular matrix - cannot factorize it (info: " << info <<" )"); } dgetri_(&N, invA, &N, ipiv, work, &lwork, &info); if(info != 0) { AKANTU_DEBUG_ERROR("Cannot invert the matrix (info: "<< info <<" )"); } delete [] ipiv; delete [] work; } #else inline void Math::inv(__attribute__((unused)) UInt n, __attribute__((unused)) const Real * A, __attribute__((unused)) Real * Ainv) { AKANTU_DEBUG_ERROR("You have to compile with the support of LAPACK activated to use this function!"); } #endif /* -------------------------------------------------------------------------- */ inline void Math::matrix22_eigenvalues(Real * A, Real *Adiag) { ///d = determinant of Matrix A Real d = det2(A); ///b = trace of Matrix A Real b = A[0]+A[3]; Real c = sqrt(b*b - 4 *d); Adiag[0]= .5*(b + c); Adiag[1]= .5*(b - c); } /* -------------------------------------------------------------------------- */ inline void Math::matrix33_eigenvalues(Real * A, Real *Adiag) { - ///d = determinant of Matrix A - Real d = det3(A); - ///b = trace of Matrix A - Real b = A[0]+A[4]+A[8]; - - Real a = -1 ; - /// c = 0.5*(trace(M^2)-trace(M)^2) - Real c = A[3]*A[1] + A[2]*A[6] + A[5]*A[7] - A[0]*A[4] - - A[0]*A[8] - A[4]*A[8]; - /// Define x, y, z - Real x = ((3*c/a) - ((b*b)/(a*a)))/3; - Real y=((2*(b*b*b)/(a*a*a)) - (9*b*c/(a*a)) + (27*d/a))/27; - Real z = (y*y)/4 + (x*x*x)/27; - /// Define I, j, k, m, n, p (so equations are not so cluttered) - Real i = sqrt(y*y/4 - z); - Real j = -pow(i,1./3.); - Real k; - if (fabs(i)<1e-12) - k = 0; - else - k = acos(-(y/(2*i))); - - Real m = cos(k/3); - Real n = sqrt(3)*sin(k/3); - Real p = b/(3*a); - - Adiag[0]=-(2*j*m + p);; - Adiag[1]=-(-j *(m + n) + p); - Adiag[2]=-(-j * (m - n) + p); + /// a L^3 + b L^2 + c L + d = 0 + matrixEig(3, A, Adiag); +// Real a = -1 ; +// ///b = trace of Matrix A +// Real b = A[0]+A[4]+A[8]; +// /// c = 0.5*(trace(M^2)-trace(M)^2) +// Real c = A[1]*A[3] + A[2]*A[6] + A[5]*A[7] - A[0]*A[4] - +// A[0]*A[8] - A[4]*A[8]; +// ///d = determinant of Matrix A +// Real d = det3(A); +// +// /// Define x, y, z +// Real x = c/a - b*b/(3.*a*a); +// Real y = 2.*b*b*b/(27.*a*a*a) - b*c/(3.*a*a) + d/a; +// Real z = y*y/4. + x*x*x/27.; +// /// Define I, j, k, m, n, p (so equations are not so cluttered) +// Real i = sqrt(y*y/4. - z); +// Real j = pow(i,1./3.); +// Real k = 0; +// if (std::abs(i) > 1e-12) +// k = acos(-(y/(2.*i))); +// +// Real m = cos(k/3); +// Real n = sqrt(3.)*sin(k/3); +// Real p = -b/(3.*a); +// +// Adiag[0] = 2*j*m + p; +// Adiag[1] = -j *(m + n) + p; +// Adiag[2] = -j * (m - n) + p; } /* -------------------------------------------------------------------------- */ template inline void Math::eigenvalues(Real * A, Real * d) { if(dim == 1) { d[0] = A[0]; } else if(dim == 2) { matrix22_eigenvalues(A, d); } - else if(dim == 3) { matrix33_eigenvalues(A, d); } + // else if(dim == 3) { matrix33_eigenvalues(A, d); } else matrixEig(dim, A, d); } /* -------------------------------------------------------------------------- */ inline Real Math::det2(const Real * mat) { return mat[0]*mat[3] - mat[1]*mat[2]; } /* -------------------------------------------------------------------------- */ inline Real Math::det3(const Real * mat) { return mat[0]*(mat[4]*mat[8]-mat[7]*mat[5]) - mat[3]*(mat[1]*mat[8]-mat[7]*mat[2]) + mat[6]*(mat[1]*mat[5]-mat[4]*mat[2]); } /* -------------------------------------------------------------------------- */ inline void Math::normal2(const Real * vec,Real * normal) { normal[0] = vec[1]; normal[1] = -vec[0]; Math::normalize2(normal); } /* -------------------------------------------------------------------------- */ inline void Math::normal3(const Real * vec1,const Real * vec2,Real * normal) { Math::vectorProduct3(vec1,vec2,normal); Math::normalize3(normal); } /* -------------------------------------------------------------------------- */ inline void Math::normalize2(Real * vec) { Real norm = Math::norm2(vec); vec[0] /= norm; vec[1] /= norm; } /* -------------------------------------------------------------------------- */ inline void Math::normalize3(Real * vec) { Real norm = Math::norm3(vec); vec[0] /= norm; vec[1] /= norm; vec[2] /= norm; } /* -------------------------------------------------------------------------- */ inline Real Math::norm2(const Real * vec) { return sqrt(vec[0]*vec[0] + vec[1]*vec[1]); } /* -------------------------------------------------------------------------- */ inline Real Math::norm3(const Real * vec) { return sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); } /* -------------------------------------------------------------------------- */ inline Real Math::norm(UInt n, const Real * vec) { Real norm = 0.; for (UInt i = 0; i < n; ++i) { norm += vec[i]*vec[i]; } return sqrt(norm); } /* -------------------------------------------------------------------------- */ inline void Math::inv2(const Real * mat,Real * inv) { Real det_mat = det2(mat); inv[0] = mat[3] / det_mat; inv[1] = -mat[1] / det_mat; inv[2] = -mat[2] / det_mat; inv[3] = mat[0] / det_mat; } /* -------------------------------------------------------------------------- */ inline void Math::inv3(const Real * mat,Real * inv) { Real det_mat = det3(mat); inv[0] = (mat[4]*mat[8] - mat[7]*mat[5])/det_mat; inv[1] = (mat[2]*mat[7] - mat[8]*mat[1])/det_mat; inv[2] = (mat[1]*mat[5] - mat[4]*mat[2])/det_mat; inv[3] = (mat[5]*mat[6] - mat[8]*mat[3])/det_mat; inv[4] = (mat[0]*mat[8] - mat[6]*mat[2])/det_mat; inv[5] = (mat[2]*mat[3] - mat[5]*mat[0])/det_mat; inv[6] = (mat[3]*mat[7] - mat[6]*mat[4])/det_mat; inv[7] = (mat[1]*mat[6] - mat[7]*mat[0])/det_mat; inv[8] = (mat[0]*mat[4] - mat[3]*mat[1])/det_mat; } /* -------------------------------------------------------------------------- */ inline void Math::vectorProduct3(const Real * v1, const Real * v2, Real * res) { res[0] = v1[1]*v2[2] - v1[2]*v2[1]; res[1] = v1[2]*v2[0] - v1[0]*v2[2]; res[2] = v1[0]*v2[1] - v1[1]*v2[0]; } /* -------------------------------------------------------------------------- */ inline Real Math::vectorDot2(const Real * v1, const Real * v2) { return (v1[0]*v2[0] + v1[1]*v2[1]); } /* -------------------------------------------------------------------------- */ inline Real Math::vectorDot3(const Real * v1, const Real * v2) { return (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]); } /* -------------------------------------------------------------------------- */ inline Real Math::distance_2d(const Real * x, const Real * y) { return sqrt((y[0] - x[0])*(y[0] - x[0]) + (y[1] - x[1])*(y[1] - x[1])); } /* -------------------------------------------------------------------------- */ inline Real Math::triangle_inradius(const Real * coord1, const Real * coord2, const Real * coord3) { /** * @f{eqnarray*}{ * r &=& A / s \\ * A &=& 1/4 * \sqrt{(a + b + c) * (a - b + c) * (a + b - c) (-a + b + c)} \\ * s &=& \frac{a + b + c}{2} * @f} */ Real a, b, c; a = distance_2d(coord1, coord2); b = distance_2d(coord2, coord3); c = distance_2d(coord1, coord3); Real s; s = (a + b + c) * 0.5; return sqrt((s - a) * (s - b) * (s - c) / s); } /* -------------------------------------------------------------------------- */ inline Real Math::distance_3d(const Real * x, const Real * y) { return sqrt((y[0] - x[0])*(y[0] - x[0]) + (y[1] - x[1])*(y[1] - x[1]) + (y[2] - x[2])*(y[2] - x[2]) ); } /* -------------------------------------------------------------------------- */ inline Real Math::tetrahedron_volume(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4) { Real xx[9], vol; xx[0] = coord2[0]; xx[1] = coord2[1]; xx[2] = coord2[2]; xx[3] = coord3[0]; xx[4] = coord3[1]; xx[5] = coord3[2]; xx[6] = coord4[0]; xx[7] = coord4[1]; xx[8] = coord4[2]; vol = det3(xx); xx[0] = coord1[0]; xx[1] = coord1[1]; xx[2] = coord1[2]; xx[3] = coord3[0]; xx[4] = coord3[1]; xx[5] = coord3[2]; xx[6] = coord4[0]; xx[7] = coord4[1]; xx[8] = coord4[2]; vol -= det3(xx); xx[0] = coord1[0]; xx[1] = coord1[1]; xx[2] = coord1[2]; xx[3] = coord2[0]; xx[4] = coord2[1]; xx[5] = coord2[2]; xx[6] = coord4[0]; xx[7] = coord4[1]; xx[8] = coord4[2]; vol += det3(xx); xx[0] = coord1[0]; xx[1] = coord1[1]; xx[2] = coord1[2]; xx[3] = coord2[0]; xx[4] = coord2[1]; xx[5] = coord2[2]; xx[6] = coord3[0]; xx[7] = coord3[1]; xx[8] = coord3[2]; vol -= det3(xx); vol /= 6; return vol; } /* -------------------------------------------------------------------------- */ inline Real Math::tetrahedron_inradius(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4) { Real l12, l13, l14, l23, l24, l34; l12 = distance_3d(coord1, coord2); l13 = distance_3d(coord1, coord3); l14 = distance_3d(coord1, coord4); l23 = distance_3d(coord2, coord3); l24 = distance_3d(coord2, coord4); l34 = distance_3d(coord3, coord4); Real s1, s2, s3, s4; s1 = (l12 + l23 + l13) * 0.5; s1 = sqrt(s1*(s1-l12)*(s1-l23)*(s1-l13)); s2 = (l12 + l24 + l14) * 0.5; s2 = sqrt(s2*(s2-l12)*(s2-l24)*(s2-l14)); s3 = (l23 + l34 + l24) * 0.5; s3 = sqrt(s3*(s3-l23)*(s3-l34)*(s3-l24)); s4 = (l13 + l34 + l14) * 0.5; s4 = sqrt(s4*(s4-l13)*(s4-l34)*(s4-l14)); Real volume = Math::tetrahedron_volume(coord1,coord2,coord3,coord4); return 3*volume/(s1+s2+s3+s4); } /* -------------------------------------------------------------------------- */ inline void Math::barycenter(const Real * coord, UInt nb_points, UInt spatial_dimension, Real * barycenter) { memset(barycenter, 0, spatial_dimension * sizeof(Real)); for (UInt n = 0; n < nb_points; ++n) { UInt offset = n * spatial_dimension; for (UInt i = 0; i < spatial_dimension; ++i) { barycenter[i] += coord[offset + i] / (Real) nb_points; } } } /* -------------------------------------------------------------------------- */ inline void Math::vector_2d(const Real * x, const Real * y, Real * res) { res[0] = y[0]-x[0]; res[1] = y[1]-x[1]; } /* -------------------------------------------------------------------------- */ inline void Math::vector_3d(const Real * x, const Real * y, Real * res) { res[0] = y[0]-x[0]; res[1] = y[1]-x[1]; res[2] = y[2]-x[2]; } /* -------------------------------------------------------------------------- */ inline bool Math::are_float_equal(const Real x, const Real y){ return (std::abs( x - y) < tolerance); } /* -------------------------------------------------------------------------- */ inline bool Math::isnan(Real x) { #if defined(__INTEL_COMPILER) #pragma warning ( push ) #pragma warning ( disable : 1572 ) #endif //defined(__INTEL_COMPILER) // x = x return false means x = quiet_NaN return !(x == x); #if defined(__INTEL_COMPILER) #pragma warning ( pop ) #endif //defined(__INTEL_COMPILER) } /* -------------------------------------------------------------------------- */ inline bool Math::are_vector_equal(UInt n, Real * x, Real * y){ bool test = true; for (UInt i = 0; i < n; ++i) { test &= are_float_equal(x[i],y[i]); } return test; } /* -------------------------------------------------------------------------- */ inline bool Math::intersects(Real x_min, Real x_max, Real y_min, Real y_max) { return ! ((x_max < y_min) || (x_min > y_max)); } /* -------------------------------------------------------------------------- */ inline bool Math::is_in_range(Real a, Real x_min, Real x_max) { return ((a >= x_min) && (a <= x_max)); } diff --git a/src/common/aka_types.hh b/src/common/aka_types.hh index fb260a805..50b7b5cde 100644 --- a/src/common/aka_types.hh +++ b/src/common/aka_types.hh @@ -1,509 +1,509 @@ /** * @file aka_types.hh * @author Nicolas Richart * @date Wed Feb 16 20:28:13 2011 * * @brief description of the "simple" types * * @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_error.hh" #include "aka_math.hh" #include "aka_vector.hh" /* -------------------------------------------------------------------------- */ #include #ifndef __INTEL_COMPILER #include #else #include #endif /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_TYPES_HH__ #define __AKANTU_AKA_TYPES_HH__ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* maps */ /* -------------------------------------------------------------------------- */ #ifndef __INTEL_COMPILER template struct unordered_map { typedef typename std::tr1::unordered_map type; }; #else template struct unordered_map { typedef typename std::map type; }; #endif namespace types { class Matrix; /* ------------------------------------------------------------------------ */ /* Vector */ /* ------------------------------------------------------------------------ */ template class Vector { public: Vector() : n(0), values(NULL), wrapped(false) {} Vector(UInt n, T def = T()) : n(n), values(new T[n]), wrapped(false) { std::fill_n(values, n, def); } Vector(T* data, UInt n) : n(n), values(data), wrapped(true) {} Vector(const Vector & src) { wrapped = src.wrapped; n = src.n; if (src.wrapped) { values = src.values; } else { values = new T[n]; memcpy(this->values, src.values, n * sizeof(T)); } } virtual ~Vector() { if(!wrapped) delete [] values; }; /* ---------------------------------------------------------------------- */ UInt size() const { return n; } T * storage() const { return values; } /* ---------------------------------------------------------------------- */ void shallowCopy(const Vector & src) { if(!wrapped) delete [] values; this->n = src.n; this->wrapped = true; this->values = src.values; } /* ---------------------------------------------------------------------- */ inline T& operator()(UInt i) { return *(values + i); }; inline const T& operator()(UInt i) const { return *(values + i); }; inline T& operator[](UInt idx) { return *(values + idx); }; inline const T& operator[](UInt idx) const { return *(values + idx); }; /* ---------------------------------------------------------------------- */ inline Vector & operator=(const Vector & src) { if(this != &src) { if (wrapped) { AKANTU_DEBUG_ASSERT(n == src.n, "vectors of different size"); memcpy(this->values, src.values, n * sizeof(T)); } else { n = src.n; - delete []values; + delete [] values; values = new T[n]; memcpy(this->values, src.values, n * sizeof(T)); } } return *this; } /* ---------------------------------------------------------------------- */ inline Vector & operator+=(const Vector & vect) { T * a = this->storage(); T * b = vect.storage(); for (UInt i = 0; i < n; ++i) *(a++) += *(b++); return *this; } /* ---------------------------------------------------------------------- */ inline Vector & operator+=(const T & x) { T * a = this->values; for (UInt i = 0; i < n; ++i) *(a++) += x; return *this; } /* ---------------------------------------------------------------------- */ inline Vector & operator-=(const Vector & vect) { T * a = this->storage(); T * b = vect.storage(); for (UInt i = 0; i < n; ++i) *(a++) -= *(b++); return *this; } /* ---------------------------------------------------------------------- */ inline Vector & operator*=(const T & scalar) { T * a = this->storage(); for (UInt i = 0; i < n; ++i) *(a++) *= scalar; return *this; } /* -------------------------------------------------------------------------- */ inline Vector & operator=(T & scalar) { T * a = this->storage(); for (UInt i = 0; i < n; ++i) *(a++) = scalar; return *this; } /* ---------------------------------------------------------------------- */ inline Vector & operator/=(const T & x) { T * a = this->values; for (UInt i = 0; i < n; ++i) *(a++) /= x; return *this; } /* ---------------------------------------------------------------------- */ inline Real dot(const Vector & vect) { return Math::vectorDot(values, vect.storage(), n); } /* ---------------------------------------------------------------------- */ inline Vector & crossProduct(const Vector & v1, const Vector & v2) { AKANTU_DEBUG_ASSERT(n == 3, "crossProduct is only defined in 3D"); AKANTU_DEBUG_ASSERT(n == v1.n && n == v2.n, "crossProduct is not a valid operation non matching size vectors"); // for (UInt i = 0; i < n; ++i) { // values[i] = // v1((i+1) % n) * v2((i+2) % n) - // v1((i+2) % n) * v1((i+1) % n); // } Math::vectorProduct3(v1.values, v2.values, this->values); return *this; } /* ---------------------------------------------------------------------- */ inline void clear() { memset(values, 0, n * sizeof(T)); }; template inline void mul(const Matrix & A, const Vector & x, Real alpha = 1.0); /* ---------------------------------------------------------------------- */ inline Real norm() const { return Math::norm(this->n, this->values); } /* ---------------------------------------------------------------------- */ /// norm of (*this - x) inline Real distance(const Vector & y) const { Real * vx = values; Real * vy = y.storage(); Real sum_2 = 0; for (UInt i = 0; i < n; ++i, ++vx, ++vy) sum_2 += (*vx - *vy)*(*vx - *vy); return sqrt(sum_2); } /* ---------------------------------------------------------------------- */ /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "types::Vector<" << debug::demangle(typeid(T).name()) << "> [" << n <<"] :" << std::endl; stream << space << AKANTU_INDENT << "| "; for (UInt i = 0; i < n; ++i) { stream << values[i] << " "; } stream << "|" << std::endl; } friend class ::akantu::Vector; protected: UInt n; T * values; bool wrapped; }; typedef Vector RVector; // support operations for the creation of other vectors template Vector operator*(T scalar, const Vector& a); template Vector operator+(const Vector& a, const Vector& b); template Vector operator-(const Vector& a, const Vector& b); /* -------------------------------------------------------------------------- */ template Vector operator*(T scalar, const Vector& a) { Vector r = a; r *= scalar; return r; } template Vector operator+(const Vector& a, const Vector& b) { Vector r = a; r += b; return r; } template Vector operator-(const Vector& a, const Vector& b) { Vector r = a; r -= b; return r; } /* ------------------------------------------------------------------------ */ /* Matrix */ /* ------------------------------------------------------------------------ */ class Matrix { public: Matrix() : m(0), n(0), values(NULL), wrapped(true) {}; Matrix(UInt m, UInt n, Real def = 0) : m(m), n(n), values(new Real[n*m]), wrapped(false) { std::fill_n(values, n*m, def); }; Matrix(Real * data, UInt m, UInt n) : m(m), n(n), values(data), wrapped(true) {}; Matrix(const Matrix & src) { m = src.m; n = src.n; values = src.values; wrapped = src.wrapped; const_cast(src).wrapped = true; }; virtual ~Matrix() { if(!wrapped) delete [] values; }; /* ---------------------------------------------------------------------- */ UInt size() const { return n*m; }; UInt rows() const { return m; }; UInt cols() const { return n; }; Real * storage() const { return values; }; /* ---------------------------------------------------------------------- */ void shallowCopy(const Matrix & src) { if(!wrapped) delete [] values; this->n = src.n; this->m = src.m; this->wrapped = true; this->values = src.values; } /* ---------------------------------------------------------------------- */ inline Real& operator()(UInt i, UInt j) { return *(values + i*n + j); }; inline const Real& operator()(UInt i, UInt j) const { return *(values + i*n + j); }; inline Real& operator[](UInt idx) { return *(values + idx); }; inline const Real& operator[](UInt idx) const { return *(values + idx); }; inline Matrix & operator=(const Matrix & mat) { if(this != &mat) { if(values != NULL) { memcpy(this->values, mat.values, m*n*sizeof(Real)); } else { this->m = mat.m; this->n = mat.n; this->values = mat.values; const_cast(mat).wrapped = true; this->wrapped = false; } } return *this; }; /* ---------------------------------------------------------------------- */ inline Matrix & operator=(Real x) { Real * a = this->values; for (UInt i = 0; i < n*m; ++i) *(a++) = x; return *this; } /* ---------------------------------------------------------------------- */ inline Matrix operator* (const Matrix & B) { Matrix C(this->m, B.n); C.mul(*this, B); return C; }; /* ---------------------------------------------------------------------- */ inline Matrix & operator+=(const Matrix & A) { Real * a = this->storage(); Real * b = A.storage(); for (UInt i = 0; i < n*m; ++i) *(a++) += *(b++); return *this; } /* ---------------------------------------------------------------------- */ inline Matrix & operator+=(Real x) { Real * a = this->values; for (UInt i = 0; i < n*m; ++i) *(a++) += x; return *this; } /* ---------------------------------------------------------------------- */ inline Matrix & operator*=(Real x) { Real * a = this->storage(); for (UInt i = 0; i < n*m; ++i) *(a++) *= x; return *this; } /* ---------------------------------------------------------------------- */ inline Matrix & operator/=(Real x) { Real * a = this->values; for (UInt i = 0; i < n*m; ++i) *(a++) /= x; return *this; } /* ---------------------------------------------------------------------- */ template inline void mul(const Matrix & A, const Matrix & B, Real alpha = 1.0) { UInt k = A.n; if(tr_A) k = A.m; #ifndef AKANTU_NDEBUG if (tr_B){ AKANTU_DEBUG_ASSERT(k == B.n, "matrices to multiply have no fit dimensions"); AKANTU_DEBUG_ASSERT(n == B.m, "matrices to multiply have no fit dimensions"); } else { AKANTU_DEBUG_ASSERT(k == B.m, "matrices to multiply have no fit dimensions"); AKANTU_DEBUG_ASSERT(n == B.n, "matrices to multiply have no fit dimensions"); } if (tr_A){ AKANTU_DEBUG_ASSERT(m == A.n, "matrices to multiply have no fit dimensions"); } else{ AKANTU_DEBUG_ASSERT(m == A.m, "matrices to multiply have no fit dimensions"); } #endif //AKANTU_NDEBUG Math::matMul(m, n, k, alpha, A.storage(), B.storage(), 0., values); } /* ---------------------------------------------------------------------- */ inline void outerProduct(const types::Vector & A, const types::Vector & B) { AKANTU_DEBUG_ASSERT(A.size() == m && B.size() == n, "A and B are not compatible with the size of the matrix"); for (UInt i = 0; i < m; ++i) { for (UInt j = 0; j < n; ++j) { values[i * m + j] += A[i] * B[j]; } } } /* ---------------------------------------------------------------------- */ inline void eig(types::Vector & eigenvalues, Matrix & eigenvectors) const { AKANTU_DEBUG_ASSERT(n == m, "eig is not a valid operation on a rectangular matrix"); Math::matrixEig(this->n, this->values, eigenvalues.storage(), eigenvectors.storage()); } /* ---------------------------------------------------------------------- */ inline void clear() { std::fill_n(values, m * n, 0); }; /* ---------------------------------------------------------------------- */ inline void copy(const Matrix & src) { memcpy(values, src.storage(), m * n * sizeof(Real)); } /* ---------------------------------------------------------------------- */ inline void eye(Real alpha = 1.) { AKANTU_DEBUG_ASSERT(n == m, "eye is not a valid operation on a rectangular matrix"); clear(); for (UInt i = 0; i < n; ++i) { values[i*n + i] = alpha; } } /* ---------------------------------------------------------------------- */ inline Real trace() const { AKANTU_DEBUG_ASSERT(n == m, "trace is not a valid operation on a rectangular matrix"); Real trace = 0.; for (UInt i = 0; i < n; ++i) trace += values[i*n + i]; return trace; } /* -------------------------------------------------------------------------- */ inline Real norm() const { return Math::norm(this->n*this->m, this->values); } /* ---------------------------------------------------------------------- */ inline Matrix transpose() const { Matrix tmp(m, n); for (UInt i = 0; i < n; ++i) { for (UInt j = 0; j < m; ++j) { tmp(j,i) = operator()(i,j); } } return tmp; } /* ---------------------------------------------------------------------- */ inline void inverse(const Matrix & A) { AKANTU_DEBUG_ASSERT(A.n == A.m, "inv is not a valid operation on a rectangular matrix"); AKANTU_DEBUG_ASSERT(n == A.n, "the matrix should have the same size as its inverse"); Math::inv(A.n, A.values, this->values); } /* ---------------------------------------------------------------------- */ /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "types::Matrix" << " [" << n << "," << m <<"] :" << std::endl; for (UInt i = 0; i < m; ++i) { stream << space << AKANTU_INDENT << "| "; for (UInt j = 0; j < n; ++j) { stream << std::setw(10) << values[i*n +j] << " "; } stream << "|" << std::endl; } }; friend class ::akantu::Vector; protected: UInt m; UInt n; Real* values; bool wrapped; }; /* ------------------------------------------------------------------------ */ template template inline void Vector::mul(const Matrix & A, const Vector & x, Real alpha) { UInt n = x.n; Math::matVectMul(this->n, n, alpha, A.storage(), x.storage(), 0., values); } /* -------------------------------------------------------------------------- */ inline std::ostream & operator<<(std::ostream & stream, const Matrix & _this) { _this.printself(stream); return stream; } /* -------------------------------------------------------------------------- */ template inline std::ostream & operator<<(std::ostream & stream, const Vector & _this) { _this.printself(stream); return stream; } } __END_AKANTU__ #endif /* __AKANTU_AKA_TYPES_HH__ */ diff --git a/src/common/aka_vector.cc b/src/common/aka_vector.cc index 267f0bd35..5e4b7a029 100644 --- a/src/common/aka_vector.cc +++ b/src/common/aka_vector.cc @@ -1,121 +1,121 @@ /** * @file aka_vector.cc * @author Nicolas Richart * @date Thu Jun 17 15:14:24 2010 * * @brief class vector * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_vector.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Functions VectorBase */ /* -------------------------------------------------------------------------- */ VectorBase::VectorBase(const ID & id) : id(id), allocated_size(0), size(0), nb_component(1), size_of_type(0) { } /* -------------------------------------------------------------------------- */ VectorBase::~VectorBase() { } /* -------------------------------------------------------------------------- */ void VectorBase::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "VectorBase [" << std::endl; stream << space << " + size : " << size << std::endl; stream << space << " + nb component : " << nb_component << std::endl; stream << space << " + allocated size : " << allocated_size << std::endl; Real mem_size = (allocated_size * nb_component * size_of_type) / 1024.; stream << space << " + size of type : " << size_of_type << "B" << std::endl; stream << space << " + memory allocated : " << mem_size << "kB" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ template <> Int Vector::find(const Real & elem) const { AKANTU_DEBUG_IN(); UInt i = 0; Real epsilon = std::numeric_limits::epsilon(); for (; (i < size) && (fabs(values[i] - elem) <= epsilon); ++i); AKANTU_DEBUG_OUT(); return (i == size) ? -1 : (Int) i; } /* -------------------------------------------------------------------------- */ template <> Vector & Vector::operator*=(__attribute__((unused)) const ElementType & alpha) { AKANTU_DEBUG_TO_IMPLEMENT(); return *this; } template <> Vector & Vector::operator-=(__attribute__((unused)) const Vector & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); return *this; } template <> Vector & Vector::operator+=(__attribute__((unused)) const Vector & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); return *this; } template <> Vector & Vector::operator*=(__attribute__((unused)) const char & alpha) { AKANTU_DEBUG_TO_IMPLEMENT(); return *this; } template <> Vector & Vector::operator-=(__attribute__((unused)) const Vector & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); return *this; } template <> Vector & Vector::operator+=(__attribute__((unused)) const Vector & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); return *this; } /* -------------------------------------------------------------------------- */ // template class Vector; // template class Vector; // template class Vector; // template class Vector; // template class Vector; // template class Vector; // template class Vector; -//template class Vector; +// template class Vector; __END_AKANTU__ diff --git a/src/common/aka_vector.hh b/src/common/aka_vector.hh index 2d60d0cb5..dd163980e 100644 --- a/src/common/aka_vector.hh +++ b/src/common/aka_vector.hh @@ -1,355 +1,369 @@ /** * @file aka_vector.hh * @author Nicolas Richart * @date Thu Jun 17 10:04:55 2010 * * @brief class of vectors * * @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_VECTOR_HH__ #define __AKANTU_VECTOR_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class Matrix; /// class that afford to store vectors in static memory class VectorBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: VectorBase(const ID & id = ""); virtual ~VectorBase(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// get the amount of space allocated in bytes inline UInt getMemorySize() const; /// set the size to zero without freeing the allocated space inline void empty(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(AllocatedSize, allocated_size, UInt); AKANTU_GET_MACRO(Size, size, UInt); AKANTU_GET_MACRO(NbComponent, nb_component, UInt); AKANTU_GET_MACRO(ID, id, const ID &); AKANTU_GET_MACRO(Tag, tag, const std::string &); AKANTU_SET_MACRO(Tag, tag, const std::string &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the vector ID id; /// the size allocated UInt allocated_size; /// the size used UInt size; /// number of components UInt nb_component; /// size of the stored type UInt size_of_type; /// User defined tag std::string tag; }; - +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ namespace types { class Matrix; template class Vector; } + /* -------------------------------------------------------------------------- */ -template class Vector : public VectorBase { +template::value > +class Vector : public VectorBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef T value_type; typedef value_type & reference; typedef value_type * pointer_type; typedef const value_type & const_reference; /// Allocation of a new vector inline Vector(UInt size = 0, UInt nb_component = 1, const ID & id = ""); /// Allocation of a new vector with a default value Vector(UInt size, UInt nb_component, const value_type def_values[], const ID & id = ""); /// Allocation of a new vector with a default value Vector(UInt size, UInt nb_component, const_reference value, const ID & id = ""); /// Copy constructor (deep copy if deep=true) - Vector(const Vector& vect, bool deep = true, const ID & id = ""); + Vector(const Vector& vect, bool deep = true, const ID & id = ""); /// Copy constructor (deep copy) - Vector(const std::vector& vect); + Vector(const std::vector & vect); virtual inline ~Vector(); /* ------------------------------------------------------------------------ */ /* Iterator */ /* ------------------------------------------------------------------------ */ /// \todo protected: does not compile with intel check why public: - template + template ::value > class iterator_internal; public: /* ------------------------------------------------------------------------ */ // template class iterator : public iterator_internal {}; // template class const_iterator : public iterator_internal {}; /* ------------------------------------------------------------------------ */ - template + //template using iterator = iterator_internal; + + template class iterator : public iterator_internal { public: typedef iterator_internal parent; - typedef typename parent::pointer pointer; + typedef typename parent::value_type value_type; + typedef typename parent::pointer pointer; + typedef typename parent::reference reference; + typedef typename parent::difference_type difference_type; + typedef typename parent::iterator_category iterator_category; public: iterator() : parent() {}; iterator(pointer_type data, UInt offset) : parent(data, offset) {}; iterator(pointer warped) : parent(warped) {}; iterator(const iterator & it) : parent(it) {}; + iterator(const parent & it) : parent(it) {}; + + inline iterator operator+(difference_type n) + { return parent::operator+(n);; } + inline iterator operator-(difference_type n) + { return parent::operator-(n);; } + inline difference_type operator-(const iterator & b) + { return parent::operator-(b); } + + inline iterator & operator++() + { parent::operator++(); return *this; }; + inline iterator & operator--() + { parent::operator--(); return *this; }; + inline iterator & operator+=(const UInt n) + { parent::operator+=(n); return *this; } }; /* ------------------------------------------------------------------------ */ - template + //template using const_iterator = iterator_internal; + + template class const_iterator : public iterator_internal { public: typedef iterator_internal parent; - typedef typename parent::pointer pointer; + typedef typename parent::value_type value_type; + typedef typename parent::pointer pointer; + typedef typename parent::reference reference; + typedef typename parent::difference_type difference_type; + typedef typename parent::iterator_category iterator_category; public: const_iterator() : parent() {}; const_iterator(pointer_type data, UInt offset) : parent(data, offset) {}; const_iterator(pointer warped) : parent(warped) {}; const_iterator(const const_iterator & it) : parent(it) {}; - }; + const_iterator(const parent & it) : parent(it) {}; + + inline const_iterator operator+(difference_type n) + { return parent::operator+(n); } + inline const_iterator operator-(difference_type n) + { return parent::operator-(n); } + inline difference_type operator-(const const_iterator & b) + { return parent::operator-(b); } + + inline const_iterator & operator++() + { parent::operator++(); return *this; }; + inline const_iterator & operator--() + { parent::operator--(); return *this; }; + inline const_iterator & operator+=(const UInt n) + { parent::operator+=(n); return *this; } - /// specialization of the previous iterators for the scalar types - /* ------------------------------------------------------------------------ */ - template - class iterator : public iterator_internal { - public: - typedef iterator_internal parent; - typedef typename parent::pointer pointer; - public: - iterator() : parent() {}; - iterator(pointer_type data, UInt offset) : parent(data, offset) {}; - iterator(pointer warped) : parent(warped) {}; - iterator(const iterator & it) : parent(it) {}; - }; - - /* -------------------------------------------------------------------------- */ - template - class const_iterator : public iterator_internal { - public: - typedef iterator_internal parent; - typedef typename parent::pointer pointer; - public: - const_iterator() : parent() {}; - const_iterator(pointer_type data, UInt offset) : parent(data, offset) {}; - const_iterator(pointer warped) : parent(warped) {}; - const_iterator(const const_iterator & it) : parent(it) {}; }; - - /* ------------------------------------------------------------------------ */ - // template inline iterator begin(); - // template inline iterator end(); - // template inline const_iterator begin() const; - // template inline const_iterator end() const; - inline iterator begin(); inline iterator end(); inline const_iterator begin() const; inline const_iterator end() const; inline iterator< types::Vector > begin(UInt n); inline iterator< types::Vector > end(UInt n); inline const_iterator< types::Vector > begin(UInt n) const; inline const_iterator< types::Vector > end(UInt n) const; inline iterator< types::Matrix > begin(UInt m, UInt n); inline iterator< types::Matrix > end(UInt m, UInt n); inline const_iterator< types::Matrix > begin(UInt m, UInt n) const; inline const_iterator< types::Matrix > end(UInt m, UInt n) const; inline iterator< types::Matrix > begin_reinterpret(UInt m, UInt n, UInt size, UInt nb_component); inline iterator< types::Matrix > end_reinterpret(UInt m, UInt n, UInt size, UInt nb_component); inline const_iterator< types::Matrix > begin_reinterpret(UInt m, UInt n, UInt size, UInt nb_component) const; inline const_iterator< types::Matrix > end_reinterpret(UInt m, UInt n, UInt size, UInt nb_component) const; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// get jth componemt of the ith tuple in read-only inline const_reference get(UInt i, UInt j = 0) const; /// get jth component of the ith tuple inline reference at(UInt i, UInt j = 0); /// add an element at the end of the vector with the value value for all /// component inline void push_back(const_reference value); /// add an element at the end of the vector inline void push_back(const value_type new_elem[]); + template + inline void push_back(const iterator & it); + /** * remove an element and move the last one in the hole * /!\ change the order in the vector */ inline void erase(UInt i); template inline void erase(const iterator & it); /// change the size of the vector and allocate more memory if needed void resize(UInt size); /// change the number of components by interlacing data void extendComponentsInterlaced(UInt multiplicator, UInt stride); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; - // Vector& operator=(const Vector& vect); + // Vector& operator=(const Vector& vect); /// search elem in the vector, return the position of the first occurrence or /// -1 if not found Int find(const_reference elem) const; Int find(T elem[]) const; /// set a vvector to 0 inline void clear() { std::fill_n(values, size*nb_component, T()); }; /// copy the content of an other vector - void copy(const Vector & vect); + void copy(const Vector & vect); /// give the address of the memory allocated for this vector T * storage() const { return values; }; protected: /// perform the allocation for the constructors void allocate(UInt size, UInt nb_component = 1); /// resize without initializing the memory void resizeUnitialized(UInt new_size); /* ------------------------------------------------------------------------ */ /* Operators */ /* ------------------------------------------------------------------------ */ public: - Vector & operator-=(const Vector & vect); - Vector & operator+=(const Vector & vect); - Vector & operator*=(const T & alpha); + Vector & operator-=(const Vector & vect); + Vector & operator+=(const Vector & vect); + Vector & operator*=(const T & alpha); inline reference operator()(UInt i, UInt j = 0); inline const_reference operator()(UInt i, UInt j = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: UInt getSize() const{ return this->size; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: /// array of values T * values; // /!\ very dangerous }; __END_AKANTU__ #include "aka_types.hh" __BEGIN_AKANTU__ #include "aka_vector_tmpl.hh" - /* -------------------------------------------------------------------------- */ -/* Inline Functions Vector */ +/* Inline Functions Vector */ /* -------------------------------------------------------------------------- */ -template -inline std::ostream & operator<<(std::ostream & stream, const Vector & _this) +template +inline std::ostream & operator<<(std::ostream & stream, const Vector & _this) { _this.printself(stream); return stream; } /* -------------------------------------------------------------------------- */ /* Inline Functions VectorBase */ /* -------------------------------------------------------------------------- */ inline std::ostream & operator<<(std::ostream & stream, const VectorBase & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_VECTOR_HH__ */ diff --git a/src/common/aka_vector_tmpl.hh b/src/common/aka_vector_tmpl.hh index 09ec963be..ce06777b6 100644 --- a/src/common/aka_vector_tmpl.hh +++ b/src/common/aka_vector_tmpl.hh @@ -1,1085 +1,895 @@ /** * @file aka_vector_inline_impl.cc * @author Nicolas Richart * @date Thu Jul 15 00:09:33 2010 * * @brief Inline functions of the classes Vector and VectorBase * * @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 . * */ /* -------------------------------------------------------------------------- */ /* Inline Functions Vector */ /* -------------------------------------------------------------------------- */ __END_AKANTU__ #include __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ -template inline T & Vector::operator()(UInt i, UInt j) { +template +inline T & Vector::operator()(UInt i, UInt j) { AKANTU_DEBUG_ASSERT(size > 0, "The vector \"" << id << "\" is empty"); AKANTU_DEBUG_ASSERT((i < size) && (j < nb_component), "The value at position [" << i << "," << j << "] is out of range in vector \"" << id << "\""); return values[i*nb_component + j]; } /* -------------------------------------------------------------------------- */ -template inline const T & Vector::operator()(UInt i, UInt j) const { +template +inline const T & Vector::operator()(UInt i, UInt j) const { AKANTU_DEBUG_ASSERT(size > 0, "The vector \"" << id << "\" is empty"); AKANTU_DEBUG_ASSERT((i < size) && (j < nb_component), "The value at position [" << i << "," << j << "] is out of range in vector \"" << id << "\""); return values[i*nb_component + j]; } /* -------------------------------------------------------------------------- */ -template inline T & Vector::at(UInt i, UInt j) { +template +inline T & Vector::at(UInt i, UInt j) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(size > 0, "The vector is empty"); AKANTU_DEBUG_ASSERT((i < size) && (j < nb_component), "The value at position [" << i << "," << j << "] is out of range"); AKANTU_DEBUG_OUT(); return values[i*nb_component + j]; } /* -------------------------------------------------------------------------- */ -template inline const T & Vector::get(UInt i, UInt j) const{ +template +inline const T & Vector::get(UInt i, UInt j) const{ AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(size > 0, "The vector is empty"); AKANTU_DEBUG_ASSERT((i < size) && (j < nb_component), "The value at position [" << i << "," << j << "] is out of range"); AKANTU_DEBUG_OUT(); return values[i*nb_component + j]; } /* -------------------------------------------------------------------------- */ -template inline void Vector::push_back(const T & value) { +template +inline void Vector::push_back(const T & value) { // AKANTU_DEBUG_IN(); UInt pos = size; resizeUnitialized(size+1); /// @todo see if with std::uninitialized_fill it allow to build vector of objects std::uninitialized_fill_n(values + pos * nb_component, nb_component, value); // for (UInt i = 0; i < nb_component; ++i) { // values[pos*nb_component + i] = value; // } // AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template inline void Vector::push_back(const T new_elem[]) { +template +inline void Vector::push_back(const T new_elem[]) { // AKANTU_DEBUG_IN(); UInt pos = size; resizeUnitialized(size+1); T * tmp = values + nb_component * pos; std::uninitialized_copy(new_elem, new_elem + nb_component, tmp); // for (UInt i = 0; i < nb_component; ++i) { // values[pos*nb_component + i] = new_elem[i]; // } // AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template inline void Vector::erase(UInt i){ +template +template +inline void Vector::push_back(const Vector::iterator & it) { + UInt pos = size; + + resizeUnitialized(size+1); + + T * tmp = values + nb_component * pos; + T * new_elem = it.data(); + std::uninitialized_copy(new_elem, new_elem + nb_component, tmp); +} + +/* -------------------------------------------------------------------------- */ + + + + +/* -------------------------------------------------------------------------- */ +template +inline void Vector::erase(UInt i){ AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT((size > 0), "The vector is empty"); AKANTU_DEBUG_ASSERT((i < size), "The element at position [" << i << "] is out of range"); if(i != (size - 1)) { for (UInt j = 0; j < nb_component; ++j) { values[i*nb_component + j] = values[(size-1)*nb_component + j]; } } resize(size - 1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template -Vector & Vector::operator-=(const Vector & vect) { +template +Vector & Vector::operator-=(const Vector & vect) { AKANTU_DEBUG_ASSERT((size == vect.size) && (nb_component == vect.nb_component), "The too vector don't have the same sizes"); T * a = values; T * b = vect.values; for (UInt i = 0; i < size*nb_component; ++i) { *a -= *b; ++a;++b; } return *this; } /* -------------------------------------------------------------------------- */ -template -Vector & Vector::operator+=(const Vector & vect) { +template +Vector & Vector::operator+=(const Vector & vect) { AKANTU_DEBUG_ASSERT((size == vect.size) && (nb_component == vect.nb_component), "The too vector don't have the same sizes"); T * a = values; T * b = vect.values; for (UInt i = 0; i < size*nb_component; ++i) { *a++ += *b++; } return *this; } /* -------------------------------------------------------------------------- */ -template -Vector & Vector::operator*=(const T & alpha) { +template +Vector & Vector::operator*=(const T & alpha) { T * a = values; for (UInt i = 0; i < size*nb_component; ++i) { *a++ *= alpha; } return *this; } /* -------------------------------------------------------------------------- */ -/* Functions Vector */ +/* Functions Vector */ /* -------------------------------------------------------------------------- */ -template inline Vector::Vector (UInt size, - UInt nb_component, - const ID & id) : +template +Vector::Vector (UInt size, + UInt nb_component, + const ID & id) : VectorBase(id), values(NULL) { AKANTU_DEBUG_IN(); allocate(size, nb_component); - T val = T(); - std::uninitialized_fill(values, values + size*nb_component, val); + if(!is_scal) { + T val = T(); + std::uninitialized_fill(values, values + size*nb_component, val); + } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -#define AKANTU_CONSTRUCTOR_SPEC(type) \ - template<> inline Vector::Vector (UInt size, \ - UInt nb_component, \ - const ID & id) : \ - VectorBase(id), values(NULL) { \ - AKANTU_DEBUG_IN(); \ - allocate(size, nb_component); \ - AKANTU_DEBUG_OUT(); \ - } - -AKANTU_CONSTRUCTOR_SPEC(Real) -AKANTU_CONSTRUCTOR_SPEC(UInt) -AKANTU_CONSTRUCTOR_SPEC(Int) -AKANTU_CONSTRUCTOR_SPEC(bool) -#undef AKANTU_CONSTRUCTOR_SPEC - - -/* -------------------------------------------------------------------------- */ -template Vector::Vector (UInt size, - UInt nb_component, - const T def_values[], - const ID & id) : +template +Vector::Vector (UInt size, + UInt nb_component, + const T def_values[], + const ID & id) : VectorBase(id), values(NULL) { AKANTU_DEBUG_IN(); allocate(size, nb_component); T * tmp = values; for (UInt i = 0; i < size; ++i) { tmp = values + nb_component * i; std::uninitialized_copy(def_values, def_values + nb_component, tmp); // for (UInt j = 0; j < nb_component; ++j) { // values[i*nb_component + j] = def_values[j]; // } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template Vector::Vector (UInt size, - UInt nb_component, - const T & value, - const ID & id) : +template +Vector::Vector (UInt size, + UInt nb_component, + const T & value, + const ID & id) : VectorBase(id), values(NULL) { AKANTU_DEBUG_IN(); allocate(size, nb_component); std::uninitialized_fill_n(values, size*nb_component, value); // for (UInt i = 0; i < nb_component*size; ++i) { // values[i] = value; // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template Vector::Vector(const Vector& vect, bool deep, const ID & id) { +template +Vector::Vector(const Vector & vect, + bool deep, + const ID & id) { AKANTU_DEBUG_IN(); this->id = (id == "") ? vect.id : id; if (deep) { allocate(vect.size, vect.nb_component); T * tmp = values; std::uninitialized_copy(vect.values, vect.values + size * nb_component, tmp); // for (UInt i = 0; i < size; ++i) { // for (UInt j = 0; j < nb_component; ++j) { // values[i*nb_component + j] = vect.values[i*nb_component + j]; // } // } } else { this->values = vect.values; this->size = vect.size; this->nb_component = vect.nb_component; this->allocated_size = vect.allocated_size; this->size_of_type = vect.size_of_type; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template Vector::Vector(const std::vector& vect) { +template +Vector::Vector(const std::vector& vect) { AKANTU_DEBUG_IN(); this->id = ""; allocate(vect.size(), 1); T * tmp = values; std::uninitialized_copy(&(vect[0]), &(vect[size-1]), tmp); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template inline Vector::~Vector () { +template +Vector::~Vector () { AKANTU_DEBUG_IN(); AKANTU_DEBUG(dblAccessory, "Freeing " << allocated_size*nb_component*sizeof(T) / 1024. << "kB (" << id <<")"); if(values){ - for (UInt i = 0; i < size * nb_component; ++i) { - T * obj = values+i; - obj->~T(); - } + if(!is_scal) + for (UInt i = 0; i < size * nb_component; ++i) { + T * obj = values+i; + obj->~T(); + } free(values); } size = allocated_size = 0; AKANTU_DEBUG_OUT(); } -/* -------------------------------------------------------------------------- */ -#define AKANTU_DESTRUCTOR_SPEC(type) \ - template<> inline Vector::~Vector () { \ - AKANTU_DEBUG_IN(); \ - AKANTU_DEBUG(dblAccessory, "Freeing " \ - << allocated_size*nb_component*sizeof(type) / 1024. \ - << "kB (" << id <<")"); \ - if(values) free(values); \ - size = allocated_size = 0; \ - AKANTU_DEBUG_OUT(); \ - } -AKANTU_DESTRUCTOR_SPEC(Real) -AKANTU_DESTRUCTOR_SPEC(UInt) -AKANTU_DESTRUCTOR_SPEC(Int) -AKANTU_DESTRUCTOR_SPEC(bool) -#undef AKANTU_DESTRUCTOR_SPEC /* -------------------------------------------------------------------------- */ -template void Vector::allocate(UInt size, - UInt nb_component) { +template +void Vector::allocate(UInt size, + UInt nb_component) { AKANTU_DEBUG_IN(); if (size == 0){ values = NULL; } else { values = static_cast(malloc(nb_component * size * sizeof(T))); AKANTU_DEBUG_ASSERT(values != NULL, "Cannot allocate " << nb_component * size * sizeof(T) / 1024. << "kB (" << id <<")"); } if (values == NULL) { this->size = this->allocated_size = 0; } else { AKANTU_DEBUG(dblAccessory, "Allocated " << size * nb_component * sizeof(T) / 1024. << "kB (" << id <<")"); this->size = this->allocated_size = size; } this->size_of_type = sizeof(T); this->nb_component = nb_component; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template -void Vector::resize(UInt new_size) { +template +void Vector::resize(UInt new_size) { UInt old_size = size; T * old_values = values; if(new_size < size) { for (UInt i = new_size * nb_component; i < size * nb_component; ++i) { T * obj = old_values+i; obj->~T(); } } resizeUnitialized(new_size); T val = T(); if(size > old_size) std::uninitialized_fill(values + old_size*nb_component, values + size*nb_component, val); } /* -------------------------------------------------------------------------- */ -template -void Vector::resizeUnitialized(UInt new_size) { +template +void Vector::resizeUnitialized(UInt new_size) { // AKANTU_DEBUG_IN(); // free some memory if(new_size <= allocated_size) { if(allocated_size - new_size > AKANTU_MIN_ALLOCATION) { AKANTU_DEBUG(dblAccessory, "Freeing " << (allocated_size - size)*nb_component*sizeof(T) / 1024. << "kB (" << id <<")"); // Normally there are no allocation problem when reducing an array T * tmp_ptr = static_cast(realloc(values, new_size * nb_component * sizeof(T))); if(new_size != 0 && tmp_ptr == NULL) { AKANTU_DEBUG_ERROR("Cannot free data (" << id << ")" << " [current allocated size : " << allocated_size << " | " << "requested size : " << new_size << "]"); } values = tmp_ptr; allocated_size = new_size; } size = new_size; // AKANTU_DEBUG_OUT(); return; } // allocate more memory UInt size_to_alloc = (new_size - allocated_size < AKANTU_MIN_ALLOCATION) ? allocated_size + AKANTU_MIN_ALLOCATION : new_size; T *tmp_ptr = static_cast(realloc(values, size_to_alloc * nb_component * sizeof(T))); AKANTU_DEBUG_ASSERT(tmp_ptr != NULL, "Cannot allocate " << size_to_alloc * nb_component * sizeof(T) / 1024. << "kB"); if (tmp_ptr == NULL) { AKANTU_DEBUG_ERROR("Cannot allocate more data (" << id << ")" << " [current allocated size : " << allocated_size << " | " << "requested size : " << new_size << "]"); } AKANTU_DEBUG(dblAccessory, "Allocating " << (size_to_alloc - allocated_size)*nb_component*sizeof(T) / 1024. << "kB"); allocated_size = size_to_alloc; size = new_size; values = tmp_ptr; // AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template void Vector::extendComponentsInterlaced(UInt multiplicator, - UInt block_size) { +template +void Vector::extendComponentsInterlaced(UInt multiplicator, + UInt block_size) { AKANTU_DEBUG_IN(); if (multiplicator == 1) return; AKANTU_DEBUG_ASSERT(multiplicator > 1, "invalid multiplicator"); AKANTU_DEBUG_ASSERT(nb_component%block_size == 0, "stride must divide actual number of components"); values = static_cast(realloc(values, nb_component*multiplicator*size* sizeof(T))); UInt new_component = nb_component/block_size * multiplicator; for (UInt i = 0,k=size-1; i < size; ++i,--k) { for (UInt j = 0; j < new_component; ++j) { UInt m = new_component - j -1; UInt n = m/multiplicator; for (UInt l = 0,p=block_size-1; l < block_size; ++l,--p) { values[k*nb_component*multiplicator+m*block_size+p] = values[k*nb_component+n*block_size+p]; } } } nb_component = nb_component * multiplicator; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template Int Vector::find(const T & elem) const { +template +Int Vector::find(const T & elem) const { AKANTU_DEBUG_IN(); UInt i = 0; for (; (i < size) && (values[i] != elem); ++i); AKANTU_DEBUG_OUT(); return (i == size) ? -1 : (Int) i; } /* -------------------------------------------------------------------------- */ -template Int Vector::find(T elem[]) const { +template +Int Vector::find(T elem[]) const { AKANTU_DEBUG_IN(); T * it = values; UInt i = 0; UInt c = 0; for (;i < size && (c != nb_component); ++i) { c = 0; T * cit = it; T * celem = elem; for(; (c < nb_component) && (*cit == *celem); ++c, ++cit, ++celem); it += nb_component; } AKANTU_DEBUG_OUT(); return (i == size) ? -1 : (Int) i; } /* -------------------------------------------------------------------------- */ -template void Vector::copy(const Vector& vect) { +template +void Vector::copy(const Vector& vect) { AKANTU_DEBUG_IN(); if(AKANTU_DEBUG_TEST(dblWarning)) if(vect.nb_component != nb_component) { AKANTU_DEBUG(dblWarning, "The two vectors do not have the same number of components"); } // this->id = vect.id; resize((vect.size * vect.nb_component) / nb_component); T * tmp = values; std::uninitialized_copy(vect.values, vect.values + size * nb_component, tmp); // memcpy(this->values, vect.values, vect.size * vect.nb_component * sizeof(T)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template -void Vector::printself(std::ostream & stream, int indent) const { +template +void Vector::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); Real real_size = allocated_size * nb_component * size_of_type / 1024.0; std::streamsize prec = stream.precision(); std::ios_base::fmtflags ff = stream.flags(); stream.setf (std::ios_base::showbase); stream.precision(2); stream << space << "Vector<" << debug::demangle(typeid(T).name()) << "> [" << std::endl; stream << space << " + id : " << this->id << std::endl; stream << space << " + size : " << this->size << std::endl; stream << space << " + nb_component : " << this->nb_component << std::endl; stream << space << " + allocated size : " << this->allocated_size << std::endl; stream << space << " + memory size : " << real_size << "kB" << std::endl; if(!AKANTU_DEBUG_LEVEL_IS_TEST()) stream << space << " + address : " << std::hex << this->values << std::dec << std::endl; stream.precision(prec); stream.flags(ff); if(AKANTU_DEBUG_TEST(dblDump)) { stream << space << " + values : {"; for (UInt i = 0; i < this->size; ++i) { stream << "{"; for (UInt j = 0; j < this->nb_component; ++j) { stream << this->values[i*nb_component + j]; if(j != this->nb_component - 1) stream << ", "; } stream << "}"; if(i != this->size - 1) stream << ", "; } stream << "}" << std::endl; } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ /* Inline Functions VectorBase */ /* -------------------------------------------------------------------------- */ inline UInt VectorBase::getMemorySize() const { return allocated_size * nb_component * size_of_type; } inline void VectorBase::empty() { size = 0; } -/** \todo change definition of iterators - template - template - - template - template::isScalar > - class Vector::iterator_internal : public std::iterator { -*/ - /* -------------------------------------------------------------------------- */ /* Iterators */ /* -------------------------------------------------------------------------- */ -template -template -//class Vector::iterator_internal : public virtual std::iterator { -class Vector::iterator_internal { +template +template +class Vector::iterator_internal { public: - typedef R value_type; - typedef R* pointer; - typedef R& reference; - typedef IR internal_value_type; - typedef IR* internal_pointer; -protected: - iterator_internal(UInt offset, pointer_type data, pointer ret) : offset(offset), - initial(data), - ret(ret) { - } - - virtual ~iterator_internal() { delete ret; }; + typedef R value_type; + typedef R* pointer; + typedef R& reference; + typedef IR internal_value_type; + typedef IR* internal_pointer; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; public: iterator_internal() : offset(0), initial(NULL), ret(NULL) {}; iterator_internal(pointer_type data, UInt offset) : offset(offset), initial(data), ret(new value_type(data)) { AKANTU_DEBUG_ASSERT(offset == ret->size(), "The iterator_internal is not compatible with the type " << typeid(value_type).name()); } iterator_internal(pointer warped) : offset(warped->size()), initial(warped->storage()), ret(const_cast(warped)) { } iterator_internal(const iterator_internal & it) { if(this != &it) { this->offset = it.offset; this->initial = it.initial; this->ret = new internal_value_type(*it.ret); } } + virtual ~iterator_internal() { delete ret; }; + inline iterator_internal & operator=(const iterator_internal & it) { if(this != &it) { this->offset = it.offset; this->initial = it.initial; if(this->ret) this->ret->shallowCopy(*it.ret); else this->ret = new internal_value_type(*it.ret); } return *this; } inline reference operator*() { return *ret; }; inline pointer operator->() { return ret; }; inline iterator_internal & operator++() { ret->values += offset; return *this; }; + inline iterator_internal & operator--() { ret->values -= offset; return *this; }; - inline iterator_internal & operator+=(const UInt n) { - ret->values += offset * n; - return *this; - } + inline iterator_internal & operator+=(const UInt n) { ret->values += offset * n; return *this; } + inline iterator_internal & operator-=(const UInt n) { ret->values -= offset * n; return *this; } - inline reference operator[](const UInt n) { - ret->values = initial + n*offset; - return *ret; - } + inline reference operator[](const UInt n) { ret->values = initial + n*offset; return *ret; } - inline bool operator==(const iterator_internal & other) { - return (*this).ret->values == other.ret->values; - } - inline bool operator!=(const iterator_internal & other) { - return (*this).ret->values != other.ret->values; - } + inline bool operator==(const iterator_internal & other) { return (*this).ret->values == other.ret->values; } + inline bool operator!=(const iterator_internal & other) { return (*this).ret->values != other.ret->values; } + inline bool operator <(const iterator_internal & other) { return (*this).ret->values < other.ret->values; } + inline bool operator<=(const iterator_internal & other) { return (*this).ret->values <= other.ret->values; } + inline bool operator> (const iterator_internal & other) { return (*this).ret->values > other.ret->values; } + inline bool operator>=(const iterator_internal & other) { return (*this).ret->values >= other.ret->values; } + + inline iterator_internal operator+(difference_type n) { iterator_internal tmp(*this); tmp += n; return tmp; } + inline iterator_internal operator-(difference_type n) { iterator_internal tmp(*this); tmp -= n; return tmp; } + + + inline difference_type operator-(const iterator_internal & b) { return ret->values - b.ret->values; } - inline pointer_type getCurrentStorage() const { + + inline pointer_type data() const { return ret->storage(); } protected: UInt offset; pointer_type initial; internal_pointer ret; }; - -// /* -------------------------------------------------------------------------- */ -// template -// template -// inline Vector::iterator Vector::begin() { -// return iterator(values, nb_component); -// } - -// /* -------------------------------------------------------------------------- */ -// template -// template -// inline Vector::iterator Vector::end() { -// return iterator(values + nb_component * size, nb_component); -// } - /* -------------------------------------------------------------------------- */ -template -inline Vector::iterator< types::Vector > Vector::begin(UInt n) { +template +inline Vector::iterator< types::Vector > Vector::begin(UInt n) { AKANTU_DEBUG_ASSERT(nb_component == n, "The iterator is not compatible with the type Vector(" << n<< ")"); return iterator< types::Vector >(new types::Vector(values, n)); } /* -------------------------------------------------------------------------- */ -template -inline Vector::iterator< types::Vector > Vector::end(UInt n) { +template +inline Vector::iterator< types::Vector > Vector::end(UInt n) { AKANTU_DEBUG_ASSERT(nb_component == n, "The iterator is not compatible with the type Vector(" << n<< ")"); return iterator< types::Vector >(new types::Vector(values + nb_component * size, n)); } /* -------------------------------------------------------------------------- */ -template -inline Vector::const_iterator< types::Vector > Vector::begin(UInt n) const { +template +inline Vector::const_iterator< types::Vector > Vector::begin(UInt n) const { AKANTU_DEBUG_ASSERT(nb_component == n, "The iterator is not compatible with the type Vector(" << n<< ")"); return const_iterator< types::Vector >(new types::Vector(values, n)); } /* -------------------------------------------------------------------------- */ -template -inline Vector::const_iterator< types::Vector > Vector::end(UInt n) const { +template +inline Vector::const_iterator< types::Vector > Vector::end(UInt n) const { AKANTU_DEBUG_ASSERT(nb_component == n, "The iterator is not compatible with the type Vector(" << n<< ")"); return const_iterator< types::Vector >(new types::Vector(values + nb_component * size, n)); } /* -------------------------------------------------------------------------- */ template<> inline Vector::iterator Vector::begin(UInt m, UInt n) { AKANTU_DEBUG_ASSERT(nb_component == n*m, "The iterator is not compatible with the type Matrix(" << m << "," << n<< ")"); return iterator< types::Matrix >(new types::Matrix(values, m, n)); } /* -------------------------------------------------------------------------- */ template<> inline Vector::iterator Vector::end(UInt m, UInt n) { AKANTU_DEBUG_ASSERT(nb_component == n*m, "The iterator is not compatible with the type Matrix(" << m << "," << n<< ")"); return iterator(new types::Matrix(values + nb_component * size, m, n)); } /* -------------------------------------------------------------------------- */ template<> inline Vector::const_iterator Vector::begin(UInt m, UInt n) const { AKANTU_DEBUG_ASSERT(nb_component == n*m, "The iterator is not compatible with the type Matrix(" << m << "," << n<< ")"); return const_iterator< types::Matrix >(new types::Matrix(values, m, n)); } /* -------------------------------------------------------------------------- */ template<> inline Vector::const_iterator Vector::end(UInt m, UInt n) const { AKANTU_DEBUG_ASSERT(nb_component == n*m, "The iterator is not compatible with the type Matrix(" << m << "," << n<< ")"); return const_iterator(new types::Matrix(values + nb_component * size, m, n)); } /* -------------------------------------------------------------------------- */ template<> inline Vector::iterator< types::Matrix > Vector::begin_reinterpret(UInt m, UInt n, __attribute__((unused)) UInt size, __attribute__((unused)) UInt nb_component) { AKANTU_DEBUG_ASSERT(nb_component * size == this->nb_component * this->size, "The new values for size (" << size << ") and nb_component (" << nb_component << ") are not compatible with the one of this vector"); AKANTU_DEBUG_ASSERT(nb_component == n*m, "The iterator is not compatible with the type Matrix(" << m << "," << n<< ")"); return iterator< types::Matrix >(new types::Matrix(values + nb_component * 0, m, n)); } /* -------------------------------------------------------------------------- */ template<> inline Vector::iterator< types::Matrix > Vector::end_reinterpret(UInt m, UInt n, UInt size, UInt nb_component) { AKANTU_DEBUG_ASSERT(nb_component * size == this->nb_component * this->size, "The new values for size (" << size << ") and nb_component (" << nb_component << ") are not compatible with the one of this vector"); AKANTU_DEBUG_ASSERT(nb_component == n*m, "The iterator is not compatible with the type Matrix(" << m << "," << n<< ")"); return iterator(new types::Matrix(values + nb_component * size, m, n)); } /* -------------------------------------------------------------------------- */ template<> inline Vector::const_iterator< types::Matrix > Vector::begin_reinterpret(UInt m, UInt n, __attribute__((unused)) UInt size, __attribute__((unused)) UInt nb_component) const { AKANTU_DEBUG_ASSERT(nb_component * size == this->nb_component * this->size, "The new values for size (" << size << ") and nb_component (" << nb_component << ") are not compatible with the one of this vector"); AKANTU_DEBUG_ASSERT(nb_component == n*m, "The iterator is not compatible with the type Matrix(" << m << "," << n<< ")"); return const_iterator< types::Matrix >(new types::Matrix(values + nb_component * 0, m, n)); } /* -------------------------------------------------------------------------- */ template<> inline Vector::const_iterator< types::Matrix > Vector::end_reinterpret(UInt m, UInt n, UInt size, UInt nb_component) const { AKANTU_DEBUG_ASSERT(nb_component * size == this->nb_component * this->size, "The new values for size (" << size << ") and nb_component (" << nb_component << ") are not compatible with the one of this vector"); AKANTU_DEBUG_ASSERT(nb_component == n*m, "The iterator is not compatible with the type Matrix(" << m << "," << n<< ")"); return const_iterator(new types::Matrix(values + nb_component * size, m, n)); } -// template -// template -// inline typename Vector::template iterator_internal & Vector::iterator_internal::operator++() { -// ret += offset; -// return *this; -// } - -// inline iterator_internal & operator+=(const UInt n) { -// ret->values += offset * n; -// return *this; -// } /* -------------------------------------------------------------------------- */ /** * Specialization for scalar types */ - -/* If gcc < 4.4 some problem with detection of specialization of a template by - * an other template so I have copied the code, that is really ugly just to help - * the compiler. This part of code should be removed if version of gcc before * - * 4.4 are note supported anymore. Problems for know appears on Mac OS with gcc - * version is 4.2.1 - */ -#if (__GNUC__ < 4) || \ - ((__GNUC__ == 4) && (__GNUC_MINOR__ < 4)) - -#define specialize_internal_iterator_for_scalar(T) \ - template <> \ - template <> \ - class Vector::iterator_internal { \ - public: \ - typedef T value_type; \ - typedef T* pointer; \ - typedef T& reference; \ - typedef T internal_value_type; \ - typedef T* internal_pointer; \ - protected: \ - iterator_internal(__attribute__((unused)) UInt offset, \ - pointer data, pointer ret) : \ - initial(data), \ - ret(ret) { \ - AKANTU_DEBUG_ASSERT(offset == 1, \ - "The iterator is not compatible with the type " \ - << typeid(value_type).name()); \ - } \ - \ - public: \ - iterator_internal() : initial(NULL), ret(NULL) {}; \ - \ - iterator_internal(pointer data, \ - __attribute__((unused)) UInt offset) : \ - initial(data), \ - ret(data) { \ - AKANTU_DEBUG_ASSERT(offset == 1, \ - "The iterator is not compatible with the type " \ - << typeid(value_type).name()); \ - }; \ - \ - iterator_internal(const iterator_internal & it) { \ - if(this != &it) { \ - this->initial = it.initial; \ - this->ret = new internal_value_type(*it.ret); \ - } \ - } \ - \ - virtual ~iterator_internal() { }; \ - \ - inline iterator_internal & operator=(const iterator_internal & it) { \ - if(this != &it) { \ - this->initial = it.initial; \ - this->ret = it.ret; \ - } \ - return *this; \ - } \ - \ - inline reference operator*() { return *ret; }; \ - inline pointer operator->() { return ret; }; \ - inline iterator_internal & operator++() { ++ret; return *this; }; \ - \ - inline iterator_internal & operator+=(const UInt n) { \ - ret += n; \ - return *this; \ - } \ - \ - inline reference operator[](const UInt n) { \ - ret = initial + n; \ - return *ret; \ - } \ - \ - inline bool operator==(const iterator_internal & other) { \ - return (*this).ret == other.ret; \ - } \ - inline bool operator!=(const iterator_internal & other) { \ - return (*this).ret != other.ret; \ - } \ - \ - inline iterator_internal & operator-(size_t n) { \ - ret -= n; \ - return *this; \ - } \ - \ - inline size_t operator-(const iterator_internal & b) { \ - return ret - b.getCurrentStorage(); \ - } \ - \ - inline pointer getCurrentStorage() const { \ - return ret; \ - } \ - \ - protected: \ - pointer initial; \ - pointer ret; \ - } - -specialize_internal_iterator_for_scalar(Real); -specialize_internal_iterator_for_scalar(UInt); - -#else -template -template -class Vector::iterator_internal : public std::iterator{ +template +template +class Vector::iterator_internal { public: - typedef T value_type; - typedef T* pointer; - typedef T& reference; - typedef T internal_value_type; - typedef T* internal_pointer; -protected: - iterator_internal(UInt offset, pointer data, pointer ret) : - initial(data), - ret(ret) { } + typedef R value_type; + typedef R* pointer; + typedef R& reference; + typedef IR internal_value_type; + typedef IR* internal_pointer; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; public: - iterator_internal() : initial(NULL), ret(NULL) {}; - - iterator_internal(pointer data, UInt offset) : - initial(data), - ret(data) { - AKANTU_DEBUG_ASSERT(offset == 1, - "The iterator_internal is not compatible with the type " - << typeid(value_type).name()); - }; - + iterator_internal(pointer data = NULL, UInt offset = 1) : ret(data), initial(data) { }; iterator_internal(const iterator_internal & it) { - if(this != &it) { - this->initial = it.initial; - this->ret = new internal_value_type(*it.ret); - } + if(this != &it) { this->ret = it.ret; this->initial = it.initial; } } virtual ~iterator_internal() { }; - inline iterator_internal & operator=(const iterator_internal & it) { - if(this != &it) { - this->initial = it.initial; - this->ret = it.ret; - } - return *this; - } + inline iterator_internal & operator=(const iterator_internal & it) + { if(this != &it) { this->ret = it.ret; this->initial = it.initial; } return *this; } inline reference operator*() { return *ret; }; inline pointer operator->() { return ret; }; inline iterator_internal & operator++() { ++ret; return *this; }; inline iterator_internal & operator--() { --ret; return *this; }; - inline iterator_internal & operator+=(const UInt n) { - ret += n; - return *this; - } + inline iterator_internal & operator+=(const UInt n) { ret += n; return *this; } + inline iterator_internal & operator-=(const UInt n) { ret -= n; return *this; } - inline reference operator[](const UInt n) { - ret = initial + n; - return *ret; - } - - inline bool operator==(const iterator_internal & other) { - return (*this).ret == other.ret; - } - inline bool operator!=(const iterator_internal & other) { - return (*this).ret != other.ret; - } - - inline bool operator<(const iterator_internal & other) { - return ret < other.ret; - } + inline reference operator[](const UInt n) { ret = initial + n; return *ret; } - inline bool operator<=(const iterator_internal & other) { - return ret <= other.ret; - } - - inline bool operator>(const iterator_internal & other) { - return ret > other.ret; - } + inline bool operator==(const iterator_internal & other) { return ret == other.ret; } + inline bool operator!=(const iterator_internal & other) { return ret != other.ret; } + inline bool operator< (const iterator_internal & other) { return ret < other.ret; } + inline bool operator<=(const iterator_internal & other) { return ret <= other.ret; } + inline bool operator> (const iterator_internal & other) { return ret > other.ret; } + inline bool operator>=(const iterator_internal & other) { return ret >= other.ret; } - inline bool operator>=(const iterator_internal & other) { - return ret >= other.ret; - } + inline iterator_internal operator-(difference_type n) { return iterator_internal(ret - n); } + inline iterator_internal operator+(difference_type n) { return iterator_internal(ret + n); } + inline difference_type operator-(const iterator_internal & b) { return ret - b.ret; } - inline iterator_internal & operator-(size_t n) { - ret -= n; - return *this; - } - - inline size_t operator-(const iterator_internal & b) { - return ret - b.getCurrentStorage(); - } - - inline iterator_internal & operator+(size_t n) { - ret += n; - return *this; - } - - inline pointer getCurrentStorage() const { - return ret; - } + inline pointer data() const { return ret; } protected: - pointer initial; pointer ret; + pointer initial; }; -#endif /* -------------------------------------------------------------------------- */ -template +template template -inline void Vector::erase(const iterator & it) { +inline void Vector::erase(const iterator & it) { T * curr = it.getCurrentStorage(); UInt pos = (curr - values) / nb_component; erase(pos); } -// inline reference operator[](const UInt n) { -// ret->values = initial + n*offset; -// return *ret; -// } - - /* -------------------------------------------------------------------------- */ -template -inline Vector::iterator Vector::begin() { - return iterator(values, 1); +template +inline Vector::iterator Vector::begin() { + return iterator(values); } /* -------------------------------------------------------------------------- */ -template -inline Vector::iterator Vector::end() { - return iterator(values + nb_component * size, 1); +template +inline Vector::iterator Vector::end() { + return iterator(values + size); } /* -------------------------------------------------------------------------- */ -template -inline Vector::const_iterator Vector::begin() const { - return const_iterator(values, 1); +template +inline Vector::const_iterator Vector::begin() const { + return const_iterator(values); } /* -------------------------------------------------------------------------- */ -template -inline Vector::const_iterator Vector::end() const { - return const_iterator(values + nb_component * size, 1); +template +inline Vector::const_iterator Vector::end() const { + return const_iterator(values + size); } diff --git a/src/fem/by_element_type_tmpl.hh b/src/fem/by_element_type_tmpl.hh index 29b1f6a33..c96c3b901 100644 --- a/src/fem/by_element_type_tmpl.hh +++ b/src/fem/by_element_type_tmpl.hh @@ -1,367 +1,368 @@ /** * @file by_element_type_inline_impl.cc * @author Nicolas Richart * @date Thu Aug 4 14:41:29 2011 * * @brief * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* ByElementType */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template inline std::string ByElementType::printType(const ElementType & type, const GhostType & ghost_type) { std::stringstream sstr; sstr << "(" << ghost_type << ":" << type << ")"; return sstr.str(); } /* -------------------------------------------------------------------------- */ template inline bool ByElementType::exists(ElementType type, GhostType ghost_type) const { return this->getData(ghost_type).find(type) != this->getData(ghost_type).end(); } /* -------------------------------------------------------------------------- */ template inline const Stored & ByElementType::operator()(const ElementType & type, const GhostType & ghost_type) const { typename DataMap::const_iterator it = this->getData(ghost_type).find(type); if(it == this->getData(ghost_type).end()) AKANTU_EXCEPTION("No element of type " << ByElementType::printType(type, ghost_type) << " in this ByElementType<" << debug::demangle(typeid(Stored).name()) << "> class"); return it->second; } /* -------------------------------------------------------------------------- */ template inline Stored & ByElementType::operator()(const ElementType & type, const GhostType & ghost_type) { typename DataMap::iterator it = this->getData(ghost_type).find(type); // if(it == this->getData(ghost_type).end()) // AKANTU_EXCEPTION("No element of type " // << ByElementType::printType(type, ghost_type) // << " in this ByElementType<" // << debug::demangle(typeid(Stored).name()) << "> class"); if(it == this->getData(ghost_type).end()) { DataMap & data = this->getData(ghost_type); const std::pair & res = data.insert(std::pair(type, Stored())); it = res.first; } return it->second; } /* -------------------------------------------------------------------------- */ template inline Stored & ByElementType::operator()(const Stored & insert, const ElementType & type, const GhostType & ghost_type) { typename DataMap::iterator it = this->getData(ghost_type).find(type); if(it != this->getData(ghost_type).end()) { AKANTU_EXCEPTION("Element of type " << ByElementType::printType(type, ghost_type) << " already in this ByElementType<" << debug::demangle(typeid(Stored).name()) << "> class"); } else { DataMap & data = this->getData(ghost_type); const std::pair & res = data.insert(std::pair(type, insert)); it = res.first; } return it->second; } /* -------------------------------------------------------------------------- */ template inline typename ByElementType::DataMap & ByElementType::getData(GhostType ghost_type) { if(ghost_type == _not_ghost) return data; else return ghost_data; } /* -------------------------------------------------------------------------- */ template inline const typename ByElementType::DataMap & ByElementType::getData(GhostType ghost_type) const { if(ghost_type == _not_ghost) return data; else return ghost_data; } /* -------------------------------------------------------------------------- */ /// Works only if stored is a pointer to a class with a printself method template void ByElementType::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "ByElementType<" << debug::demangle(typeid(Stored).name()) << "> [" << std::endl; for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; const DataMap & data = getData(gt); typename DataMap::const_iterator it; for(it = data.begin(); it != data.end(); ++it) { stream << space << space << ByElementType::printType(it->first, gt) << " [" << std::endl; it->second->printself(stream, indent + 3); } } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ template ByElementType::ByElementType(const ID & id, const ID & parent_id) { AKANTU_DEBUG_IN(); std::stringstream sstr; if(parent_id != "") sstr << parent_id << ":"; sstr << id; this->id = sstr.str(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template ByElementType::~ByElementType() { } /* -------------------------------------------------------------------------- */ template inline Vector & ByElementTypeVector::alloc(UInt size, UInt nb_component, const ElementType & type, const GhostType & ghost_type) { std::string ghost_id = ""; if (ghost_type == _ghost) ghost_id = ":ghost"; Vector * tmp; typename ByElementTypeVector::DataMap::iterator it = this->getData(ghost_type).find(type); if(it == this->getData(ghost_type).end()) { std::stringstream sstr; sstr << this->id << ":" << type << ghost_id; tmp = &(Memory::alloc(sstr.str(), size, nb_component, T())); std::stringstream sstrg; sstrg << ghost_type; tmp->setTag(sstrg.str()); this->getData(ghost_type)[type] = tmp; } else { AKANTU_DEBUG_INFO("The vector " << this->id << this->printType(type, ghost_type) << " already exists, it is resized instead of allocated."); tmp = it->second; it->second->resize(size); } return *tmp; } /* -------------------------------------------------------------------------- */ template inline void ByElementTypeVector::alloc(UInt size, UInt nb_component, const ElementType & type) { this->alloc(size, nb_component, type, _not_ghost); this->alloc(size, nb_component, type, _ghost); } /* -------------------------------------------------------------------------- */ template inline void ByElementTypeVector::free() { AKANTU_DEBUG_IN(); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; const DataMap & data = this->getData(gt); typename DataMap::const_iterator it; for(it = data.begin(); it != data.end(); ++it) { dealloc(it->second->getID()); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template inline const Vector & ByElementTypeVector::operator()(const ElementType & type, const GhostType & ghost_type) const { typename ByElementTypeVector::DataMap::const_iterator it = this->getData(ghost_type).find(type); if(it == this->getData(ghost_type).end()) AKANTU_EXCEPTION("No element of type " << ByElementTypeVector::printType(type, ghost_type) << " in this ByElementTypeVector<" - << debug::demangle(typeid(T).name()) << "> class"); + << debug::demangle(typeid(T).name()) << "> class(\"" + << this->id << "\")"); return *(it->second); } /* -------------------------------------------------------------------------- */ template inline Vector & ByElementTypeVector::operator()(const ElementType & type, const GhostType & ghost_type) { typename ByElementTypeVector::DataMap::iterator it = this->getData(ghost_type).find(type); if(it == this->getData(ghost_type).end()) AKANTU_EXCEPTION("No element of type " << ByElementTypeVector::printType(type, ghost_type) << " in this ByElementTypeVector<" << debug::demangle(typeid(T).name()) << "> class (\"" << this->id << "\")"); return *(it->second); } /* -------------------------------------------------------------------------- */ template inline void ByElementTypeVector::setVector(const ElementType & type, const GhostType & ghost_type, const Vector & vect) { typename ByElementTypeVector::DataMap::iterator it = this->getData(ghost_type).find(type); if(AKANTU_DEBUG_TEST(dblWarning) && it != this->getData(ghost_type).end() && it->second != &vect) { AKANTU_DEBUG_WARNING("The Vector " << this->printType(type, ghost_type) << " is already registred, this call can lead to a memory leak."); } this->getData(ghost_type)[type] = &(const_cast &>(vect)); } /* -------------------------------------------------------------------------- */ /* ElementType Iterator */ /* -------------------------------------------------------------------------- */ template ByElementType::type_iterator::type_iterator(DataMapIterator & list_begin, DataMapIterator & list_end, UInt dim, ElementKind ek) : list_begin(list_begin), list_end(list_end), dim(dim), kind(ek) { } /* -------------------------------------------------------------------------- */ template ByElementType::type_iterator::type_iterator(const type_iterator & it) : list_begin(it.list_begin), list_end(it.list_end), dim(it.dim), kind(it.kind) { } /* -------------------------------------------------------------------------- */ template inline typename ByElementType::type_iterator::reference ByElementType::type_iterator::operator*() { return list_begin->first; } /* -------------------------------------------------------------------------- */ template inline typename ByElementType::type_iterator & ByElementType::type_iterator::operator++() { ++list_begin; while((list_begin != list_end) && (((dim != 0) && (dim != Mesh::getSpatialDimension(list_begin->first))) || ((kind != _ek_not_defined) && (kind != Mesh::getKind(list_begin->first))))) ++list_begin; return *this; } /* -------------------------------------------------------------------------- */ template typename ByElementType::type_iterator ByElementType::type_iterator::operator++(int) { type_iterator tmp(*this); operator++(); return tmp; } /* -------------------------------------------------------------------------- */ template inline bool ByElementType::type_iterator::operator==(const type_iterator & other) { return this->list_begin == other.list_begin; } /* -------------------------------------------------------------------------- */ template inline bool ByElementType::type_iterator::operator!=(const type_iterator & other) { return this->list_begin != other.list_begin; } /* -------------------------------------------------------------------------- */ template inline typename ByElementType::type_iterator ByElementType::firstType(UInt dim, GhostType ghost_type, ElementKind kind) const { typename DataMap::const_iterator b,e; if(ghost_type == _not_ghost) { b = data.begin(); e = data.end(); } else { b = ghost_data.begin(); e = ghost_data.end(); } // loop until the first valid type while((b != e) && (((dim != 0) && (dim != Mesh::getSpatialDimension(b->first))) || ((kind != _ek_not_defined) && (kind != Mesh::getKind(b->first))))) ++b; return typename ByElementType::type_iterator(b, e, dim, kind); } /* -------------------------------------------------------------------------- */ template inline typename ByElementType::type_iterator ByElementType::lastType(UInt dim, GhostType ghost_type, ElementKind kind) const { typename DataMap::const_iterator e; if(ghost_type == _not_ghost) { e = data.end(); } else { e = ghost_data.end(); } return typename ByElementType::type_iterator(e, e, dim, kind); } diff --git a/src/fem/fem.hh b/src/fem/fem.hh index be38d88f9..b499aebc2 100644 --- a/src/fem/fem.hh +++ b/src/fem/fem.hh @@ -1,330 +1,335 @@ /** * @file fem.hh * @author Nicolas Richart * @date Fri Jul 16 10:24:24 2010 * * @brief FEM class * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_FEM_HH__ #define __AKANTU_FEM_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "mesh.hh" #include "element_class.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ - +namespace akantu { + class Integrator; + class ShapeFunctions; +} __BEGIN_AKANTU__ class QuadraturePoint : public Element { public: QuadraturePoint(ElementType type = _not_defined, UInt element = 0, UInt num_point = 0, GhostType ghost_type = _not_ghost) : Element(type, element, ghost_type), num_point(num_point), global_num(0), position((Real *)NULL, 0) { }; QuadraturePoint(UInt element, UInt num_point, UInt global_num, const types::RVector & position, ElementType type, GhostType ghost_type = _not_ghost) : Element(type, element, ghost_type), num_point(num_point), global_num(global_num), position((Real *)NULL, 0) { this->position.shallowCopy(position); }; QuadraturePoint(const QuadraturePoint & quad) : Element(quad), num_point(quad.num_point), position((Real *) NULL, 0) { position.shallowCopy(quad.position); }; inline QuadraturePoint & operator=(const QuadraturePoint & q) { if(this != &q) { element = q.element; type = q.type; ghost_type = q.ghost_type; num_point = q.num_point; global_num = q.global_num; position.shallowCopy(q.position); } return *this; } AKANTU_GET_MACRO(Position, position, const types::RVector &); void setPosition(const types::RVector & position) { this->position.shallowCopy(position); } /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "QuadraturePoint ["; Element::printself(stream, 0); stream << ", " << num_point << "]"; } public: UInt num_point; UInt global_num; private: types::RVector position; }; /** * The generic FEM class derived in a FEMTemplate class containing the * shape functions and the integration method */ class FEM : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FEM(Mesh & mesh, UInt spatial_dimension = 0, ID id = "fem", MemoryID memory_id = 0); virtual ~FEM(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// build the profile of the sparse matrix corresponding to the mesh void initSparseMatrixProfile(SparseMatrixType sparse_matrix_type = _unsymmetric); /// pre-compute all the shape functions, their derivatives and the jacobians virtual void initShapeFunctions(const GhostType & ghost_type = _not_ghost) = 0; /* ------------------------------------------------------------------------ */ /* Integration method bridges */ /* ------------------------------------------------------------------------ */ /// integrate f for all elements of type "type" virtual void integrate(const Vector & f, Vector &intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const = 0; /// integrate a scalar value on all elements of type "type" virtual Real integrate(const Vector & f, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const = 0; /// integrate f for all quadrature points of type "type" virtual void integrateOnQuadraturePoints(const Vector & f, Vector &intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const = 0; /* ------------------------------------------------------------------------ */ /* compatibility with old FEM fashion */ /* ------------------------------------------------------------------------ */ /// get the number of quadrature points virtual UInt getNbQuadraturePoints(const ElementType & type, const GhostType & ghost_type = _not_ghost) const = 0; /// get the precomputed shapes const virtual Vector & getShapes(const ElementType & type, const GhostType & ghost_type = _not_ghost) const = 0; /// get the derivatives of shapes const virtual Vector & getShapesDerivatives(const ElementType & type, const GhostType & ghost_type = _not_ghost, UInt id = 0) const = 0; /// get quadrature points const virtual Vector & getQuadraturePoints(const ElementType & type, const GhostType & ghost_type = _not_ghost) const = 0; /* ------------------------------------------------------------------------ */ /* Shape method bridges */ /* ------------------------------------------------------------------------ */ virtual void gradientOnQuadraturePoints(const Vector &u, Vector &nablauq, const UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const = 0; virtual void interpolateOnQuadraturePoints(const Vector &u, Vector &uq, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const =0; /* ------------------------------------------------------------------------ */ /* Other methods */ /* ------------------------------------------------------------------------ */ /// pre-compute normals on control points virtual void computeNormalsOnControlPoints(const GhostType & ghost_type = _not_ghost) = 0; /// pre-compute normals on control points virtual void computeNormalsOnControlPoints(__attribute__((unused)) const Vector & field, __attribute__((unused)) const GhostType & ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// pre-compute normals on control points virtual void computeNormalsOnControlPoints(__attribute__((unused)) const Vector & field, __attribute__((unused)) Vector & normal, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type = _not_ghost) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// assemble vectors void assembleVector(const Vector & elementary_vect, Vector & nodal_values, const Vector & equation_number, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL, Real scale_factor = 1) const; /// assemble matrix in the complete sparse matrix void assembleMatrix(const Vector & elementary_mat, SparseMatrix & matrix, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const; /// assemble a field as a lumped matrix (ex. rho in lumped mass) virtual void assembleFieldLumped(__attribute__ ((unused)) const Vector & field_1, __attribute__ ((unused)) UInt nb_degree_of_freedom, __attribute__ ((unused)) Vector & lumped, __attribute__ ((unused)) const Vector & equation_number, __attribute__ ((unused)) ElementType type, __attribute__ ((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); }; /// assemble a field as a matrix (ex. rho to mass matrix) virtual void assembleFieldMatrix(__attribute__ ((unused)) const Vector & field_1, __attribute__ ((unused)) UInt nb_degree_of_freedom, __attribute__ ((unused)) SparseMatrix & matrix, __attribute__ ((unused)) ElementType type, __attribute__ ((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; private: /// initialise the class void init(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(ElementDimension, element_dimension, UInt); /// get the mesh contained in the fem object inline Mesh & getMesh() const; /// get the in-radius of an element static inline Real getElementInradius(Real * coord, const ElementType & type); /// get the normals on quadrature points AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NormalsOnQuadPoints, normals_on_quad_points, Real); + virtual const ShapeFunctions & getShapeFunctionsInterface() const = 0; + virtual const Integrator & getIntegratorInterface() const = 0; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the fem object ID id; /// spatial dimension of the problem UInt element_dimension; /// the mesh on which all computation are made Mesh * mesh; /// normals at quadrature points ByElementTypeReal normals_on_quad_points; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "fem_inline_impl.cc" #endif /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const FEM & _this) { _this.printself(stream); return stream; } /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const QuadraturePoint & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #include "fem_template.hh" #endif /* __AKANTU_FEM_HH__ */ diff --git a/src/fem/fem_template.hh b/src/fem/fem_template.hh index 837779780..83417fcd6 100644 --- a/src/fem/fem_template.hh +++ b/src/fem/fem_template.hh @@ -1,250 +1,254 @@ /** * @file fem_template.hh * @author Guillaume Anciaux * @date Thu Feb 10 10:55:21 2011 * * @brief templated class that calls integration and shape objects * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #ifndef __AKANTU_FEM_TEMPLATE_HH__ #define __AKANTU_FEM_TEMPLATE_HH__ /* -------------------------------------------------------------------------- */ #include "fem.hh" #include "integrator.hh" #include "shape_functions.hh" #include "shape_lagrange.hh" #include "shape_cohesive.hh" #include "shape_linked.hh" #include "integrator_gauss.hh" #include "integrator_cohesive.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template class FEMTemplate : public FEM{ /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FEMTemplate(Mesh & mesh, UInt spatial_dimension = 0, ID id = "fem", MemoryID memory_id = 0); virtual ~FEMTemplate(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// pre-compute all the shape functions, their derivatives and the jacobians void initShapeFunctions(const GhostType & ghost_type = _not_ghost); /* ------------------------------------------------------------------------ */ /* Integration method bridges */ /* ------------------------------------------------------------------------ */ /// integrate f for all elements of type "type" void integrate(const Vector & f, Vector &intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const; /// integrate a scalar value on all elements of type "type" Real integrate(const Vector & f, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const; /// integrate partially around a quadrature point (@f$ intf_q = f_q * J_q * w_q @f$) void integrateOnQuadraturePoints(const Vector & f, Vector &intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const; /// get the number of quadrature points UInt getNbQuadraturePoints(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /// get shapes precomputed const Vector & getShapes(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /// get the derivatives of shapes const Vector & getShapesDerivatives(const ElementType & type, const GhostType & ghost_type = _not_ghost, UInt id=0) const; /// get quadrature points const Vector & getQuadraturePoints(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /* ------------------------------------------------------------------------ */ /* Shape method bridges */ /* ------------------------------------------------------------------------ */ void gradientOnQuadraturePoints(const Vector &u, Vector &nablauq, const UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const; void interpolateOnQuadraturePoints(const Vector &u, Vector &uq, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const; /// find natural coords from real coords provided an element void inverseMap(const types::RVector & real_coords, UInt element, const ElementType & type, types::RVector & natural_coords, const GhostType & ghost_type = _not_ghost) const; /// return true if the coordinates provided are inside the element, false otherwise inline bool contains(const types::RVector & real_coords, UInt element, const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /// compute the shape on a provided point inline void computeShapes(const types::RVector & real_coords, UInt element, const ElementType & type, types::RVector & shapes, const GhostType & ghost_type = _not_ghost) const; /* ------------------------------------------------------------------------ */ /* Other methods */ /* ------------------------------------------------------------------------ */ /// pre-compute normals on control points void computeNormalsOnControlPoints(const GhostType & ghost_type = _not_ghost); void computeNormalsOnControlPoints(const Vector & field, const GhostType & ghost_type = _not_ghost); void computeNormalsOnControlPoints(const Vector & field, Vector & normal, const ElementType & type, const GhostType & ghost_type = _not_ghost) const; /// function to print the contain of the class // virtual void printself(std::ostream & stream, int indent = 0) const{}; void assembleFieldLumped(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, ElementType type, const GhostType & ghost_type = _not_ghost) const; void assembleFieldMatrix(const Vector & field, UInt nb_degree_of_freedom, SparseMatrix & matrix, ElementType type, const GhostType & ghost_type = _not_ghost) const; private: template void assembleLumpedTemplate(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, const GhostType & ghost_type) const; /// @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j dV = \int \rho \varphi_i dV @f$ template void assembleLumpedRowSum(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, const GhostType & ghost_type) const; /// @f$ \tilde{M}_{i} = c * M_{ii} = \int_{V_e} \rho dV @f$ template void assembleLumpedDiagonalScaling(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, const GhostType & ghost_type) const; template void assembleFieldMatrix(const Vector & field, UInt nb_degree_of_freedom, SparseMatrix & matrix, const GhostType & ghost_type) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: + const ShapeFunctions & getShapeFunctionsInterface() const { return shape_functions; }; const Shape & getShapeFunctions() const { return shape_functions; }; + const Integrator & getIntegratorInterface() const { return integrator; }; + const Integ & getIntegrator() const { return integrator; }; + /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: Integ integrator; Shape shape_functions; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "fem_template_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const FEMTemplate & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_FEM_TEMPLATE_HH__ */ diff --git a/src/fem/integrator.hh b/src/fem/integrator.hh index 1297da2d2..30e6ff523 100644 --- a/src/fem/integrator.hh +++ b/src/fem/integrator.hh @@ -1,120 +1,121 @@ /** * @file integrator.hh * @author Guillaume Anciaux * @date Thu Feb 10 11:09:12 2011 * * @brief interface for integrator classes * * @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_INTEGRATOR_HH__ #define __AKANTU_INTEGRATOR_HH__ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class Integrator : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Integrator(const Mesh & mesh, const ID & id="integrator", const MemoryID & memory_id = 0) : Memory(memory_id), mesh(&mesh), id(id), jacobians("jacobians", id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); }; virtual ~Integrator(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: template inline void precomputeJacobiansOnQuadraturePoints(__attribute__ ((unused)) GhostType ghost_type){} void integrateOnElement(__attribute__ ((unused)) const Vector & f, __attribute__ ((unused)) Real * intf, __attribute__ ((unused)) UInt nb_degree_of_freedom, __attribute__ ((unused)) const Element & elem, __attribute__ ((unused)) GhostType ghost_type) const {}; /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Integrator [" << std::endl; jacobians.printself(stream, indent + 1); stream << space << "]" << std::endl; }; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// access to the jacobians - ByElementTypeReal & getJacobians(){return jacobians;}; + ByElementTypeReal & getJacobians() { return jacobians; }; + const ByElementTypeReal & getJacobians() const { return jacobians; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: const Mesh * mesh; ID id; /// jacobians for all elements ByElementTypeReal jacobians; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "integrator_inline_impl.cc" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Integrator & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_INTEGRATOR_HH__ */ diff --git a/src/fem/integrator_gauss.cc b/src/fem/integrator_gauss.cc index 4d7f44fa8..097ede554 100644 --- a/src/fem/integrator_gauss.cc +++ b/src/fem/integrator_gauss.cc @@ -1,327 +1,328 @@ /** * @file integrator_gauss.cc * @author Guillaume Anciaux * @author Nicolas Richart * @date Thu Feb 10 16:52:07 2011 * * @brief implementation of gauss integrator 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 "mesh.hh" #include "integrator_gauss.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ IntegratorGauss::IntegratorGauss(const Mesh & mesh, const ID & id, const MemoryID & memory_id) : Integrator(mesh, id, memory_id), quadrature_points("quadrature_points", id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void IntegratorGauss::checkJacobians(const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = ElementClass::getNbQuadraturePoints(); UInt nb_element; nb_element = mesh->getConnectivity(type,ghost_type).getSize(); Real * jacobians_val = jacobians(type, ghost_type).storage(); for (UInt i = 0; i < nb_element*nb_quadrature_points; ++i,++jacobians_val){ AKANTU_DEBUG_ASSERT(*jacobians_val >0, "Negative jacobian computed," - << " possible problem in the element node order"); + << " possible problem in the element node ordering (element " << i +/nb_quadrature_points << ")"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void IntegratorGauss::precomputeJacobiansOnQuadraturePoints(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh->getSpatialDimension(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = ElementClass::getNbQuadraturePoints(); Real * weights = ElementClass::getGaussIntegrationWeights(); UInt * elem_val = mesh->getConnectivity(type,ghost_type).storage(); UInt nb_element = mesh->getConnectivity(type,ghost_type).getSize(); Vector & jacobians_tmp = jacobians.alloc(nb_element*nb_quadrature_points, 1, type, ghost_type); Real * jacobians_val = jacobians_tmp.storage(); Real local_coord[spatial_dimension * nb_nodes_per_element]; for (UInt elem = 0; elem < nb_element; ++elem) { mesh->extractNodalValuesFromElement(mesh->getNodes(), local_coord, elem_val+elem*nb_nodes_per_element, nb_nodes_per_element, spatial_dimension); computeJacobianOnQuadPointsByElement(spatial_dimension, local_coord, nb_nodes_per_element, jacobians_val); for (UInt q = 0; q < nb_quadrature_points; ++q) { *jacobians_val++ *= weights[q]; } // jacobians_val += nb_quadrature_points; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void IntegratorGauss::integrate(const Vector & in_f, Vector &intf, UInt nb_degree_of_freedom, const GhostType & ghost_type, const Vector * filter_elements) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type), "No jacobians for the type " << jacobians.printType(type, ghost_type)); UInt nb_element = mesh->getNbElement(type,ghost_type); const Vector & jac_loc = jacobians(type, ghost_type); UInt nb_quadrature_points = ElementClass::getNbQuadraturePoints(); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } Real * in_f_val = in_f.storage(); Real * intf_val = intf.storage(); Real * jac_val = jac_loc.storage(); UInt offset_in_f = in_f.getNbComponent()*nb_quadrature_points; UInt offset_intf = intf.getNbComponent(); Real * jac = jac_val; for (UInt el = 0; el < nb_element; ++el) { if(filter_elements != NULL) { jac = jac_val + filter_elem_val[el] * nb_quadrature_points; } integrate(in_f_val, jac, intf_val, nb_degree_of_freedom, nb_quadrature_points); in_f_val += offset_in_f; intf_val += offset_intf; if(filter_elements == NULL) { jac += nb_quadrature_points; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template Real IntegratorGauss::integrate(const Vector & in_f, const GhostType & ghost_type, const Vector * filter_elements) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type), "No jacobians for the type " << jacobians.printType(type, ghost_type)); UInt nb_element = mesh->getNbElement(type, ghost_type); const Vector & jac_loc = jacobians(type, ghost_type); UInt nb_quadrature_points = ElementClass::getNbQuadraturePoints(); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } Real intf = 0.; Real * in_f_val = in_f.storage(); Real * jac_val = jac_loc.storage(); UInt offset_in_f = in_f.getNbComponent() * nb_quadrature_points; Real * jac = jac_val; for (UInt el = 0; el < nb_element; ++el) { if(filter_elements != NULL) { jac = jac_val + filter_elem_val[el] * nb_quadrature_points; } Real el_intf = 0; integrate(in_f_val, jac, &el_intf, 1, nb_quadrature_points); intf += el_intf; in_f_val += offset_in_f; if(filter_elements == NULL) { jac += nb_quadrature_points; } } AKANTU_DEBUG_OUT(); return intf; } /* -------------------------------------------------------------------------- */ template void IntegratorGauss::integrateOnQuadraturePoints(const Vector & in_f, Vector &intf, UInt nb_degree_of_freedom, const GhostType & ghost_type, const Vector * filter_elements) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type), "No jacobians for the type " << jacobians.printType(type, ghost_type)); UInt nb_element = mesh->getNbElement(type,ghost_type); const Vector & jac_loc = jacobians(type, ghost_type); UInt nb_quadrature_points = ElementClass::getNbQuadraturePoints(); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } Real * in_f_val = in_f.storage(); Real * intf_val = intf.storage(); Real * jac_val = jac_loc.storage(); Real * jac = jac_val; for (UInt el = 0; el < nb_element; ++el) { if(filter_elements != NULL) { jac = jac_val + filter_elem_val[el] * nb_quadrature_points; } for (UInt q = 0; q < nb_quadrature_points; ++q) { for (UInt dof = 0; dof < nb_degree_of_freedom; ++dof) { *intf_val = *in_f_val * *jac; ++in_f_val; ++intf_val; } ++jac; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <> void IntegratorGauss::precomputeJacobiansOnQuadraturePoints<_bernoulli_beam_2>(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh->getSpatialDimension(); UInt nb_quadrature_points = ElementClass<_bernoulli_beam_2>::getNbQuadraturePoints(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_bernoulli_beam_2); UInt * elem_val; UInt nb_element; elem_val = mesh->getConnectivity(_bernoulli_beam_2, ghost_type).storage(); nb_element = mesh->getConnectivity(_bernoulli_beam_2, ghost_type).getSize(); Vector & jacobians_tmp = jacobians.alloc(nb_element*nb_quadrature_points, 1, _bernoulli_beam_2, ghost_type); Real local_coord[spatial_dimension * nb_nodes_per_element]; Real * jacobians_val = jacobians_tmp.storage(); for (UInt elem = 0; elem < nb_element; ++elem) { mesh->extractNodalValuesFromElement(mesh->getNodes(), local_coord, elem_val+elem*nb_nodes_per_element, nb_nodes_per_element, spatial_dimension); ElementClass<_bernoulli_beam_2>::computeJacobian(local_coord, nb_quadrature_points, spatial_dimension, jacobians_val); jacobians_val += nb_quadrature_points; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* template instanciation */ /* -------------------------------------------------------------------------- */ #define INSTANCIATE_TEMPLATE_CLASS(type) \ template void IntegratorGauss:: \ precomputeJacobiansOnQuadraturePoints(const GhostType & ghost_type); \ template void IntegratorGauss:: \ checkJacobians(const GhostType & ghost_type) const; \ template void IntegratorGauss:: \ integrate(const Vector & in_f, \ Vector &intf, \ UInt nb_degree_of_freedom, \ const GhostType & ghost_type, \ const Vector * filter_elements) const; \ template Real IntegratorGauss:: \ integrate(const Vector & in_f, \ const GhostType & ghost_type, \ const Vector * filter_elements) const; \ template void IntegratorGauss:: \ integrateOnQuadraturePoints(const Vector & in_f, \ Vector &intf, \ UInt nb_degree_of_freedom, \ const GhostType & ghost_type, \ const Vector * filter_elements) const; AKANTU_BOOST_REGULAR_ELEMENT_LIST(INSTANCIATE_TEMPLATE_CLASS) #undef INSTANCIATE_TEMPLATE_CLASS __END_AKANTU__ diff --git a/src/mesh_utils/mesh_utils.cc b/src/mesh_utils/mesh_utils.cc index 9690b1908..2801b7f48 100644 --- a/src/mesh_utils/mesh_utils.cc +++ b/src/mesh_utils/mesh_utils.cc @@ -1,851 +1,906 @@ /** * @file mesh_utils.cc * @author Guillaume ANCIAUX * @date Wed Aug 18 14:21:00 2010 * * @brief All mesh utils necessary for various tasks * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "mesh_utils.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2Elements(const Mesh & mesh, CSR & node_to_elem, UInt spatial_dimension) { AKANTU_DEBUG_IN(); if (spatial_dimension == 0) spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes = mesh.getNbNodes(); const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt nb_types = type_list.size(); UInt nb_good_types = 0; UInt nb_nodes_per_element[nb_types]; // UInt nb_nodes_per_element_p1[nb_types]; UInt * conn_val[nb_types]; UInt nb_element[nb_types]; // ElementType type_p1; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; nb_nodes_per_element[nb_good_types] = Mesh::getNbNodesPerElement(type); // type_p1 = Mesh::getP1ElementType(type); // nb_nodes_per_element_p1[nb_good_types] = Mesh::getNbNodesPerElement(type_p1); conn_val[nb_good_types] = mesh.getConnectivity(type, _not_ghost).values; nb_element[nb_good_types] = mesh.getConnectivity(type, _not_ghost).getSize(); nb_good_types++; } AKANTU_DEBUG_ASSERT(nb_good_types != 0, "Some elements must be found in right dimension to compute facets!"); /// array for the node-element list node_to_elem.resizeRows(nb_nodes); node_to_elem.clearRows(); // node_offset.resize(nb_nodes + 1); // UInt * node_offset_val = node_offset.values; /// count number of occurrence of each node // memset(node_offset_val, 0, (nb_nodes + 1)*sizeof(UInt)); for (UInt t = 0; t < nb_good_types; ++t) { for (UInt el = 0; el < nb_element[t]; ++el) { UInt el_offset = el*nb_nodes_per_element[t]; for (UInt n = 0; n < nb_nodes_per_element[t]; ++n) { ++node_to_elem.rowOffset(conn_val[t][el_offset + n]); // node_offset_val[conn_val[t][el_offset + n]]++; } } } // /// convert the occurrence array in a csr one // for (UInt i = 1; i < nb_nodes; ++i) node_offset_val[i] += node_offset_val[i-1]; // for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i] = node_offset_val[i-1]; // node_offset_val[0] = 0; node_to_elem.countToCSR(); node_to_elem.resizeCols(); node_to_elem.beginInsertions(); /// rearrange element to get the node-element list // node_to_elem.resize(node_offset_val[nb_nodes]); // UInt * node_to_elem_val = node_to_elem.values; for (UInt t = 0, linearized_el = 0; t < nb_good_types; ++t) for (UInt el = 0; el < nb_element[t]; ++el, ++linearized_el) { UInt el_offset = el*nb_nodes_per_element[t]; for (UInt n = 0; n < nb_nodes_per_element[t]; ++n) node_to_elem.insertInRow(conn_val[t][el_offset + n], linearized_el); // node_to_elem_val[node_offset_val[conn_val[t][el_offset + n]]++] = linearized_el; } node_to_elem.endInsertions(); // for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i] = node_offset_val[i-1]; // node_offset_val[0] = 0; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2ElementsByElementType(const Mesh & mesh, ElementType type, CSR & node_to_elem) { // Vector & node_offset, // Vector & node_to_elem) { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_elements = mesh.getConnectivity(type, _not_ghost).getSize(); UInt * conn_val = mesh.getConnectivity(type, _not_ghost).values; /// array for the node-element list node_to_elem.resizeRows(nb_nodes); node_to_elem.clearRows(); // node_offset.resize(nb_nodes + 1); // UInt * node_offset_val = node_offset.values; // memset(node_offset_val, 0, (nb_nodes + 1)*sizeof(UInt)); /// count number of occurrence of each node for (UInt el = 0; el < nb_elements; ++el) { UInt el_offset = el*nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) ++node_to_elem.rowOffset(conn_val[el_offset + n]); // node_offset_val[conn_val[nb_nodes_per_element*el + n]]++; } /// convert the occurrence array in a csr one // for (UInt i = 1; i < nb_nodes; ++i) node_offset_val[i] += node_offset_val[i-1]; // for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i] = node_offset_val[i-1]; // node_offset_val[0] = 0; node_to_elem.countToCSR(); node_to_elem.resizeCols(); node_to_elem.beginInsertions(); /// save the element index in the node-element list // node_to_elem.resize(node_offset_val[nb_nodes]); // UInt * node_to_elem_val = node_to_elem.values; for (UInt el = 0; el < nb_elements; ++el) { UInt el_offset = el*nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { node_to_elem.insertInRow(conn_val[el_offset + n], el); } // node_to_elem_val[node_offset_val[conn_val[nb_nodes_per_element*el + n]]] = el; // node_offset_val[conn_val[nb_nodes_per_element*el + n]]++; } // /// rearrange node_offset to start with 0 // for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i] = node_offset_val[i-1]; // node_offset_val[0] = 0; node_to_elem.endInsertions(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildFacets(Mesh & mesh){ AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); ByElementTypeReal barycenter; buildFacetsDimension(mesh, mesh, true, spatial_dimension, barycenter); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildAllFacets(Mesh & mesh, Mesh & mesh_facets) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); ByElementTypeReal barycenter; /// generate facets buildFacetsDimension(mesh, mesh_facets, false, spatial_dimension, barycenter); /// compute their barycenters mesh_facets.initByElementTypeVector(barycenter, spatial_dimension, spatial_dimension - 1); Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1); for(; it != end; ++it) { UInt nb_element = mesh_facets.getNbElement(*it); barycenter(*it).resize(nb_element); Vector::iterator bary = barycenter(*it).begin(spatial_dimension); Vector::iterator bary_end = barycenter(*it).end(spatial_dimension); for (UInt el = 0; bary != bary_end; ++bary, ++el) { mesh_facets.getBarycenter(el, *it, bary->storage()); } } /// sort facets and generate subfacets for (UInt i = spatial_dimension - 1; i > 0; --i) { buildFacetsDimension(mesh_facets, mesh_facets, false, i, barycenter); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildFacetsDimension(Mesh & mesh, Mesh & mesh_facets, bool boundary_only, UInt dimension, ByElementTypeReal & barycenter){ AKANTU_DEBUG_IN(); const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt nb_types = type_list.size(); UInt nb_good_types = 0; UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes_per_element[nb_types]; UInt nb_nodes_per_facet[nb_types]; UInt nb_facets[nb_types]; UInt ** node_in_facet[nb_types]; Vector * connectivity_facets[nb_types]; Vector > * element_to_subelement[nb_types]; Vector * subelement_to_element[nb_types]; UInt * conn_val[nb_types]; UInt nb_element[nb_types]; ElementType facet_type; Real epsilon = std::numeric_limits::epsilon(); for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) != dimension) continue; nb_nodes_per_element[nb_good_types] = mesh.getNbNodesPerElement(type); facet_type = mesh.getFacetElementType(type); nb_facets[nb_good_types] = mesh.getNbFacetsPerElement(type); node_in_facet[nb_good_types] = mesh.getFacetLocalConnectivity(type); nb_nodes_per_facet[nb_good_types] = mesh.getNbNodesPerElement(facet_type); // getting connectivity of boundary facets connectivity_facets[nb_good_types] = mesh_facets.getConnectivityPointer(facet_type); connectivity_facets[nb_good_types]->resize(0); element_to_subelement[nb_good_types] = mesh_facets.getElementToSubelementPointer(facet_type); element_to_subelement[nb_good_types]->resize(0); conn_val[nb_good_types] = mesh.getConnectivity(type, _not_ghost).values; nb_element[nb_good_types] = mesh.getConnectivity(type, _not_ghost).getSize(); subelement_to_element[nb_good_types] = mesh_facets.getSubelementToElementPointer(type); subelement_to_element[nb_good_types]->resize(nb_element[nb_good_types]); nb_good_types++; } CSR node_to_elem; // Vector node_offset; // Vector node_to_elem; // buildNode2Elements(mesh,node_offset,node_to_elem); buildNode2Elements(mesh, node_to_elem, dimension); // std::cout << "node offset " << std::endl << node_offset << std::endl; // std::cout << "node to elem " << std::endl << node_to_elem << std::endl; Vector counter; /// count number of occurrence of each node for (UInt t = 0,linearized_el = 0; t < nb_good_types; ++t) { for (UInt el = 0; el < nb_element[t]; ++el, ++linearized_el) { UInt el_offset = el*nb_nodes_per_element[t]; for (UInt f = 0; f < nb_facets[t]; ++f) { //build the nodes involved in facet 'f' UInt facet_nodes[nb_nodes_per_facet[t]]; for (UInt n = 0; n < nb_nodes_per_facet[t]; ++n) { UInt node_facet = node_in_facet[t][f][n]; facet_nodes[n] = conn_val[t][el_offset + node_facet]; } //our reference is the first node CSR::iterator first_node_elements; //UInt * first_node_elements = node_to_elem.values+node_offset.values[facet_nodes[0]]; UInt first_node_nelements = node_to_elem.getNbCols(facet_nodes[0]); // node_offset.values[facet_nodes[0]+1]- // node_offset.values[facet_nodes[0]]; counter.resize(first_node_nelements); counter.clear(); //loop over the other nodes to search intersecting elements, //which are the elements that share another node with the //starting element after first_node CSR::iterator first_node_elements_end; first_node_elements_end = node_to_elem.end(facet_nodes[0]); for (UInt n = 1; n < nb_nodes_per_facet[t]; ++n) { CSR::iterator node_elements, node_elements_begin, node_elements_end; node_elements_begin = node_to_elem.begin(facet_nodes[n]); node_elements_end = node_to_elem.end(facet_nodes[n]); // UInt * node_elements = node_to_elem.values+node_offset.values[facet_nodes[n]]; // node_offset.values[facet_nodes[n]+1]- // node_offset.values[facet_nodes[n]]; UInt local_el = 0; for (first_node_elements = node_to_elem.begin(facet_nodes[0]); first_node_elements != first_node_elements_end; ++first_node_elements, ++local_el) { for (node_elements = node_elements_begin; node_elements != node_elements_end; ++node_elements) { if (*first_node_elements == *node_elements) { ++counter.values[local_el]; // it may cause trouble: break; } } // if (counter.values[local_el] == nb_nodes_per_facet[t]) break; } } // bool connected_facet = false; //the connected elements are those for which counter is n_facet // UInt connected_element = -1; // counting the number of elements connected to the facets and // taking the minimum element number, because the facet should // be inserted just once UInt nb_element_connected_to_facet = 0; UInt minimum_el_index = std::numeric_limits::max(); Vector connected_elements; for (UInt el1 = 0; el1 < counter.getSize(); el1++) { UInt el_index = node_to_elem(facet_nodes[0], el1); if (counter.values[el1] == nb_nodes_per_facet[t]-1) { ++nb_element_connected_to_facet; minimum_el_index = std::min(minimum_el_index, el_index); connected_elements.push_back(el_index); } } if (minimum_el_index == linearized_el) { if (!boundary_only || (boundary_only && nb_element_connected_to_facet == 1)) { connectivity_facets[t]->push_back(facet_nodes); UInt current_nb_facets = element_to_subelement[t]->getSize(); element_to_subelement[t]->resize(current_nb_facets + 1); Vector & elements = (*element_to_subelement[t])(current_nb_facets); // build elements_on_facets: linearized_el must come first // in order to store the facet in the correct direction // and avoid to invert the sign in the normal computation elements.push_back(mesh.linearizedToElement(linearized_el)); /// boundary facet if (nb_element_connected_to_facet == 1) elements.push_back(ElementNull); /// internal facet else if (nb_element_connected_to_facet == 2) elements.push_back(mesh.linearizedToElement(connected_elements.values[1])); /// facet of facet else { UInt nb_connected = connected_elements.getSize(); for (UInt i = 1; i < nb_connected; ++i) { elements.push_back(mesh.linearizedToElement(connected_elements.values[i])); } /// check if sorting is needed: /// - in 3D to sort triangles around segments /// - in 2D to sort segments around points if (dimension == spatial_dimension - 1) { /// barycentrical coordinates for each connected /// element with respect to start_node Vector connected_nodes(nb_connected, 2); const Vector & coord = mesh_facets.getNodes(); const Vector & facet_conn = mesh_facets.getConnectivity(facet_type); /// node around which the sorting is carried out is /// the first node of the current facet UInt start_node = facet_conn(facet_conn.getSize()-1, 0); Real start_coord[spatial_dimension]; for (UInt dim = 0; dim < spatial_dimension; ++dim) { start_coord[dim] = coord(start_node, dim); } if (spatial_dimension == 3) { /// vector connecting facet first node to second Real tangent[spatial_dimension]; /// vector connecting facet first node and /// barycenter of elements(0) Real temp[spatial_dimension]; /// two normals to the segment facet to define the /// reference system Real normal1[spatial_dimension]; Real normal2[spatial_dimension]; Vector & bar = barycenter(elements(0).type); /// facet second node UInt second_node = facet_conn(facet_conn.getSize()-1, 1); /// construction of tangent and temp arrays for (UInt dim = 0; dim < spatial_dimension; ++dim) { Real x1, x2; x1 = coord(second_node, dim); x2 = bar(elements(0).element, dim); tangent[dim] = x1 - start_coord[dim]; temp[dim] = x2 - start_coord[dim]; } /// get normal1 and normal2 Math::normalize3(tangent); Math::vectorProduct3(tangent, temp, normal1); Math::normalize3(normal1); Math::vectorProduct3(tangent, normal1, normal2); for (UInt n = 0; n < nb_connected; ++n) { Real bary_coord[spatial_dimension]; Vector & bary = barycenter(elements(n).type); /// get the barycenter local coordinates for (UInt dim = 0; dim < spatial_dimension; ++dim) { bary_coord[dim] = bary(elements(n).element, dim) - start_coord[dim]; } /// project the barycenter coordinates on the two /// normals to have them on the same plane connected_nodes(n, 0) = Math::vectorDot(bary_coord, normal1, spatial_dimension); connected_nodes(n, 1) = Math::vectorDot(bary_coord, normal2, spatial_dimension); } } else if (spatial_dimension == 2) { for (UInt n = 0; n < nb_connected; ++n) { Vector & bary = barycenter(elements(n).type); /// get the barycenter local coordinates for (UInt dim = 0; dim < spatial_dimension; ++dim) { connected_nodes(n, dim) = bary(elements(n).element, dim) - start_coord[dim]; } } } /// associate to each element a real value based on /// atan2 function (check wikipedia) std::map atan2; for (UInt n = 0; n < nb_connected; ++n) { Real x = connected_nodes(n, 0); Real y = connected_nodes(n, 1); /// in order to avoid division by zero: if (std::abs(y) <= std::abs(y) * epsilon && x < 0) y = Math::getTolerance(); atan2[elements(n)] = y / (sqrt(x * x + y * y) + x); } /// sort elements according to their atan2 values ElementSorter sorter(atan2); std::sort(elements.storage(), elements.storage() + elements.getSize(), sorter); } } /// current facet index UInt current_facet = connectivity_facets[t]->getSize() - 1; /// loop on every element connected to current facet and /// insert current facet in the first free spot of the /// subelement_to_element vector for (UInt elem = 0; elem < elements.getSize(); ++elem) { if (elements(elem).type != _not_defined) { for (UInt f_in = 0; f_in < nb_facets[t]; ++f_in) { if ((*subelement_to_element[t])(elements(elem).element, f_in).type == _not_defined) { (*subelement_to_element[t])(elements(elem).element, f_in).type = facet_type; (*subelement_to_element[t])(elements(elem).element, f_in).element = current_facet; break; } } } } } } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ // void MeshUtils::buildNormals(Mesh & mesh,UInt spatial_dimension){ // AKANTU_DEBUG_IN(); // const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); // Mesh::ConnectivityTypeList::const_iterator it; // UInt nb_types = type_list.size(); // UInt nb_nodes_per_element[nb_types]; // UInt nb_nodes_per_element_p1[nb_types]; // UInt nb_good_types = 0; // Vector * connectivity[nb_types]; // Vector * normals[nb_types]; // if (spatial_dimension == 0) spatial_dimension = mesh.getSpatialDimension(); // for(it = type_list.begin(); it != type_list.end(); ++it) { // ElementType type = *it; // ElementType type_p1 = mesh.getP1ElementType(type); // if(mesh.getSpatialDimension(type) != spatial_dimension) continue; // nb_nodes_per_element[nb_good_types] = mesh.getNbNodesPerElement(type); // nb_nodes_per_element_p1[nb_good_types] = mesh.getNbNodesPerElement(type_p1); // // getting connectivity // connectivity[nb_good_types] = mesh.getConnectivityPointer(type); // if (!connectivity[nb_good_types]) // AKANTU_DEBUG_ERROR("connectivity is not allocatted : this should probably not have happened"); // //getting array of normals // normals[nb_good_types] = mesh.getNormalsPointer(type); // if(normals[nb_good_types]) // normals[nb_good_types]->resize(0); // else // normals[nb_good_types] = &mesh.createNormals(type); // nb_good_types++; // } // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void MeshUtils::renumberMeshNodes(Mesh & mesh, UInt * local_connectivities, UInt nb_local_element, UInt nb_ghost_element, ElementType type, Vector & nodes_numbers) { AKANTU_DEBUG_IN(); nodes_numbers.resize(0); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); - UInt * conn = local_connectivities; - std::map renumbering_map; /// renumber the nodes - for (UInt el = 0; el < nb_local_element + nb_ghost_element; ++el) { - for (UInt n = 0; n < nb_nodes_per_element; ++n) { - std::map::iterator it = renumbering_map.find(*conn); - // Int nn = nodes_numbers.find(*conn); - if(it == renumbering_map.end()) { - UInt old_node = *conn; - nodes_numbers.push_back(old_node); - *conn = nodes_numbers.getSize() - 1; - - renumbering_map[old_node] = *conn; - } else { - *conn = it->second; - } - conn++; - } - } + renumberNodesInConnectivity(local_connectivities, + (nb_local_element + nb_ghost_element)*nb_nodes_per_element, + renumbering_map, + nodes_numbers); renumbering_map.clear(); /// copy the renumbered connectivity to the right place Vector * local_conn = mesh.getConnectivityPointer(type); local_conn->resize(nb_local_element); memcpy(local_conn->values, local_connectivities, nb_local_element * nb_nodes_per_element * sizeof(UInt)); Vector * ghost_conn = mesh.getConnectivityPointer(type,_ghost); ghost_conn->resize(nb_ghost_element); memcpy(ghost_conn->values, local_connectivities + nb_local_element * nb_nodes_per_element, nb_ghost_element * nb_nodes_per_element * sizeof(UInt)); AKANTU_DEBUG_OUT(); } +/* -------------------------------------------------------------------------- */ +void MeshUtils::renumberNodesInConnectivity(UInt * list_nodes, + UInt nb_nodes, + std::map & renumbering_map, + Vector & nodes_numbers) { + AKANTU_DEBUG_IN(); + + UInt * connectivity = list_nodes; + for (UInt n = 0; n < nb_nodes; ++n, ++connectivity) { + UInt & node = *connectivity; + std::map::iterator it = renumbering_map.find(node); + if(it == renumbering_map.end()) { + UInt old_node = node; + nodes_numbers.push_back(old_node); + node = nodes_numbers.getSize() - 1; + renumbering_map[old_node] = node; + } else { + node = it->second; + } + } + + AKANTU_DEBUG_OUT(); +} + + +/* -------------------------------------------------------------------------- */ +void MeshUtils::purifyMesh(Mesh & mesh) { + AKANTU_DEBUG_IN(); + + std::map renumbering_map; + Vector node_numbers; + + for (UInt gt = _not_ghost; gt <= _ghost; ++gt) { + GhostType ghost_type = (GhostType) gt; + + Mesh::type_iterator it = mesh.firstType(0, ghost_type, _ek_not_defined); + Mesh::type_iterator end = mesh.lastType(0, ghost_type, _ek_not_defined); + for(; it != end; ++it) { + + ElementType type(*it); + UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); + + const Vector & connectivity_vect = mesh.getConnectivity(type, ghost_type); + UInt nb_element(connectivity_vect.getSize()); + UInt * connectivity = connectivity_vect.storage(); + + renumberNodesInConnectivity (connectivity, nb_element*nb_nodes_per_element, renumbering_map, node_numbers); + } + } + + UInt spatial_dimension = mesh.getSpatialDimension(); + + Vector & nodes = const_cast &>(mesh.getNodes()); + Vector::iterator nodes_it = nodes.begin(spatial_dimension); + Vector new_nodes(0, spatial_dimension); + + for (UInt i = 0; i < node_numbers.getSize(); ++i) { + new_nodes.push_back(nodes_it + node_numbers(i)); + } + + std::copy(new_nodes.begin(spatial_dimension), new_nodes.end(spatial_dimension), + nodes.begin(spatial_dimension)); + + nodes.resize(node_numbers.getSize()); + + AKANTU_DEBUG_OUT(); +} + + /* -------------------------------------------------------------------------- */ void MeshUtils::setUIntData(Mesh & mesh, UInt * data, UInt nb_tags, const ElementType & type) { AKANTU_DEBUG_IN(); UInt nb_element = mesh.getNbElement(type, _not_ghost); UInt nb_ghost_element = mesh.getNbElement(type, _ghost); char * names = reinterpret_cast(data + (nb_element + nb_ghost_element) * nb_tags); UIntDataMap & uint_data_map = mesh.getUIntDataMap(type, _not_ghost); UIntDataMap & ghost_uint_data_map = mesh.getUIntDataMap(type, _ghost); for (UInt t = 0; t < nb_tags; ++t) { std::string name(names); // std::cout << name << std::endl; names += name.size() + 1; UIntDataMap::iterator it = uint_data_map.find(name); if(it == uint_data_map.end()) { uint_data_map[name] = new Vector(0, 1, name); it = uint_data_map.find(name); } it->second->resize(nb_element); memcpy(it->second->values, data, nb_element * sizeof(UInt)); data += nb_element; it = ghost_uint_data_map.find(name); if(it == ghost_uint_data_map.end()) { ghost_uint_data_map[name] = new Vector(0, 1, name); it = ghost_uint_data_map.find(name); } it->second->resize(nb_ghost_element); memcpy(it->second->values, data, nb_ghost_element * sizeof(UInt)); data += nb_ghost_element; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildSurfaceID(Mesh & mesh) { AKANTU_DEBUG_IN(); // Vector node_offset; // Vector node_to_elem; CSR node_to_elem; /// Get list of surface elements UInt spatial_dimension = mesh.getSpatialDimension(); // buildNode2Elements(mesh, node_offset, node_to_elem, spatial_dimension-1); buildNode2Elements(mesh, node_to_elem, spatial_dimension-1); /// Find which types of elements have been linearized const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt nb_types = type_list.size(); ElementType lin_element_type[nb_types]; UInt nb_lin_types = 0; UInt nb_nodes_per_element[nb_types]; UInt nb_nodes_per_element_p1[nb_types]; UInt * conn_val[nb_types]; UInt nb_element[nb_types+1]; ElementType type_p1; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; ElementType facet_type = mesh.getFacetElementType(type); lin_element_type[nb_lin_types] = facet_type; nb_nodes_per_element[nb_lin_types] = Mesh::getNbNodesPerElement(facet_type); type_p1 = Mesh::getP1ElementType(facet_type); nb_nodes_per_element_p1[nb_lin_types] = Mesh::getNbNodesPerElement(type_p1); conn_val[nb_lin_types] = mesh.getConnectivity(facet_type, _not_ghost).values; nb_element[nb_lin_types] = mesh.getNbElement(facet_type, _not_ghost); nb_lin_types++; } for (UInt i = 1; i < nb_lin_types; ++i) nb_element[i] += nb_element[i+1]; for (UInt i = nb_lin_types; i > 0; --i) nb_element[i] = nb_element[i-1]; nb_element[0] = 0; /// Find close surfaces Vector surface_value_id(1, nb_element[nb_lin_types], -1); Int * surf_val = surface_value_id.values; UInt nb_surfaces = 0; UInt nb_cecked_elements; UInt nb_elements_to_ceck; UInt * elements_to_ceck = new UInt [nb_element[nb_lin_types]]; memset(elements_to_ceck, 0, nb_element[nb_lin_types]*sizeof(UInt)); for (UInt lin_el = 0; lin_el < nb_element[nb_lin_types]; ++lin_el) { if(surf_val[lin_el] != -1) continue; /* Surface id already assigned */ /* First element of new surface */ surf_val[lin_el] = nb_surfaces; nb_cecked_elements = 0; nb_elements_to_ceck = 1; memset(elements_to_ceck, 0, nb_element[nb_lin_types]*sizeof(UInt)); elements_to_ceck[0] = lin_el; // Find others elements belonging to this surface while(nb_cecked_elements < nb_elements_to_ceck) { UInt ceck_lin_el = elements_to_ceck[nb_cecked_elements]; // Transform linearized index of element into ElementType one UInt lin_type_nb = 0; while (ceck_lin_el >= nb_element[lin_type_nb+1]) lin_type_nb++; UInt ceck_el = ceck_lin_el - nb_element[lin_type_nb]; // Get connected elements UInt el_offset = ceck_el*nb_nodes_per_element[lin_type_nb]; for (UInt n = 0; n < nb_nodes_per_element_p1[lin_type_nb]; ++n) { UInt node_id = conn_val[lin_type_nb][el_offset + n]; CSR::iterator it_n; for (it_n = node_to_elem.begin(node_id); it_n != node_to_elem.end(node_id); ++it_n) { // for (UInt i = node_offset.values[node_id]; i < node_offset.values[node_id+1]; ++i) { if(surf_val[*it_n] == -1) { /* Found new surface element */ surf_val[*it_n] = nb_surfaces; elements_to_ceck[nb_elements_to_ceck] = *it_n; nb_elements_to_ceck++; } // if(surf_val[node_to_elem.values[i]] == -1) { /* Found new surface element */ // surf_val[node_to_elem.values[i]] = nb_surfaces; // elements_to_ceck[nb_elements_to_ceck] = node_to_elem.values[i]; // nb_elements_to_ceck++; // } } } nb_cecked_elements++; } nb_surfaces++; } delete [] elements_to_ceck; /// Transform local linearized element index in the global one for (UInt i = 0; i < nb_lin_types; ++i) nb_element[i] = nb_element[i+1] - nb_element[i]; UInt el_offset = 0; for (UInt type_it = 0; type_it < nb_lin_types; ++type_it) { ElementType type = lin_element_type[type_it]; Vector * surf_id_type = mesh.getSurfaceIDPointer(type, _not_ghost); surf_id_type->resize(nb_element[type_it]); surf_id_type->clear(); for (UInt el = 0; el < nb_element[type_it]; ++el) surf_id_type->values[el] = surf_val[el+el_offset]; el_offset += nb_element[type_it]; } /// Set nb_surfaces in mesh mesh.nb_surfaces = nb_surfaces; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildNodesPerSurface(const Mesh & mesh, CSR & nodes_per_surface) { AKANTU_DEBUG_IN(); UInt nb_surfaces = mesh.getNbSurfaces(); UInt nb_nodes = mesh.getNbNodes(); UInt spatial_dimension = mesh.getSpatialDimension(); //surface elements UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator end = mesh.lastType(spatial_dimension); for(; it != end; ++it) { facet_type[nb_facet_types++] = mesh.getFacetElementType(*it); } UInt * surface_nodes_id = new UInt[nb_nodes*nb_surfaces]; std::fill_n(surface_nodes_id, nb_surfaces*nb_nodes, 0); for(UInt t = 0; t < nb_facet_types; ++t) { ElementType type = facet_type[t]; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); UInt * connecticity = mesh.getConnectivity(type, _not_ghost).values; UInt * surface_id = mesh.getSurfaceID(type, _not_ghost).values;; for (UInt el = 0; el < nb_element; ++el) { UInt offset = *surface_id * nb_nodes; for (UInt n = 0; n < nb_nodes_per_element; ++n) { surface_nodes_id[offset + *connecticity] = 1; ++connecticity; } ++surface_id; } } nodes_per_surface.resizeRows(nb_surfaces); nodes_per_surface.clearRows(); UInt * surface_nodes_id_tmp = surface_nodes_id; for (UInt s = 0; s < nb_surfaces; ++s) for (UInt n = 0; n < nb_nodes; ++n) nodes_per_surface.rowOffset(s) += *surface_nodes_id_tmp++; nodes_per_surface.countToCSR(); nodes_per_surface.resizeCols(); nodes_per_surface.beginInsertions(); surface_nodes_id_tmp = surface_nodes_id; for (UInt s = 0; s < nb_surfaces; ++s) for (UInt n = 0; n < nb_nodes; ++n) { if (*surface_nodes_id_tmp == 1) nodes_per_surface.insertInRow(s, n); surface_nodes_id_tmp++; } nodes_per_surface.endInsertions(); delete [] surface_nodes_id; AKANTU_DEBUG_OUT(); } __END_AKANTU__ // LocalWords: ElementType diff --git a/src/mesh_utils/mesh_utils.hh b/src/mesh_utils/mesh_utils.hh index dd412cd58..493cadb70 100644 --- a/src/mesh_utils/mesh_utils.hh +++ b/src/mesh_utils/mesh_utils.hh @@ -1,173 +1,182 @@ /** * @file mesh_utils.hh * @author Guillaume ANCIAUX * @date Wed Aug 18 14:03:39 2010 * * @brief All mesh utils necessary for various tasks * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "aka_csr.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_UTILS_HH__ #define __AKANTU_MESH_UTILS_HH__ /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class MeshUtils { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshUtils(); virtual ~MeshUtils(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// build map from nodes to elements static void buildNode2Elements(const Mesh & mesh, CSR & node_to_elem, UInt spatial_dimension = 0); // static void buildNode2Elements(const Mesh & mesh, Vector & node_offset, Vector & node_to_elem, UInt spatial_dimension = 0); /// build map from nodes to elements for a specific element type static void buildNode2ElementsByElementType(const Mesh & mesh, ElementType type, CSR & node_to_elem); // static void buildNode2ElementsByElementType(const Mesh & mesh, ElementType type, Vector & node_offset, Vector & node_to_elem); /// build facets elements on boundary static void buildFacets(Mesh & mesh); /// build facets elements : boundary and internals static void buildAllFacets(Mesh & mesh, Mesh & mesh_facets); /// build facets for a given spatial dimension static void buildFacetsDimension(Mesh & mesh, Mesh & mesh_facets, bool boundary_only, UInt dimension, ByElementTypeReal & barycenter); /// build normal to some elements // static void buildNormals(Mesh & mesh, UInt spatial_dimension=0); /// take the local_connectivity array as the array of local and ghost /// connectivity, renumber the nodes and set the connectivity of the mesh static void renumberMeshNodes(Mesh & mesh, UInt * local_connectivities, UInt nb_local_element, UInt nb_ghost_element, ElementType type, Vector & old_nodes); static void setUIntData(Mesh & mesh, UInt * data, UInt nb_tags, const ElementType & type); /// Detect closed surfaces of the mesh and save the surface id /// of the surface elements in the array surface_id static void buildSurfaceID(Mesh & mesh); /// compute pbc pair for on given direction static void computePBCMap(const Mesh & mymesh,const UInt dir, std::map & pbc_pair); /// compute pbc pair for a surface pair static void computePBCMap(const Mesh & mymesh, const std::pair & surface_pair, const ElementType type, std::map & pbc_pair); // /// tweak mesh connectivity to activate pbc // static void tweakConnectivityForPBC(Mesh & mesh, // bool flag_x, // bool flag_y = false, // bool flag_z = false); /// create a multimap of nodes per surfaces static void buildNodesPerSurface(const Mesh & mesh, CSR & nodes_per_surface); /// function to print the contain of the class // virtual void printself(std::ostream & stream, int indent = 0) const; + /// remove not connected nodes /!\ this functions renumbers the nodes. + static void purifyMesh(Mesh & mesh); + private: /// match pairs that are on the associated pbc's static void matchPBCPairs(const Mesh & mymesh, const UInt dir, std::vector & selected_left, std::vector & selected_right, std::map & pbc_pair); + /// function used by all the renumbering functions + static void renumberNodesInConnectivity(UInt * list_nodes, + UInt nb_nodes, + std::map & renumbering_map, + Vector & nodes_numbers); + /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; class ElementSorter { public: ElementSorter(const ElementSorter & e) : atan2(e.atan2) {} ElementSorter(std::map & atan2) : atan2(atan2) {} inline bool operator()(const Element & first, const Element & second); private: std::map & atan2; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "mesh_utils_inline_impl.cc" #endif /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const MeshUtils & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_MESH_UTILS_HH__ */ diff --git a/src/model/parser.hh b/src/model/parser.hh index c860d3ab0..bd9ed9640 100644 --- a/src/model/parser.hh +++ b/src/model/parser.hh @@ -1,104 +1,109 @@ /** * @file material_parser.hh * @author Guillaume ANCIAUX * @date Thu Nov 25 11:43:48 2010 * * @brief * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_PARSER_HH__ #define __AKANTU_MATERIAL_PARSER_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ +class Parsable { +public: + virtual bool setParam(const std::string & key, const std::string & value, + const ID & id) = 0; +}; + class Parser { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Parser() : current_line(0) {}; virtual ~Parser(){ infile.close(); }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// open/close a file to parse void open(const std::string & filename); void close(); /// read the file and return the next material type std::string getNextSection(const std::string & obj_type, std::string & optional_param); /// read properties and instanciate a given material object template void readSection(M & model); - template - Obj * readSection(M & model, std::string & obj_name); - + /// read the properties in a section + void readSection(const std::string & obj_name, Parsable & obj); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: inline void my_getline(); /// number of the current line UInt current_line; /// material file std::ifstream infile; /// current read line std::string line; /// name of file parsed std::string filename; }; #include "parser_tmpl.hh" #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "parser_inline_impl.cc" #endif __END_AKANTU__ #endif diff --git a/src/model/parser_tmpl.hh b/src/model/parser_tmpl.hh index 48b75a7dc..0c9db1dc8 100644 --- a/src/model/parser_tmpl.hh +++ b/src/model/parser_tmpl.hh @@ -1,81 +1,79 @@ /** * @file parser_tmpl.hh * @author Nicolas Richart * @date Thu Nov 24 08:44:22 2011 * * @brief Template part of the parser * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ template inline void Parser::readSection(M & model) { my_getline(); while(line[0] != ']') { if(line != "") { size_t pos = line.find("="); if(pos == std::string::npos) AKANTU_DEBUG_ERROR("Malformed material file : line must be \"key = value\" at line" << current_line); - + std::string keyword = trim(line.substr(0, pos)); std::string value = trim(line.substr(pos + 1)); - + if(!model.setParam(keyword, value)) { AKANTU_DEBUG_ERROR("Malformed file : error in setParam at line " << current_line <<"." << " Parameter (" << keyword << ") is not recognized!"); } } my_getline(); } } /* -------------------------------------------------------------------------- */ -template -inline Obj * Parser::readSection(ParentType & parent, std::string & obj_name){ - /// instanciate the material object - Obj * obj = new Obj(parent, obj_name); +inline void Parser::readSection(const std::string & obj_name, + Parsable & obj){ /// read the material properties my_getline(); while(line[0] != ']') { if(line != "") { size_t pos = line.find("="); if(pos == std::string::npos) AKANTU_DEBUG_ERROR("Malformed material file : line must be \"key = value\" at line" << current_line); - + std::string keyword = trim(line.substr(0, pos)); std::string value = trim(line.substr(pos + 1)); - if(!obj->setParam(keyword, value, obj_name)) { - AKANTU_DEBUG_ERROR("Malformed material file : error in setParam at line " - << current_line <<"." - << " Parameter (" << keyword << ") is not recognizedby " << obj_name << "!"); + if(!obj.setParam(keyword, value, obj_name)) { + AKANTU_DEBUG_WARNING("Malformed material file : error in setParam at line " + << current_line <<"." + << " Parameter (" << keyword << ") is not recognized by " << obj_name << "!"); } } my_getline(); } - return obj; } + diff --git a/src/model/solid_mechanics/material.cc b/src/model/solid_mechanics/material.cc index e391d9ed4..4b1d659e5 100644 --- a/src/model/solid_mechanics/material.cc +++ b/src/model/solid_mechanics/material.cc @@ -1,795 +1,791 @@ /** * @file material.cc * @author Nicolas Richart * @date Tue Jul 27 11:43:41 2010 * * @brief Implementation of the common part of the material 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 "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(model.getMemoryID()), id(id), name(""), model(&model), stress("stress", id), strain("strain", id), element_filter("element_filter", id), // potential_energy_vector(false), potential_energy("potential_energy", id), is_non_local(false), interpolation_inverse_coordinates("interpolation inverse coordinates", id), interpolation_points_matrices("interpolation points matrices", id), is_init(false) { AKANTU_DEBUG_IN(); rho = 0; AKANTU_DEBUG_ASSERT(this->model,"model has wrong type: cannot proceed"); spatial_dimension = this->model->getSpatialDimension(); /// allocate strain stress for local elements initInternalVector(strain, spatial_dimension * spatial_dimension); initInternalVector(stress, spatial_dimension * spatial_dimension); /// for each connectivity types allocate the element filer array of the material initInternalVector(element_filter, 1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Material::~Material() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool Material::setParam(const std::string & key, const std::string & value, __attribute__ ((unused)) const ID & id) { std::stringstream sstr(value); if(key == "name") name = std::string(value); else if(key == "rho") { sstr >> rho; } else return false; return true; } /* -------------------------------------------------------------------------- */ void Material::initMaterial() { AKANTU_DEBUG_IN(); resizeInternalVector(stress); resizeInternalVector(strain); is_init = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::initInternalVector(ByElementTypeVector & vect, UInt nb_component, ElementKind element_kind) const { AKANTU_DEBUG_IN(); model->getFEM().getMesh().initByElementTypeVector(vect, nb_component, spatial_dimension, false, element_kind); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::resizeInternalVector(ByElementTypeVector & by_el_type_vect, ElementKind element_kind) const { AKANTU_DEBUG_IN(); FEM * fem = & model->getFEM(); if (element_kind == _ek_cohesive) fem = & model->getFEM("CohesiveFEM"); const Mesh & mesh = fem->getMesh(); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt, element_kind); Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt, element_kind); for(; it != end; ++it) { const Vector & elem_filter = element_filter(*it, gt); UInt nb_element = elem_filter.getSize(); UInt nb_quadrature_points = fem->getNbQuadraturePoints(*it, gt); UInt new_size = nb_element * nb_quadrature_points; Vector & vect = by_el_type_vect(*it, gt); - UInt size = vect.getSize(); - UInt nb_component = vect.getNbComponent(); - vect.resize(new_size); - memset(vect.storage() + size * nb_component, 0, (new_size - size) * nb_component * sizeof(T)); } } 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(Vector & displacement, GhostType ghost_type) { AKANTU_DEBUG_IN(); computeAllStresses(displacement, ghost_type); assembleResidual(ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::assembleResidual(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); Vector & residual = const_cast &>(model->getResidual()); Mesh & mesh = model->getFEM().getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { const Vector & shapes_derivatives = model->getFEM().getShapesDerivatives(*it, ghost_type); Vector & elem_filter = element_filter(*it, ghost_type); UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(*it, ghost_type); UInt nb_element = elem_filter.getSize(); /// compute @f$\sigma \frac{\partial \varphi}{\partial X}@f$ by @f$\mathbf{B}^t \mathbf{\sigma}_q@f$ Vector * sigma_dphi_dx = new Vector(nb_element*nb_quadrature_points, size_of_shapes_derivatives, "sigma_x_dphi_/_dX"); Real * shapesd = shapes_derivatives.storage(); Real * shapesd_val; UInt * elem_filter_val = elem_filter.storage(); Vector * shapesd_filtered = new Vector(nb_element*nb_quadrature_points, size_of_shapes_derivatives, "filtered shapesd"); Real * shapesd_filtered_val = shapesd_filtered->values; for (UInt el = 0; el < nb_element; ++el) { shapesd_val = shapesd + elem_filter_val[el] * size_of_shapes_derivatives * nb_quadrature_points; memcpy(shapesd_filtered_val, shapesd_val, size_of_shapes_derivatives * nb_quadrature_points * sizeof(Real)); shapesd_filtered_val += size_of_shapes_derivatives * nb_quadrature_points; } Vector & stress_vect = stress(*it, ghost_type); // Vector::iterator sigma = stress_vect.begin(spatial_dimension, spatial_dimension); // Vector::iterator sigma_end = stress_vect.end(spatial_dimension, spatial_dimension); // Vector::iterator nabla_B = shapesd_filtered->begin(nb_nodes_per_element, spatial_dimension); // Vector::iterator sigma_dphi_dx_it = sigma_dphi_dx->begin(nb_nodes_per_element, spatial_dimension); // for (; sigma != sigma_end; ++sigma, ++nabla_B, ++sigma_dphi_dx_it) { // sigma_dphi_dx_it->mul(*nabla_B, *sigma); // } Math::matrix_matrixt(nb_nodes_per_element, spatial_dimension, spatial_dimension, *shapesd_filtered, stress_vect, *sigma_dphi_dx); 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$ */ Vector * int_sigma_dphi_dx = new Vector(nb_element, nb_nodes_per_element * spatial_dimension, "int_sigma_x_dphi_/_dX"); model->getFEM().integrate(*sigma_dphi_dx, *int_sigma_dphi_dx, size_of_shapes_derivatives, *it, ghost_type, &elem_filter); delete sigma_dphi_dx; /// assemble model->getFEM().assembleVector(*int_sigma_dphi_dx, residual, model->getDOFSynchronizer().getLocalDOFEquationNumbers(), residual.getNbComponent(), *it, ghost_type, &elem_filter, -1); delete int_sigma_dphi_dx; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the stress from the strain * * @param[in] current_position nodes postition + displacements * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ void Material::computeAllStresses(Vector & displacement, GhostType ghost_type) { AKANTU_DEBUG_IN(); resizeInternalVector(stress); resizeInternalVector(strain); UInt spatial_dimension = model->getSpatialDimension(); Mesh::type_iterator it = model->getFEM().getMesh().firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = model->getFEM().getMesh().lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { Vector & elem_filter = element_filter(*it, ghost_type); Vector & strain_vect = strain(*it, ghost_type); /// compute @f$\nabla u@f$ model->getFEM().gradientOnQuadraturePoints(displacement, strain_vect, spatial_dimension, *it, ghost_type, &elem_filter); /// compute @f$\mathbf{\sigma}_q@f$ from @f$\nabla u@f$ computeStress(*it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::setToSteadyState(GhostType ghost_type) { AKANTU_DEBUG_IN(); const Vector & displacement = model->getDisplacement(); resizeInternalVector(strain); UInt spatial_dimension = model->getSpatialDimension(); Mesh::type_iterator it = model->getFEM().getMesh().firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = model->getFEM().getMesh().lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { Vector & elem_filter = element_filter(*it, ghost_type); Vector & strain_vect = strain(*it, ghost_type); /// compute @f$\nabla u@f$ model->getFEM().gradientOnQuadraturePoints(displacement, strain_vect, 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(Vector & current_position, GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); Mesh & mesh = model->getFEM().getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { switch(spatial_dimension) { case 1: { assembleStiffnessMatrix<1>(current_position, *it, ghost_type); break; } case 2: { assembleStiffnessMatrix<2>(current_position, *it, ghost_type); break; } case 3: { assembleStiffnessMatrix<3>(current_position, *it, ghost_type); break; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::assembleStiffnessMatrix(Vector & current_position, const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); SparseMatrix & K = const_cast(model->getStiffnessMatrix()); const Vector & shapes_derivatives = model->getFEM().getShapesDerivatives(type,ghost_type); Vector & elem_filter = element_filter(type, ghost_type); Vector & strain_vect = strain(type, ghost_type); UInt * elem_filter_val = elem_filter.storage(); UInt nb_element = elem_filter.getSize(); UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(type, ghost_type); strain_vect.resize(nb_quadrature_points * nb_element); model->getFEM().gradientOnQuadraturePoints(current_position, strain_vect, dim, type, ghost_type, &elem_filter); UInt tangent_size = getTangentStiffnessVoigtSize(dim); Vector * tangent_stiffness_matrix = new Vector(nb_element*nb_quadrature_points, tangent_size * tangent_size, "tangent_stiffness_matrix"); computeTangentStiffness(type, *tangent_stiffness_matrix, ghost_type); /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_d_b_size = dim * nb_nodes_per_element; Vector * bt_d_b = new Vector(nb_element * nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B"); UInt size_of_b = tangent_size * bt_d_b_size; Real * B = new Real[size_of_b]; Real * Bt_D = new Real[size_of_b]; Real * Bt_D_B = bt_d_b->storage(); Real * D = tangent_stiffness_matrix->storage(); UInt offset_bt_d_b = bt_d_b_size * bt_d_b_size; UInt offset_d = tangent_size * tangent_size; for (UInt e = 0; e < nb_element; ++e) { Real * shapes_derivatives_val = shapes_derivatives.values + elem_filter_val[e]*size_of_shapes_derivatives*nb_quadrature_points; for (UInt q = 0; q < nb_quadrature_points; ++q) { transferBMatrixToSymVoigtBMatrix(shapes_derivatives_val, B, nb_nodes_per_element); Math::matrixt_matrix(bt_d_b_size, tangent_size, tangent_size, B, D, Bt_D); Math::matrix_matrix(bt_d_b_size, bt_d_b_size, tangent_size, Bt_D, B, Bt_D_B); shapes_derivatives_val += size_of_shapes_derivatives; D += offset_d; Bt_D_B += offset_bt_d_b; } } delete [] B; delete [] Bt_D; delete tangent_stiffness_matrix; /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Vector * K_e = new Vector(nb_element, bt_d_b_size * bt_d_b_size, "K_e"); model->getFEM().integrate(*bt_d_b, *K_e, bt_d_b_size * bt_d_b_size, type, ghost_type, &elem_filter); delete bt_d_b; model->getFEM().assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, &elem_filter); delete K_e; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if(ghost_type != _not_ghost) return; Real * epot = potential_energy(el_type, ghost_type).storage(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; computePotentialEnergyOnQuad(grad_u, sigma, *epot); epot++; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computePotentialEnergyByElement() { AKANTU_DEBUG_IN(); Mesh & mesh = model->getFEM().getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension); for(; it != last_type; ++it) { if(!potential_energy.exists(*it, _not_ghost)) { UInt nb_element = element_filter(*it, _not_ghost).getSize(); UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(*it, _not_ghost); potential_energy.alloc(nb_element * nb_quadrature_points, 1, *it, _not_ghost); } computePotentialEnergy(*it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real Material::getPotentialEnergy() { AKANTU_DEBUG_IN(); Real epot = 0.; computePotentialEnergyByElement(); /// integrate the potential energy for each type of elements Mesh & mesh = model->getFEM().getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension); for(; it != last_type; ++it) { epot += model->getFEM().integrate(potential_energy(*it, _not_ghost), *it, _not_ghost, &element_filter(*it, _not_ghost)); } AKANTU_DEBUG_OUT(); return epot; } /* -------------------------------------------------------------------------- */ Real Material::getEnergy(std::string type) { AKANTU_DEBUG_IN(); if(type == "potential") return getPotentialEnergy(); AKANTU_DEBUG_OUT(); return 0.; } /* -------------------------------------------------------------------------- */ void Material::computeQuadraturePointsCoordinates(ByElementTypeReal & quadrature_points_coordinates) const { AKANTU_DEBUG_IN(); const Mesh & mesh = model->getFEM().getMesh(); mesh.initByElementTypeVector(quadrature_points_coordinates, spatial_dimension, 0); Vector nodes_coordinates(mesh.getNodes(), true); nodes_coordinates += model->getDisplacement(); for(UInt gt = (UInt) _not_ghost; gt < (UInt) _casper; ++gt) { GhostType ghost_type = (GhostType) gt; Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { const Vector & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_tot_quad = model->getFEM().getNbQuadraturePoints(*it, ghost_type) * nb_element; Vector & quads = quadrature_points_coordinates(*it, ghost_type); quads.resize(nb_tot_quad); model->getFEM().interpolateOnQuadraturePoints(nodes_coordinates, quads, spatial_dimension, *it, ghost_type, &elem_filter); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::initElementalFieldInterpolation(ByElementTypeReal & interpolation_points_coordinates) { AKANTU_DEBUG_IN(); const Mesh & mesh = model->getFEM().getMesh(); ByElementTypeReal quadrature_points_coordinates("quadrature_points_coordinates_tmp_nl", id); computeQuadraturePointsCoordinates(quadrature_points_coordinates); Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator last = mesh.lastType(spatial_dimension); for (; it != last; ++it) { UInt nb_element = mesh.getNbElement(*it); if (nb_element == 0) continue; ElementType type = *it; #define AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD(type) \ initElementalFieldInterpolation(quadrature_points_coordinates(type), \ interpolation_points_coordinates(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 Vector & quad_coordinates, const Vector & interpolation_points_coordinates) { AKANTU_DEBUG_IN(); UInt size_inverse_coords = getSizeElementalFieldInterpolationCoodinates(); Vector & elem_fil = element_filter(type); UInt nb_element = elem_fil.getSize(); UInt nb_quad_per_element = model->getFEM().getNbQuadraturePoints(type); UInt nb_interpolation_points = interpolation_points_coordinates.getSize(); AKANTU_DEBUG_ASSERT(nb_interpolation_points % nb_element == 0, "Can't interpolate elemental field on elements, the coordinates vector has a wrong size"); UInt nb_interpolation_points_per_elem = nb_interpolation_points / nb_element; if(!interpolation_inverse_coordinates.exists(type)) interpolation_inverse_coordinates.alloc(nb_element, size_inverse_coords*size_inverse_coords, type); if(!interpolation_points_matrices.exists(type)) interpolation_points_matrices.alloc(nb_element, nb_interpolation_points_per_elem * size_inverse_coords, type); Vector & interp_inv_coord = interpolation_inverse_coordinates(type); Vector & interp_points_mat = interpolation_points_matrices(type); types::Matrix quad_coord_matrix(size_inverse_coords, size_inverse_coords); Vector::const_iterator quad_coords_it = quad_coordinates.begin_reinterpret(nb_quad_per_element, spatial_dimension, nb_element, nb_quad_per_element * spatial_dimension); Vector::const_iterator points_coords_it = interpolation_points_coordinates.begin_reinterpret(nb_interpolation_points_per_elem, spatial_dimension, nb_element, nb_interpolation_points_per_elem * spatial_dimension); Vector::iterator inv_quad_coord_it = interp_inv_coord.begin(size_inverse_coords, size_inverse_coords); Vector::iterator inv_points_mat_it = interp_points_mat.begin(nb_interpolation_points_per_elem, size_inverse_coords); /// loop over the elements of the current material and element type for (UInt el = 0; el < nb_element; ++el) { /// matrix containing the quadrature points coordinates const types::Matrix & quad_coords = *quad_coords_it; /// matrix to store the matrix inversion result types::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); /// invert the interpolation matrix inv_quad_coord_matrix.inverse(quad_coord_matrix); /// matrix containing the interpolation points coordinates const types::Matrix & points_coords = *points_coords_it; /// matrix to store the interpolation points coordinates /// compatible with these functions types::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_quad_coord_it; ++inv_points_mat_it; ++quad_coords_it; ++points_coords_it; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::interpolateStress(const ElementType type, Vector & result) { AKANTU_DEBUG_IN(); #define INTERPOLATE_ELEMENTAL_FIELD(type) \ interpolateElementalField(stress(type), \ result) \ AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(INTERPOLATE_ELEMENTAL_FIELD); #undef INTERPOLATE_ELEMENTAL_FIELD AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::interpolateElementalField(const Vector & field, Vector & result) { AKANTU_DEBUG_IN(); Vector & elem_fil = element_filter(type); UInt nb_element = elem_fil.getSize(); UInt nb_quad_per_element = model->getFEM().getNbQuadraturePoints(type); UInt size_inverse_coords = getSizeElementalFieldInterpolationCoodinates(); types::Matrix coefficients(nb_quad_per_element, field.getNbComponent()); const Vector & interp_inv_coord = interpolation_inverse_coordinates(type); const Vector & interp_points_coord = interpolation_points_matrices(type); UInt nb_interpolation_points_per_elem = interp_points_coord.getNbComponent() / size_inverse_coords; Vector filtered_field(nb_element, nb_quad_per_element); extractElementalFieldForInterplation(field, filtered_field); Vector::const_iterator field_it = field.begin_reinterpret(nb_quad_per_element, field.getNbComponent(), nb_element, nb_quad_per_element * field.getNbComponent()); Vector::const_iterator interpolation_points_coordinates_it = interp_points_coord.begin(nb_interpolation_points_per_elem, size_inverse_coords); Vector::iterator result_it = result.begin_reinterpret(nb_interpolation_points_per_elem, field.getNbComponent(), nb_element, nb_interpolation_points_per_elem * field.getNbComponent()); Vector::const_iterator inv_quad_coord_it = interp_inv_coord.begin(size_inverse_coords, size_inverse_coords); /// loop over the elements of the current material and element type for (UInt el = 0; el < nb_element; ++el, ++field_it, ++result_it, ++inv_quad_coord_it, ++interpolation_points_coordinates_it) { /** * matrix containing the inversion of the quadrature points' * coordinates */ const types::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 types::Matrix & coord = *interpolation_points_coordinates_it; /// multiply the coordinates matrix by the coefficients matrix and store the result (*result_it).mul(coord, coefficients); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ const Vector & Material::getVector(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 << id << ":" << vect_id << ":" << type << ghost_id; ID fvect_id = sstr.str(); try { return Memory::getVector(fvect_id); } catch(debug::Exception & e) { AKANTU_EXCEPTION("The material " << name << "(" <(ByElementTypeVector & vect, UInt nb_component, ElementKind element_kind) const; template void Material::initInternalVector(ByElementTypeVector & vect, UInt nb_component, ElementKind element_kind) const; template void Material::initInternalVector(ByElementTypeVector & vect, UInt nb_component, ElementKind element_kind) const; template void Material::resizeInternalVector(ByElementTypeVector & vect, ElementKind element_kind) const; template void Material::resizeInternalVector(ByElementTypeVector & vect, ElementKind element_kind) const; template void Material::resizeInternalVector(ByElementTypeVector & vect, ElementKind element_kind) const; __END_AKANTU__ diff --git a/src/model/solid_mechanics/material.hh b/src/model/solid_mechanics/material.hh index ea49175ff..aa592cefd 100644 --- a/src/model/solid_mechanics/material.hh +++ b/src/model/solid_mechanics/material.hh @@ -1,503 +1,505 @@ /** * @file material.hh * @author Nicolas Richart * @date Fri Jul 23 09:06:29 2010 * * @brief Mother class for all materials * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" -//#include "fem.hh" +#include "parser.hh" //#include "mesh.hh" #include "data_accessor.hh" //#include "static_communicator.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_HH__ #define __AKANTU_MATERIAL_HH__ /* -------------------------------------------------------------------------- */ namespace akantu { class Model; class SolidMechanicsModel; class CommunicationBuffer; } __BEGIN_AKANTU__ /** * Interface of all materials * Prerequisites for a new material * - inherit from this class * - implement the following methods: * \code * virtual Real getStableTimeStep(Real h, const Element & element = ElementNull); * * virtual void computeStress(ElementType el_type, * GhostType ghost_type = _not_ghost); * * virtual void computeTangentStiffness(const ElementType & el_type, * Vector & tangent_matrix, * GhostType ghost_type = _not_ghost); * \endcode * */ -class Material : protected Memory, public DataAccessor { +class Material : protected Memory, public DataAccessor, public Parsable { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Material(SolidMechanicsModel & model, const ID & id = ""); virtual ~Material(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// read properties virtual bool setParam(const std::string & key, const std::string & value, const ID & id); /// initialize the material computed parameter virtual void initMaterial(); /// compute the residual for this material virtual void updateResidual(Vector & displacement, GhostType ghost_type = _not_ghost); void assembleResidual(GhostType ghost_type); /// compute the residual for this material virtual void computeAllStresses(Vector & current_position, GhostType ghost_type = _not_ghost); /// set material to steady state void setToSteadyState(GhostType ghost_type = _not_ghost); /// compute the stiffness matrix virtual void assembleStiffnessMatrix(Vector & current_position, GhostType ghost_type); /// compute the stable time step for an element of size h virtual Real getStableTimeStep(Real h, const Element & element = ElementNull) = 0; /// compute the p-wave speed in the material - virtual Real getPushWaveSpeed() { AKANTU_DEBUG_TO_IMPLEMENT(); }; + virtual Real getPushWaveSpeed() const { AKANTU_DEBUG_TO_IMPLEMENT(); }; /// compute the s-wave speed in the material - virtual Real getShearWaveSpeed() { AKANTU_DEBUG_TO_IMPLEMENT(); }; + virtual Real getShearWaveSpeed() const { AKANTU_DEBUG_TO_IMPLEMENT(); }; /// add an element to the local mesh filter inline UInt addElement(const ElementType & type, UInt element, const GhostType & ghost_type); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /** * interpolate stress on given positions for each element by means * of a geometrical interpolation on quadrature points */ virtual void interpolateStress(const ElementType type, Vector & result); /** * function to initialize the elemental field interpolation * function by inverting the quadrature points' coordinates */ virtual void initElementalFieldInterpolation(ByElementTypeReal & interpolation_points_coordinates); protected: /// constitutive law virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost) = 0; /// set the material to steady state (to be implemented for materials that need it) virtual void setToSteadyState(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) {}; /// compute the tangent stiffness matrix virtual void computeTangentStiffness(const ElementType & el_type, Vector & tangent_matrix, GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the potential energy virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); template void assembleStiffnessMatrix(Vector & current_position, const ElementType & type, GhostType ghost_type); /// transfer the B matrix to a Voigt notation B matrix template inline void transferBMatrixToSymVoigtBMatrix(Real * B, Real * Bvoigt, UInt nb_nodes_per_element) const; inline UInt getTangentStiffnessVoigtSize(UInt spatial_dimension) const; /// compute the potential energy by element void computePotentialEnergyByElement(); /// compute the coordinates of the quadrature points void computeQuadraturePointsCoordinates(ByElementTypeReal & quadrature_points_coordinates) const; /// interpolate an elemental field on given points for each element template void interpolateElementalField(const Vector & field, Vector & result); /// template function to initialize the elemental field interpolation template void initElementalFieldInterpolation(const Vector & quad_coordinates, const Vector & interpolation_points_coordinates); /// build the coordinate matrix for the interpolation on elemental field template inline void buildElementalFieldInterpolationCoodinates(const types::Matrix & coordinates, types::Matrix & coordMatrix); /// get the size of the coordiante matrix used in the interpolation template inline UInt getSizeElementalFieldInterpolationCoodinates(); /// extract the field values corresponding to the quadrature points used for the interpolation template inline void extractElementalFieldForInterplation(const Vector & field, Vector & filtered_field); /* ------------------------------------------------------------------------ */ /* Function for all materials */ /* ------------------------------------------------------------------------ */ protected: /// compute the potential energy for on element inline void computePotentialEnergyOnQuad(types::Matrix & grad_u, types::Matrix & sigma, Real & epot); public: /// allocate an internal vector template void initInternalVector(ByElementTypeVector & vect, UInt nb_component, ElementKind element_kind = _ek_regular) const; /// resize an internal vector template void resizeInternalVector(ByElementTypeVector & vect, ElementKind element_kind = _ek_regular) const; /* ------------------------------------------------------------------------ */ template inline void gradUToF(const types::Matrix & grad_u, types::Matrix & F); inline void rightCauchy(const types::Matrix & F, types::Matrix & C); inline void leftCauchy (const types::Matrix & F, types::Matrix & B); /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: virtual inline UInt getNbDataToPack(__attribute__((unused)) const Element & element, __attribute__((unused)) SynchronizationTag tag) const { return 0; } virtual inline UInt getNbDataToUnpack(__attribute__((unused)) const Element & element, __attribute__((unused)) SynchronizationTag tag) const { return 0; } virtual UInt getNbDataToPack(__attribute__((unused)) SynchronizationTag tag) const { return 0; } virtual UInt getNbDataToUnpack(__attribute__((unused)) SynchronizationTag tag) const { return 0; } virtual inline void packData(__attribute__((unused)) CommunicationBuffer & buffer, __attribute__((unused)) const Element & element, __attribute__((unused)) SynchronizationTag tag) const { } virtual void packData(__attribute__((unused)) CommunicationBuffer & buffer, __attribute__((unused)) const UInt index, __attribute__((unused)) SynchronizationTag tag) const { } virtual inline void unpackData(__attribute__((unused)) CommunicationBuffer & buffer, __attribute__((unused)) const Element & element, __attribute__((unused)) SynchronizationTag tag) { } virtual void unpackData(__attribute__((unused)) CommunicationBuffer & buffer, __attribute__((unused)) const UInt index, __attribute__((unused)) SynchronizationTag tag) { } /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(Model, *model, const SolidMechanicsModel &) AKANTU_GET_MACRO(ID, id, const ID &); AKANTU_GET_MACRO(Rho, rho, Real); AKANTU_SET_MACRO(Rho, rho, Real); Real getPotentialEnergy(); virtual Real getEnergy(std::string type); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Strain, strain, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PotentialEnergy, potential_energy, Real); const Vector & getVector(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost) const; virtual Real getProperty(const ID & param) const; virtual void setProperty(const ID & param, Real value); protected: bool isInit() const { return is_init; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the material ID id; /// material name std::string name; /// The model to witch the material belong SolidMechanicsModel * model; /// density : rho Real rho; /// stresses arrays ordered by element types ByElementTypeReal stress; /// strains arrays ordered by element types ByElementTypeReal strain; /// list of element handled by the material ByElementTypeUInt element_filter; /// is the vector for potential energy initialized // bool potential_energy_vector; /// potential energy by element ByElementTypeReal potential_energy; /// tell if using in non local mode or not bool is_non_local; /// spatial dimension UInt spatial_dimension; /// elemental field interpolation coordinates ByElementTypeReal interpolation_inverse_coordinates; /// elemental field interpolation points ByElementTypeReal interpolation_points_matrices; private: /// boolean to know if the material has been initialized bool is_init; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "material_inline_impl.cc" #endif /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Material & _this) { _this.printself(stream); return stream; } __END_AKANTU__ /* -------------------------------------------------------------------------- */ /* Auto loop */ /* -------------------------------------------------------------------------- */ #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN \ Vector::iterator strain_it = \ this->strain(el_type, ghost_type).begin(spatial_dimension, \ spatial_dimension); \ Vector::iterator strain_end = \ this->strain(el_type, ghost_type).end(spatial_dimension, \ spatial_dimension); \ Vector::iterator stress_it = \ this->stress(el_type, ghost_type).begin(spatial_dimension, \ spatial_dimension); \ \ for(;strain_it != strain_end; ++strain_it, ++stress_it) { \ types::Matrix & __attribute__((unused)) grad_u = *strain_it; \ types::Matrix & __attribute__((unused)) sigma = *stress_it #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END \ } \ #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_mat) \ Vector::iterator strain_it = \ this->strain(el_type, ghost_type).begin(spatial_dimension, \ spatial_dimension); \ Vector::iterator strain_end = \ this->strain(el_type, ghost_type).end(spatial_dimension, \ spatial_dimension); \ \ UInt tangent_size = \ this->getTangentStiffnessVoigtSize(spatial_dimension); \ Vector::iterator tangent_it = \ tangent_mat.begin(tangent_size, \ tangent_size); \ \ for(;strain_it != strain_end; ++strain_it, ++tangent_it) { \ types::Matrix & __attribute__((unused)) grad_u = *strain_it; \ types::Matrix & tangent = *tangent_it #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END \ } /* -------------------------------------------------------------------------- */ /* Material list */ /* -------------------------------------------------------------------------- */ #define AKANTU_CORE_MATERIAL_LIST \ ((2, (elastic , MaterialElastic ))) \ ((2, (viscoelastic , MaterialViscoElastic ))) \ ((2, (elastic_orthotropic , MaterialElasticOrthotropic ))) \ ((2, (elastic_caughey , MaterialElasticCaughey ))) \ ((2, (neohookean , MaterialNeohookean ))) #define AKANTU_COHESIVE_MATERIAL_LIST \ ((2, (cohesive_bilinear , MaterialCohesiveBilinear ))) \ ((2, (cohesive_linear , MaterialCohesiveLinear ))) \ ((2, (cohesive_linear_extrinsic, MaterialCohesiveLinearExtrinsic ))) \ ((2, (cohesive_linear_exponential_extrinsic, MaterialCohesiveLinearExponentialExtrinsic ))) \ ((2, (cohesive_exponential , MaterialCohesiveExponential ))) #define AKANTU_DAMAGE_MATERIAL_LIST \ ((2, (damage_linear , MaterialDamageLinear ))) \ ((2, (marigo , MaterialMarigo ))) \ ((2, (mazars , MaterialMazars ))) \ ((2, (vreepeerlings , MaterialVreePeerlings ))) #ifdef AKANTU_DAMAGE_NON_LOCAL #define AKANTU_MATERIAL_WEIGHT_FUNCTION_TMPL_LIST \ ((stress_wf, StressBasedWeightFunction )) \ ((damage_wf, DamagedWeightFunction )) \ ((remove_wf, RemoveDamagedWeightFunction)) \ ((base_wf, BaseWeightFunction )) -# define AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST \ - ((3, (marigo_non_local , MaterialMarigoNonLocal, AKANTU_MATERIAL_WEIGHT_FUNCTION_TMPL_LIST))) \ - ((2, (mazars_non_local , MaterialMazarsNonLocal ))) \ - ((3, (vreepeerlings_non_local, MaterialVreePeerlingsNonLocal, AKANTU_MATERIAL_WEIGHT_FUNCTION_TMPL_LIST))) +#define AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST \ + ((3, (marigo_non_local , MaterialMarigoNonLocal, \ + AKANTU_MATERIAL_WEIGHT_FUNCTION_TMPL_LIST))) \ + ((2, (mazars_non_local , MaterialMazarsNonLocal))) \ + ((3, (vreepeerlings_non_local, MaterialVreePeerlingsNonLocal, \ + AKANTU_MATERIAL_WEIGHT_FUNCTION_TMPL_LIST))) #else # define AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST #endif #define AKANTU_MATERIAL_LIST \ AKANTU_CORE_MATERIAL_LIST \ AKANTU_COHESIVE_MATERIAL_LIST \ AKANTU_DAMAGE_MATERIAL_LIST \ AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST #define INSTANSIATE_MATERIAL(mat_name) \ template class mat_name<1>; \ template class mat_name<2>; \ template class mat_name<3> #if defined(__INTEL_COMPILER) #pragma warning ( push ) /* warning #654: overloaded virtual function "akantu::Material::computeStress" is only partially overridden in class "akantu::Material*" */ #pragma warning ( disable : 654 ) #endif //defined(__INTEL_COMPILER) /* -------------------------------------------------------------------------- */ // elastic materials #include "material_elastic.hh" #include "material_elastic_caughey.hh" #include "material_viscoelastic.hh" #include "material_neohookean.hh" #include "material_elastic_orthotropic.hh" // damage materials #include "material_damage.hh" #include "material_marigo.hh" #include "material_mazars.hh" #include "material_damage_linear.hh" #include "material_vreepeerlings.hh" #if defined(AKANTU_DAMAGE_NON_LOCAL) # include "material_marigo_non_local.hh" # include "material_mazars_non_local.hh" # include "material_vreepeerlings_non_local.hh" #endif // cohesive materials #include "material_cohesive.hh" #include "material_cohesive_linear.hh" #include "material_cohesive_bilinear.hh" #include "material_cohesive_linear_extrinsic.hh" #include "material_cohesive_exponential.hh" #include "material_cohesive_linear_exponential_extrinsic.hh" #if defined(__INTEL_COMPILER) #pragma warning ( pop ) #endif //defined(__INTEL_COMPILER) #endif /* __AKANTU_MATERIAL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.cc b/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.cc index a49e5a548..35ac11ac9 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/material_cohesive.cc @@ -1,644 +1,646 @@ /** * @file material_cohesive.cc * @author Marco Vocialta * @date Tue Feb 7 18:24:52 2012 * * @brief Specialization of the material class for cohesive elements * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "material_cohesive.hh" #include "solid_mechanics_model_cohesive.hh" #include "sparse_matrix.hh" #include "dof_synchronizer.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MaterialCohesive::MaterialCohesive(SolidMechanicsModel & model, const ID & id) : Material(model,id), reversible_energy("reversible_energy", id), total_energy("total_energy", id), tractions_old("tractions (old)",id), opening_old("opening (old)",id), tractions("tractions",id), opening("opening",id), delta_max("delta max",id), damage("damage", id) { AKANTU_DEBUG_IN(); this->model = dynamic_cast(&model); initInternalVector(reversible_energy, 1, _ek_cohesive); initInternalVector(total_energy, 1, _ek_cohesive); initInternalVector(tractions_old, spatial_dimension, _ek_cohesive); initInternalVector(tractions, spatial_dimension, _ek_cohesive); initInternalVector(opening_old, spatial_dimension, _ek_cohesive); initInternalVector(opening, spatial_dimension, _ek_cohesive); initInternalVector(delta_max, 1, _ek_cohesive); initInternalVector(damage, 1, _ek_cohesive); sigma_c = 0; rand = 0; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ MaterialCohesive::~MaterialCohesive() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool MaterialCohesive::setParam(const std::string & key, const std::string & value, const ID & id) { return Material::setParam(key,value,id); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); fem_cohesive = &(model->getFEMClass("CohesiveFEM")); Mesh & mesh = fem_cohesive->getMesh(); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, gt, _ek_cohesive); for(; it != last_type; ++it) { ElementType type = *it; element_filter.alloc(0, 1, type); } } resizeCohesiveVectors(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::resizeCohesiveVectors() { resizeInternalVector(reversible_energy, _ek_cohesive); resizeInternalVector(total_energy, _ek_cohesive); resizeInternalVector(tractions_old, _ek_cohesive); resizeInternalVector(tractions, _ek_cohesive); resizeInternalVector(opening_old, _ek_cohesive); resizeInternalVector(opening, _ek_cohesive); resizeInternalVector(delta_max, _ek_cohesive); resizeInternalVector(damage, _ek_cohesive); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::checkInsertion(const Vector & facet_stress, Vector & facet_insertion) { AKANTU_DEBUG_IN(); Vector & facets_check = model->getFacetsCheck(); ElementType type_facet = model->getFacetType(); UInt nb_quad_facet = model->getFEM("FacetsFEM").getNbQuadraturePoints(type_facet); UInt nb_facet = facets_check.getSize(); Vector stress_check(nb_facet, nb_quad_facet); stress_check.clear(); computeStressNorms(facet_stress, stress_check); bool * facet_check_it = facets_check.storage(); Vector::iterator stress_check_it = stress_check.begin(nb_quad_facet); Real * sigma_limit_it = model->getSigmaLimit().storage(); for (UInt f = 0; f < nb_facet; ++f, ++facet_check_it, ++stress_check_it, ++sigma_limit_it) { if (*facet_check_it == true) { for (UInt q = 0; q < nb_quad_facet; ++q) { if ((*stress_check_it)(q) > *sigma_limit_it) { facet_insertion.push_back(f); for (UInt qs = 0; qs < nb_quad_facet; ++qs) sigma_insertion.push_back((*stress_check_it)(qs)); *facet_check_it = false; break; } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the residual by assembling @f$\int_{e} t_e N_e dS @f$ * * @param[in] displacements nodes displacements * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ void MaterialCohesive::updateResidual(__attribute__((unused)) Vector & displacement, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// compute traction computeTraction(ghost_type); /// update and assemble residual assembleResidual(ghost_type); /// compute energies computeEnergies(); + + /// update old values Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); for(; it != last_type; ++it) { tractions_old(*it, ghost_type).copy(tractions(*it, ghost_type)); opening_old(*it, ghost_type).copy(opening(*it, ghost_type)); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::assembleResidual(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); Vector & residual = const_cast &>(model->getResidual()); Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); for(; it != last_type; ++it) { const Vector & shapes = fem_cohesive->getShapes(*it, ghost_type); Vector & elem_filter = element_filter(*it, ghost_type); Vector & traction = tractions(*it, ghost_type); UInt size_of_shapes = shapes.getNbComponent(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); UInt nb_quadrature_points = fem_cohesive->getNbQuadraturePoints(*it, ghost_type); UInt nb_element = elem_filter.getSize(); /// compute @f$t_i N_a@f$ Real * shapes_val = shapes.storage(); UInt * elem_filter_val = elem_filter.storage(); Vector * shapes_filtered = new Vector(nb_element*nb_quadrature_points, size_of_shapes, "filtered shapes"); Real * shapes_filtered_val = shapes_filtered->values; for (UInt el = 0; el < nb_element; ++el) { shapes_val = shapes.storage() + elem_filter_val[el] * size_of_shapes * nb_quadrature_points; memcpy(shapes_filtered_val, shapes_val, size_of_shapes * nb_quadrature_points * sizeof(Real)); shapes_filtered_val += size_of_shapes * nb_quadrature_points; } shapes_filtered_val = shapes_filtered->values; // multiply traction by shapes Vector * traction_cpy = new Vector(traction); traction_cpy->extendComponentsInterlaced(size_of_shapes, spatial_dimension); Real * traction_cpy_val = traction_cpy->storage(); for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quadrature_points; ++q) { for (UInt n = 0; n < size_of_shapes; ++n,++shapes_filtered_val) { for (UInt i = 0; i < spatial_dimension; ++i) { *traction_cpy_val++ *= *shapes_filtered_val; } } } } delete shapes_filtered; /** * compute @f$\int t \cdot N\, dS@f$ by @f$ \sum_q \mathbf{N}^t * \mathbf{t}_q \overline w_q J_q@f$ */ Vector * int_t_N = new Vector(nb_element, spatial_dimension*size_of_shapes, "int_t_N"); fem_cohesive->integrate(*traction_cpy, *int_t_N, spatial_dimension*size_of_shapes, *it, ghost_type, &elem_filter); delete traction_cpy; int_t_N->extendComponentsInterlaced(2, int_t_N->getNbComponent() ); Real * int_t_N_val = int_t_N->storage(); for (UInt el = 0; el < nb_element; ++el) { for (UInt n = 0; n < size_of_shapes*spatial_dimension; ++n) int_t_N_val[n] *= -1.; int_t_N_val += nb_nodes_per_element*spatial_dimension; } /// assemble model->getFEMBoundary().assembleVector(*int_t_N, residual, model->getDOFSynchronizer().getLocalDOFEquationNumbers(), residual.getNbComponent(), *it, ghost_type, &elem_filter, 1); delete int_t_N; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::assembleStiffnessMatrix(Vector & current_position, GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); SparseMatrix & K = const_cast(model->getStiffnessMatrix()); Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); for(; it != last_type; ++it) { UInt nb_quadrature_points = fem_cohesive->getNbQuadraturePoints(*it, ghost_type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); const Vector & shapes = fem_cohesive->getShapes(*it, ghost_type); Vector & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); UInt size_of_shapes = shapes.getNbComponent(); Real * shapes_val = shapes.storage(); UInt * elem_filter_val = elem_filter.storage(); Vector * shapes_filtered = new Vector(nb_element*nb_quadrature_points, size_of_shapes, "filtered shapes"); Real * shapes_filtered_val = shapes_filtered->values; for (UInt el = 0; el < nb_element; ++el) { shapes_val = shapes.storage() + elem_filter_val[el] * size_of_shapes * nb_quadrature_points; memcpy(shapes_filtered_val, shapes_val, size_of_shapes * nb_quadrature_points * sizeof(Real)); shapes_filtered_val += size_of_shapes * nb_quadrature_points; } shapes_filtered_val = shapes_filtered->values; /** * compute A matrix @f$ \mathbf{A} = \left[\begin{array}{c c c c c c c c c c c c} * 1 & 0 & 0 & 0& 0 & 0 & -1& 0 & 0 &0 &0 &0 \\ * 0 &1& 0&0 &0 &0 &0 & -1& 0& 0 & 0 &0 \\ * 0 &0& 1&0 &0 &0 &0 & 0& -1& 0 & 0 &0 \\ * 0 &0& 0&1 &0 &0 &0 & 0& 0& -1 & 0 &0 \\ * 0 &0& 0&0 &1 &0 &0 & 0& 0& 0 & -1 &0 \\ * 0 &0& 0&0 &0 &1 &0 & 0& 0& 0 & 0 &-1 * \end{array} \right]@f$ **/ UInt size_of_A = spatial_dimension*size_of_shapes*spatial_dimension*nb_nodes_per_element; Real * A = new Real[size_of_A]; memset(A, 0, size_of_A*sizeof(Real)); for ( UInt i = 0; i < spatial_dimension*size_of_shapes; ++i) { A[ spatial_dimension * nb_nodes_per_element * i + i ] = 1; A[ spatial_dimension * nb_nodes_per_element * i + i + spatial_dimension * size_of_shapes ] = -1; } /// compute traction computeTraction(ghost_type); /// get the tangent matrix @f$\frac{\partial{(t/\delta)}}{\partial{\delta}} @f$ Vector * tangent_stiffness_matrix = new Vector(nb_element*nb_quadrature_points, spatial_dimension* spatial_dimension, "tangent_stiffness_matrix"); computeTangentStiffness(*it, *tangent_stiffness_matrix, ghost_type); UInt size_of_N = spatial_dimension*size_of_shapes*spatial_dimension; Real * N = new Real[size_of_N]; UInt size_of_N_A = spatial_dimension*nb_nodes_per_element*spatial_dimension; Real * N_A = new Real[size_of_N_A]; Real * D_N_A = new Real[size_of_N_A]; UInt offset_At_Nt_D_N_A = spatial_dimension*nb_nodes_per_element* spatial_dimension*nb_nodes_per_element; Vector * at_nt_d_n_a = new Vector (nb_element*nb_quadrature_points, offset_At_Nt_D_N_A, "A^t*N^t*D*N*A"); Real * At_Nt_D_N_A = at_nt_d_n_a->storage(); Real * D = tangent_stiffness_matrix->storage(); /** * compute the N matrix @f$ \mathbf{N} = \begin{array}{cccccc} * N_0(\xi) & 0 & N_1(\xi) &0 & N_2(\xi) & 0 \\ * 0 & N_0(\xi)& 0 &N_1(\xi)& 0 & N_2(\xi) * \end{array} @f$ **/ for (UInt e = 0; e < nb_element; ++e) { Real * shapes_val = shapes_filtered_val + e * nb_quadrature_points * size_of_shapes; for (UInt q = 0; q < nb_quadrature_points; ++q) { memset(N, 0, size_of_N * sizeof(Real)); for (UInt i = 0; i < spatial_dimension ; ++i) { Real * Nvoigt_tmp = N + i * (size_of_shapes * spatial_dimension) + i; Real * Nregular = shapes_val + q * (size_of_shapes) ; for (UInt n = 0; n < size_of_shapes; ++n) { *Nvoigt_tmp = *Nregular; Nvoigt_tmp += spatial_dimension; Nregular ++; } } /** * compute stiffness matrix @f$ \mathbf{K} = \delta \mathbf{U}^T * \int_{\Gamma_c} {\mathbf{P}^t \frac{\partial{\mathbf{t}}} {\partial{\delta}} * \mathbf{P} d\Gamma \Delta \mathbf{U}} @f$ **/ Math::matrix_matrix (spatial_dimension, spatial_dimension*nb_nodes_per_element, size_of_shapes*spatial_dimension, N, A, N_A); Math::matrix_matrix (spatial_dimension, spatial_dimension*nb_nodes_per_element, spatial_dimension, D, N_A, D_N_A); Math::matrixt_matrix(spatial_dimension*nb_nodes_per_element, spatial_dimension*nb_nodes_per_element, spatial_dimension, N_A, D_N_A, At_Nt_D_N_A); At_Nt_D_N_A += offset_At_Nt_D_N_A; D += spatial_dimension * spatial_dimension; } } delete [] N; delete [] N_A; delete [] D_N_A; delete tangent_stiffness_matrix; Vector * K_e = new Vector(nb_element, offset_At_Nt_D_N_A , "K_e"); fem_cohesive->integrate(*at_nt_d_n_a, *K_e, offset_At_Nt_D_N_A, *it, ghost_type, &elem_filter); delete at_nt_d_n_a; model->getFEM().assembleMatrix(*K_e, K, spatial_dimension, *it, ghost_type, &elem_filter); delete K_e; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::computeTangentStiffness(const ElementType & el_type, Vector & tangent_matrix, GhostType ghost_type) { UInt nb_quadrature_points = fem_cohesive->getNbQuadraturePoints(el_type, ghost_type); Vector normal(nb_quadrature_points, spatial_dimension, "normal"); computeNormal(model->getCurrentPosition(), normal, el_type, ghost_type); computeTangentStiffness(el_type, tangent_matrix, normal, ghost_type); } /* -------------------------------------------------------------------------- * * Compute traction from displacements * * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ void MaterialCohesive::computeTraction(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); for(; it != last_type; ++it) { Vector & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_quadrature_points = nb_element*fem_cohesive->getNbQuadraturePoints(*it, ghost_type); Vector normal(nb_quadrature_points, spatial_dimension, "normal"); /// compute normals @f$\mathbf{n}@f$ computeNormal(model->getCurrentPosition(), normal, *it, ghost_type); /// compute openings @f$\mathbf{\delta}@f$ computeOpening(model->getDisplacement(), opening(*it, ghost_type), *it, ghost_type); /// compute traction @f$\mathbf{t}@f$ computeTraction(normal, *it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::computeNormal(const Vector & position, Vector & normal, ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); #define COMPUTE_NORMAL(type) \ fem_cohesive->getShapeFunctions(). \ computeNormalsOnControlPoints(position, \ normal, \ ghost_type, \ &(element_filter(type, ghost_type))) AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(COMPUTE_NORMAL); #undef COMPUTE_NORMAL AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::computeOpening(const Vector & displacement, Vector & opening, ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); #define COMPUTE_OPENING(type) \ fem_cohesive->getShapeFunctions(). \ interpolateOnControlPoints(displacement, \ opening, \ spatial_dimension, \ ghost_type, \ &(element_filter(type, ghost_type))) AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(COMPUTE_OPENING); #undef COMPUTE_OPENING AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialCohesive::computeEnergies() { AKANTU_DEBUG_IN(); Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _not_ghost, _ek_cohesive); Real * memory_space = new Real[2*spatial_dimension]; types::RVector b(memory_space, spatial_dimension); types::RVector h(memory_space + spatial_dimension, spatial_dimension); for(; it != last_type; ++it) { Vector::iterator erev = reversible_energy(*it, _not_ghost).begin(); Vector::iterator etot = total_energy(*it, _not_ghost).begin(); Vector::iterator traction_it = tractions(*it, _not_ghost).begin(spatial_dimension); Vector::iterator traction_old_it = tractions_old(*it, _not_ghost).begin(spatial_dimension); Vector::iterator opening_it = opening(*it, _not_ghost).begin(spatial_dimension); Vector::iterator opening_old_it = opening_old(*it, _not_ghost).begin(spatial_dimension); Vector::iteratortraction_end = tractions(*it, _not_ghost).end(spatial_dimension); /// loop on each quadrature point for (; traction_it != traction_end; ++traction_it, ++traction_old_it, ++opening_it, ++opening_old_it, ++erev, ++etot) { /// trapezoidal integration b = *opening_it; b -= *opening_old_it; h = *traction_old_it; h += *traction_it; *etot += .5 * b.dot(h); *erev = .5 * traction_it->dot(*opening_it); } } delete [] memory_space; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real MaterialCohesive::getReversibleEnergy() { AKANTU_DEBUG_IN(); Real erev = 0.; /// integrate the dissipated energy for each type of elements Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _not_ghost, _ek_cohesive); for(; it != last_type; ++it) { erev += fem_cohesive->integrate(reversible_energy(*it, _not_ghost), *it, _not_ghost, &element_filter(*it, _not_ghost)); } AKANTU_DEBUG_OUT(); return erev; } /* -------------------------------------------------------------------------- */ Real MaterialCohesive::getDissipatedEnergy() { AKANTU_DEBUG_IN(); Real edis = 0.; /// integrate the dissipated energy for each type of elements Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _not_ghost, _ek_cohesive); for(; it != last_type; ++it) { Vector dissipated_energy(total_energy(*it, _not_ghost)); dissipated_energy -= reversible_energy(*it, _not_ghost); edis += fem_cohesive->integrate(dissipated_energy, *it, _not_ghost, &element_filter(*it, _not_ghost)); } AKANTU_DEBUG_OUT(); return edis; } /* -------------------------------------------------------------------------- */ Real MaterialCohesive::getEnergy(std::string type) { AKANTU_DEBUG_IN(); if (type == "reversible") return getReversibleEnergy(); else if (type == "dissipated") return getDissipatedEnergy(); AKANTU_DEBUG_OUT(); return 0.; } /* -------------------------------------------------------------------------- */ void MaterialCohesive::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Material Cohesive [" << std::endl; Material::printself(stream, indent + 1); stream << space << "]" << std::endl; } __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_elastic.cc b/src/model/solid_mechanics/materials/material_elastic.cc index 5b9102c8d..1082536fc 100644 --- a/src/model/solid_mechanics/materials/material_elastic.cc +++ b/src/model/solid_mechanics/materials/material_elastic.cc @@ -1,171 +1,171 @@ /** * @file material_elastic.cc * @author Nicolas Richart * @date Tue Jul 27 11:53:52 2010 * * @brief Specialization of the material class for the elastic material * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "material_elastic.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template MaterialElastic::MaterialElastic(SolidMechanicsModel & model, const ID & id) : Material(model, id) { AKANTU_DEBUG_IN(); E = 0; nu = 1./2.; plane_stress = false; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialElastic::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); if (spatial_dimension == 1) nu = 0.; recomputeLameCoefficient(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialElastic::recomputeLameCoefficient() { lambda = nu * E / ((1 + nu) * (1 - 2*nu)); mu = E / (2 * (1 + nu)); if(plane_stress) { //lambda = 2 * lambda * mu / (lambda + 2 * mu); lambda = nu * E / ((1 + nu)*(1 - nu)); } kpa = lambda + 2./3. * mu; } /* -------------------------------------------------------------------------- */ template void MaterialElastic::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; computeStressOnQuad(grad_u, sigma); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialElastic::computeTangentStiffness(__attribute__((unused)) const ElementType & el_type, Vector & tangent_matrix, __attribute__((unused)) GhostType ghost_type) { AKANTU_DEBUG_IN(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); computeTangentStiffnessOnQuad(tangent); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template bool MaterialElastic::setParam(const std::string & key, const std::string & value, const ID & id) { std::stringstream sstr(value); if(key == "E") { sstr >> E; } else if(key == "nu") { sstr >> nu; } else if(key == "Plane_Stress") { sstr >> plane_stress; } else { return Material::setParam(key, value, id); } return true; } /* -------------------------------------------------------------------------- */ template Real MaterialElastic::getProperty(const ID & key) const { if(key == "E") { return E; } else if(key == "nu") { return nu; } else if(key == "lambda") { return nu; } else if(key == "mu") { return mu; } else if(key == "kapa") { return kpa; } else return Material::getProperty(key); } /* -------------------------------------------------------------------------- */ template void MaterialElastic::setProperty(const ID & key, Real value) { if(key == "E") { E = value; recomputeLameCoefficient(); } else if(key == "nu") { nu = value; recomputeLameCoefficient(); } else Material::setProperty(key, value); } /* -------------------------------------------------------------------------- */ template -Real MaterialElastic::getPushWaveSpeed() { +Real MaterialElastic::getPushWaveSpeed() const { return sqrt((lambda + 2*mu)/rho); } /* -------------------------------------------------------------------------- */ template -Real MaterialElastic::getShearWaveSpeed() { +Real MaterialElastic::getShearWaveSpeed() const { return sqrt(mu/rho); } /* -------------------------------------------------------------------------- */ template void MaterialElastic::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "MaterialElastic [" << std::endl; if(!plane_stress) stream << space << " + Plane strain" << std::endl; else stream << space << " + Plane stress" << std::endl; stream << space << " + density : " << rho << std::endl; stream << space << " + Young's modulus : " << E << std::endl; stream << space << " + Poisson's ratio : " << nu << std::endl; if(this->isInit()) { stream << space << " + First Lamé coefficient : " << lambda << std::endl; stream << space << " + Second Lamé coefficient : " << mu << std::endl; stream << space << " + Bulk coefficient : " << kpa << std::endl; } Material::printself(stream, indent + 1); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialElastic); __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_elastic.hh b/src/model/solid_mechanics/materials/material_elastic.hh index f4b6905fa..98e34e5ea 100644 --- a/src/model/solid_mechanics/materials/material_elastic.hh +++ b/src/model/solid_mechanics/materials/material_elastic.hh @@ -1,150 +1,150 @@ /** * @file material_elastic.hh * @author Nicolas Richart * @date Thu Jul 29 15:00:59 2010 * * @brief Material isotropic elastic * * @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 "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_ELASTIC_HH__ #define __AKANTU_MATERIAL_ELASTIC_HH__ __BEGIN_AKANTU__ /** * Material elastic isotropic * * parameters in the material files : * - rho : density (default: 0) * - E : Young's modulus (default: 0) * - nu : Poisson's ratio (default: 1/2) * - Plane_Stress : if 0: plane strain, else: plane stress (default: 0) */ template class MaterialElastic : public virtual Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialElastic(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialElastic() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void initMaterial(); virtual bool setParam(const std::string & key, const std::string & value, const ID & id); /// constitutive law for all element of a type virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the tangent stiffness matrix for an element type void computeTangentStiffness(const ElementType & el_type, Vector & tangent_matrix, GhostType ghost_type = _not_ghost); /// compute the p-wave speed in the material - virtual Real getPushWaveSpeed(); + virtual Real getPushWaveSpeed() const; /// compute the s-wave speed in the material - virtual Real getShearWaveSpeed(); + virtual Real getShearWaveSpeed() const; /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; protected: /// constitutive law for a given quadrature point - inline void computeStressOnQuad(types::Matrix & grad_u, + inline void computeStressOnQuad(const types::Matrix & grad_u, types::Matrix & sigma); /// compute the tangent stiffness matrix for an element void computeTangentStiffnessOnQuad(types::Matrix & tangent); /// recompute the lame coefficient if E or nu changes void recomputeLameCoefficient(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the stable time step inline Real getStableTimeStep(Real h, const Element & element); AKANTU_GET_MACRO(E, E, Real); AKANTU_GET_MACRO(Nu, nu, Real); AKANTU_GET_MACRO(Mu, mu, Real); AKANTU_GET_MACRO(Lambda, lambda, Real); AKANTU_GET_MACRO(Kpa, kpa, Real); AKANTU_GET_MACRO(PlaneStress, plane_stress, bool); void setE(Real E) { this->E = E; recomputeLameCoefficient(); }; void setNu(Real nu) { this->nu = nu; recomputeLameCoefficient(); }; virtual Real getProperty(const ID & param) const; virtual void setProperty(const ID & param, Real value); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the young modulus Real E; /// Poisson coefficient Real nu; /// First Lamé coefficient Real lambda; /// Second Lamé coefficient (shear modulus) Real mu; /// Bulk modulus Real kpa; /// Plane stress or plane strain bool plane_stress; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_elastic_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_MATERIAL_ELASTIC_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_elastic_caughey.cc b/src/model/solid_mechanics/materials/material_elastic_caughey.cc index 446252db0..dc601cfe3 100644 --- a/src/model/solid_mechanics/materials/material_elastic_caughey.cc +++ b/src/model/solid_mechanics/materials/material_elastic_caughey.cc @@ -1,188 +1,187 @@ /** * @file material_elastic_caughey.cc * @author David Kammer * @author Nicolas Richart * @date Wed May 4 15:25:52 2011 * * @brief Special. of the material class for the caughey viscoelastic material * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "material_elastic_caughey.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template MaterialElasticCaughey::MaterialElasticCaughey(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialElastic(model, id), stress_viscosity("stress_viscosity", id), stress_elastic("stress_elastic", id) { AKANTU_DEBUG_IN(); alpha = 0.; this->initInternalVector(this->stress_viscosity, spatial_dimension * spatial_dimension); this->initInternalVector(this->stress_elastic , spatial_dimension * spatial_dimension); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialElasticCaughey::initMaterial() { AKANTU_DEBUG_IN(); MaterialElastic::initMaterial(); this->resizeInternalVector(this->stress_viscosity); this->resizeInternalVector(this->stress_elastic ); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialElasticCaughey::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Vector & elem_filter = this->element_filter (el_type, ghost_type); Vector & stress_visc = stress_viscosity(el_type, ghost_type); Vector & stress_el = stress_elastic (el_type, ghost_type); MaterialElastic::computeStress(el_type, ghost_type); Vector & velocity = this->model->getVelocity(); - UInt nb_elem = this->element_filter(el_type, ghost_type).getSize(); - UInt nb_quad_points_per_elem = - this->model->getFEM().getNbQuadraturePoints(el_type, ghost_type); - UInt nb_quad_points = nb_quad_points_per_elem * nb_elem; +// UInt nb_elem = this->element_filter(el_type, ghost_type).getSize(); +// UInt nb_quad_points_per_elem = +// this->model->getFEM().getNbQuadraturePoints(el_type, ghost_type); +// UInt nb_quad_points = nb_quad_points_per_elem * nb_elem; - Vector strain_rate(nb_quad_points, - spatial_dimension * spatial_dimension, + Vector strain_rate(0, spatial_dimension * spatial_dimension, "strain_rate"); this->model->getFEM().gradientOnQuadraturePoints(velocity, strain_rate, - spatial_dimension, - el_type, ghost_type, &elem_filter); + spatial_dimension, + el_type, ghost_type, &elem_filter); Vector::iterator strain_rate_it = strain_rate.begin(spatial_dimension, spatial_dimension); Vector::iterator stress_visc_it = stress_visc.begin(spatial_dimension, spatial_dimension); Vector::iterator stress_el_it = stress_el.begin(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; types::Matrix & grad_v = *strain_rate_it; types::Matrix & sigma_visc = *stress_visc_it; types::Matrix & sigma_el = *stress_el_it; MaterialElastic::computeStressOnQuad(grad_v, sigma_visc); sigma_visc *= alpha; sigma_el.copy(sigma); sigma += sigma_visc; ++strain_rate_it; ++stress_visc_it; ++stress_el_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialElasticCaughey::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if(ghost_type != _not_ghost) return; Vector & stress_el = stress_elastic(el_type, ghost_type); Vector::iterator stress_el_it = stress_el.begin(spatial_dimension, spatial_dimension); Real * epot = this->potential_energy(el_type, ghost_type).storage(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; types::Matrix & sigma_el = *stress_el_it; Material::computePotentialEnergyOnQuad(grad_u, sigma_el, *epot); epot++; ++stress_el_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template bool MaterialElasticCaughey::setParam(const std::string & key, const std::string & value, const ID & id) { std::stringstream sstr(value); if(key == "alpha") { sstr >> alpha; } else { return MaterialElastic::setParam(key, value, id); } return true; } /* -------------------------------------------------------------------------- */ template Real MaterialElasticCaughey::getProperty(const ID & param) const { if(param == "alpha") { return alpha; } else return Material::getProperty(param); } /* -------------------------------------------------------------------------- */ template void MaterialElasticCaughey::setProperty(const ID & param, Real value) { if(param == "alpha") { alpha = value; } else Material::setProperty(param, value); } /* -------------------------------------------------------------------------- */ template void MaterialElasticCaughey::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "MaterialElasticCaughey [" << std::endl; MaterialElastic::printself(stream, indent + 1); stream << space << " + artifical viscous ratio : " << alpha << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialElasticCaughey); __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_elastic_inline_impl.cc b/src/model/solid_mechanics/materials/material_elastic_inline_impl.cc index 77b9a01a0..a3a628949 100644 --- a/src/model/solid_mechanics/materials/material_elastic_inline_impl.cc +++ b/src/model/solid_mechanics/materials/material_elastic_inline_impl.cc @@ -1,91 +1,96 @@ /** * @file material_elastic_inline_impl.cc * @author Nicolas Richart * @date Tue Jul 27 11:57:43 2010 * * @brief Implementation of the inline functions of the material elastic * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template -inline void MaterialElastic::computeStressOnQuad(types::Matrix & grad_u, +inline void MaterialElastic::computeStressOnQuad(const types::Matrix & grad_u, types::Matrix & sigma) { Real trace = grad_u.trace();/// trace = (\nabla u)_{kk} /// \sigma_{ij} = \lambda * (\nabla u)_{kk} * \delta_{ij} + \mu * (\nabla u_{ij} + \nabla u_{ji}) for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < spatial_dimension; ++j) { sigma(i, j) = (i == j)*lambda*trace + mu*(grad_u(i, j) + grad_u(j, i)); } } } /* -------------------------------------------------------------------------- */ template<> -inline void MaterialElastic<1>::computeStressOnQuad(types::Matrix & grad_u, +inline void MaterialElastic<1>::computeStressOnQuad(const types::Matrix & grad_u, types::Matrix & sigma) { sigma(0, 0) = E*grad_u(0, 0); } /* -------------------------------------------------------------------------- */ template void MaterialElastic::computeTangentStiffnessOnQuad(types::Matrix & tangent) { UInt n = tangent.cols(); - Real Ep = E/((1+nu)*(1-2*nu)); - Real Miiii = Ep * (1-nu); - Real Miijj = Ep * nu; - Real Mijij = Ep * (1-2*nu) * .5; + tangent.clear(); - tangent(0, 0) = Miiii; + //Real Ep = E/((1+nu)*(1-2*nu)); + Real Miiii = lambda + 2*mu; + Real Miijj = lambda; + Real Mijij = mu; + + if(spatial_dimension == 1) + tangent(0, 0) = E; + else + tangent(0, 0) = Miiii; // test of dimension should by optimized out by the compiler due to the template if(spatial_dimension >= 2) { tangent(1, 1) = Miiii; tangent(0, 1) = Miijj; tangent(1, 0) = Miijj; tangent(n - 1, n - 1) = Mijij; } if(spatial_dimension == 3) { tangent(2, 2) = Miiii; tangent(0, 2) = Miijj; tangent(1, 2) = Miijj; tangent(2, 0) = Miijj; tangent(2, 1) = Miijj; tangent(3, 3) = Mijij; tangent(4, 4) = Mijij; } } /* -------------------------------------------------------------------------- */ template inline Real MaterialElastic::getStableTimeStep(Real h, __attribute__ ((unused)) const Element & element) { return (h/getPushWaveSpeed()); } diff --git a/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc b/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc index 0cce45519..ef5c0740e 100644 --- a/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc +++ b/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc @@ -1,215 +1,215 @@ /** * @file material_elastic_orthotropic.cc * @author Marco Vocialta * @date Thu Apr 12 11:28:23 2012 * * @brief Orthotropic elastic material * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "material_elastic_orthotropic.hh" #include "solid_mechanics_model.hh" #include __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template MaterialElasticOrthotropic::MaterialElasticOrthotropic(SolidMechanicsModel & model, const ID & id) : Material(model, id) { AKANTU_DEBUG_IN(); E1 = 0; E2 = 0; E3 = 0; nu12 = 0; nu13 = 0; nu23 = 0; G12 = 0; G13 = 0; G23 = 0; plane_stress = false; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template MaterialElasticOrthotropic::~MaterialElasticOrthotropic() { delete S; } /* -------------------------------------------------------------------------- */ template void MaterialElasticOrthotropic::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); UInt size = this->getTangentStiffnessVoigtSize(spatial_dimension); S = new types::Matrix(size, size); Real Delta; Real nu21 = nu12 * E2 / E1; Real nu31 = nu13 * E3 / E1; Real nu32 = nu23 * E3 / E2; S->clear(); Delta = 1 - nu12 * nu21 - nu23 * nu32 - nu31 * nu13 - 2 * nu21 * nu13 * nu32; (*S)(0,0) = E1 * (1 - nu23 * nu32) / Delta; if(spatial_dimension >= 2) { if(plane_stress) { Delta = 1 - nu12 * nu21; (*S)(0,0) = E1 / Delta; (*S)(1,1) = E2 / Delta; (*S)(0,1) = E1 * nu21 / Delta; (*S)(1,0) = E2 * nu12 / Delta; (*S)(2,2) = G12; } else { (*S)(0,0) = E1 * (1 - nu23 * nu32) / Delta; (*S)(1,1) = E2 * (1 - nu31 * nu13) / Delta; (*S)(0,1) = (*S)(1,0) = E2 * (nu12 + nu32 * nu13) / Delta; (*S)(size - 1,size - 1) = G12; } if (spatial_dimension == 3) { (*S)(2,2) = E3 * (1 - nu12 * nu21) / Delta; (*S)(0,2) = (*S)(2,0) = E1 * (nu31 + nu21 * nu32) / Delta; (*S)(1,2) = (*S)(2,1) = E3 * (nu23 + nu21 * nu13) / Delta; (*S)(4,4) = G23; (*S)(5,5) = G13; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialElasticOrthotropic::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; computeStressOnQuad(grad_u, sigma); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialElasticOrthotropic::computeTangentStiffness(const ElementType & el_type, Vector & tangent_matrix, GhostType ghost_type) { AKANTU_DEBUG_IN(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); tangent.copy(*S); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template bool MaterialElasticOrthotropic::setParam(const std::string & key, const std::string & value, const ID & id) { std::stringstream sstr(value); if(key == "E1") { sstr >> E1; } else if(key == "E2") { sstr >> E2; } else if(key == "E3") { sstr >> E3; } else if(key == "nu12") { sstr >> nu12; } else if(key == "nu13") { sstr >> nu13; } else if(key == "nu23") { sstr >> nu23; } else if(key == "G12") { sstr >> G12; } else if(key == "G13") { sstr >> G13; } else if(key == "G23") { sstr >> G23; } else if(key == "Plane_Stress") { sstr >> plane_stress; } else { return Material::setParam(key, value, id); } return true; } /* -------------------------------------------------------------------------- */ template -Real MaterialElasticOrthotropic::getPushWaveSpeed() { +Real MaterialElasticOrthotropic::getPushWaveSpeed() const { Real Et = (*S)(0,0); if(spatial_dimension >= 2) Et = std::max(Et, (*S)(1,1)); if(spatial_dimension == 3) Et = std::max(Et, (*S)(2,2)); return sqrt( Et / rho); } /* -------------------------------------------------------------------------- */ template -Real MaterialElasticOrthotropic::getShearWaveSpeed() { +Real MaterialElasticOrthotropic::getShearWaveSpeed() const { Real G = 0; if(spatial_dimension == 2) G = (*S)(2,2); if(spatial_dimension == 3) { G = (*S)(3,3); G = std::max(G, (*S)(4,4)); G = std::max(G, (*S)(5,5)); } return sqrt( G / rho); } /* -------------------------------------------------------------------------- */ template void MaterialElasticOrthotropic::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Material<_elastic<_orthotropic> [" << std::endl; if(!plane_stress) stream << space << " + Plane strain" << std::endl; else stream << space << " + Plane stress" << std::endl; stream << space << " + density : " << rho << std::endl; stream << space << " + Young's modulus (x) : " << E1 << std::endl; stream << space << " + Young's modulus (y) : " << E2 << std::endl; stream << space << " + Young's modulus (z) : " << E3 << std::endl; stream << space << " + Poisson's ratio (xy) : " << nu12 << std::endl; stream << space << " + Poisson's ratio (xz) : " << nu13 << std::endl; stream << space << " + Poisson's ratio (yz) : " << nu23 << std::endl; stream << space << " + Shear modulus (xy) : " << G12 << std::endl; stream << space << " + Shear modulus (xz) : " << G13 << std::endl; stream << space << " + Shear modulus (yz) : " << G23 << std::endl; Material::printself(stream, indent + 1); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialElasticOrthotropic); __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_elastic_orthotropic.hh b/src/model/solid_mechanics/materials/material_elastic_orthotropic.hh index 865384e83..9a506852a 100644 --- a/src/model/solid_mechanics/materials/material_elastic_orthotropic.hh +++ b/src/model/solid_mechanics/materials/material_elastic_orthotropic.hh @@ -1,166 +1,166 @@ /** * @file material_elastic_orthotropic.hh * @author Marco Vocialta * @date Thu Apr 12 10:57:52 2012 * * @brief Orthotropic elastic material * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_ELASTIC_ORTHOTROPIC_HH__ #define __AKANTU_MATERIAL_ELASTIC_ORTHOTROPIC_HH__ __BEGIN_AKANTU__ /** * Orthotropic elastic material * \todo extend this law for any material orientation * * parameters in the material files : * - rho : density (default: 0) * - E1 : Young's modulus along x (default: 0) * - E2 : Young's modulus along y (default: 0) * - E3 : Young's modulus along z (default: 0) * - nu12 : Poisson's ratio along xy (default: 0) * - nu13 : Poisson's ratio along xz (default: 0) * - nu23 : Poisson's ratio along yz (default: 0) * - G12 : Shear modulus along xy (default: 0) * - G13 : Shear modulus along xz (default: 0) * - G23 : Shear modulus along yz (default: 0) * - Plane_Stress : if 0: plane strain, else: plane stress (default: 0) */ template class MaterialElasticOrthotropic : public virtual Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialElasticOrthotropic(SolidMechanicsModel & model, const ID & id = ""); ~MaterialElasticOrthotropic(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void initMaterial(); virtual bool setParam(const std::string & key, const std::string & value, const ID & id); /// constitutive law for all element of a type virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the tangent stiffness matrix for an element type void computeTangentStiffness(const ElementType & el_type, Vector & tangent_matrix, GhostType ghost_type = _not_ghost); /// compute the p-wave speed in the material - virtual Real getPushWaveSpeed(); + virtual Real getPushWaveSpeed() const; /// compute the s-wave speed in the material - virtual Real getShearWaveSpeed(); + virtual Real getShearWaveSpeed() const; /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; protected: /// constitutive law for a given quadrature point inline void computeStressOnQuad(types::Matrix & grad_u, types::Matrix & sigma); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the stable time step inline Real getStableTimeStep(Real h, const Element & element); AKANTU_GET_MACRO(E1, E1, Real); AKANTU_GET_MACRO(E2, E2, Real); AKANTU_GET_MACRO(E3, E3, Real); AKANTU_GET_MACRO(Nu12, nu12, Real); AKANTU_GET_MACRO(Nu13, nu13, Real); AKANTU_GET_MACRO(Nu23, nu23, Real); AKANTU_GET_MACRO(G12, G12, Real); AKANTU_GET_MACRO(G13, G13, Real); AKANTU_GET_MACRO(G23, G23, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the x young modulus Real E1; /// the y young modulus Real E2; /// the z young modulus Real E3; /// xy Poisson coefficient Real nu12; /// xz Poisson coefficient Real nu13; /// yz Poisson coefficient Real nu23; /// xy shear modulus Real G12; /// xz shear modulus Real G13; /// yz shear modulus Real G23; /// stiffness coefficients types::Matrix * S; /// Plane stress or plane strain bool plane_stress; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_elastic_orthotropic_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_MATERIAL_ELASTIC_ORTHOTROPIC_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_marigo.cc b/src/model/solid_mechanics/materials/material_marigo.cc index cec718db8..0a730e194 100644 --- a/src/model/solid_mechanics/materials/material_marigo.cc +++ b/src/model/solid_mechanics/materials/material_marigo.cc @@ -1,155 +1,171 @@ /** * @file material_marigo.cc * @author Nicolas Richart * @author Guillaume Anciaux * @author Marion Chambart * @date Tue Jul 27 11:53:52 2010 * * @brief Specialization of the material class for the marigo material * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "material_marigo.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template MaterialMarigo::MaterialMarigo(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialElastic(model, id), MaterialDamage(model, id), Yd_rand("Yd_rand",id), damage_in_y(false), yc_limit(false) { AKANTU_DEBUG_IN(); Yd = 50; Sd = 5000; Yd_randomness = 0.; epsilon_c = 0.; this->initInternalVector(this->Yd_rand, 1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialMarigo::initMaterial() { AKANTU_DEBUG_IN(); MaterialDamage::initMaterial(); Yc = .5 * epsilon_c * this->E * epsilon_c; this->resizeInternalVector(this->Yd_rand); const Mesh & mesh = this->model->getFEM().getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension); for(; it != last_type; ++it) { UInt nb_element = this->element_filter(*it).getSize(); UInt nb_quad = this->model->getFEM().getNbQuadraturePoints(*it); Vector & Yd_rand_vec = Yd_rand(*it); for(UInt e = 0; e < nb_element; ++e) { Real rand_part = (2 * drand48()-1) * Yd_randomness * Yd; for(UInt q = 0; q < nb_quad; ++q) Yd_rand_vec(nb_quad*e+q,0) = Yd + rand_part; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialMarigo::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = this->damage(el_type, ghost_type).storage(); Real * Yd_q = Yd_rand(el_type, ghost_type).storage(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; Real Y = 0; computeStressOnQuad(grad_u, sigma, *dam, Y, *Yd_q); ++dam; ++Yd_q; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; if(!this->is_non_local) this->updateDissipatedEnergy(ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template bool MaterialMarigo::setParam(const std::string & key, const std::string & value, const ID & id) { std::stringstream sstr(value); if(key == "Yd") { sstr >> Yd; } else if(key == "Sd") { sstr >> Sd; } else if(key == "Yd_randomness") { sstr >> Yd_randomness; } else if(key == "epsilon_c") { sstr >> epsilon_c; yc_limit = true; } else if(key == "damage_in_y") { sstr >> damage_in_y; } else { return MaterialDamage::setParam(key, value, id); } return true; } +/* -------------------------------------------------------------------------- */ +template +Real MaterialMarigo::getProperty(const ID & key) const { + if(key == "Yd") { return this->Yd; } + else if(key == "Sd") { return this->Sd; } + else return MaterialElastic::getProperty(key); +} + +/* -------------------------------------------------------------------------- */ +template +void MaterialMarigo::setProperty(const ID & key, + Real value) { + if(key == "Yd") { this->Yd = value; } + else if(key == "Sd") { this->Sd = value; } + else MaterialElastic::setProperty(key, value); +} /* -------------------------------------------------------------------------- */ template void MaterialMarigo::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "MaterialMarigo [" << std::endl; stream << space << " + Yd : " << Yd << std::endl; stream << space << " + Sd : " << Sd << std::endl; stream << space << " + randomness : " << Yd_randomness << std::endl; if (yc_limit) { stream << space << " + epsilon_c : " << epsilon_c << std::endl; stream << space << " + Yc : " << Yc << std::endl; } if (damage_in_y) stream << space << " + damage in y: true" << std::endl; MaterialDamage::printself(stream, indent + 1); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialMarigo); __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_marigo.hh b/src/model/solid_mechanics/materials/material_marigo.hh index 39bb5a190..b47ea90d1 100644 --- a/src/model/solid_mechanics/materials/material_marigo.hh +++ b/src/model/solid_mechanics/materials/material_marigo.hh @@ -1,155 +1,158 @@ /** * @file material_marigo.hh * @author Nicolas Richart * @author Guillaume Anciaux * @author Marion Chambart * @date Thu Jul 29 15:00:59 2010 * * @brief Material isotropic elastic * * @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 "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_MARIGO_HH__ #define __AKANTU_MATERIAL_MARIGO_HH__ __BEGIN_AKANTU__ /** * Material marigo * * parameters in the material files : * - Yd : (default: 50) * - Sd : (default: 5000) * - Ydrandomness : (default:0) */ template class MaterialMarigo : public MaterialDamage { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialMarigo(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialMarigo() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); bool setParam(const std::string & key, const std::string & value, const ID & id); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; protected: /// constitutive law for a given quadrature point inline void computeStressOnQuad(types::Matrix & grad_u, types::Matrix & sigma, Real & dam, Real & Y, Real & Ydq); inline void computeDamageAndStressOnQuad(types::Matrix & sigma, Real & dam, Real & Y, Real & Ydq); /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: inline virtual UInt getNbDataToPack(const Element & element, SynchronizationTag tag) const; inline virtual UInt getNbDataToUnpack(const Element & element, SynchronizationTag tag) const; inline virtual void packData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag) const; inline virtual void unpackData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag); virtual UInt getNbDataToPack(__attribute__((unused)) SynchronizationTag tag) const { return 0; } virtual UInt getNbDataToUnpack(__attribute__((unused)) SynchronizationTag tag) const { return 0; } virtual void packData(__attribute__((unused)) CommunicationBuffer & buffer, __attribute__((unused)) const UInt index, __attribute__((unused)) SynchronizationTag tag) const { } virtual void unpackData(__attribute__((unused)) CommunicationBuffer & buffer, __attribute__((unused)) const UInt index, __attribute__((unused)) SynchronizationTag tag) { } /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: + virtual Real getProperty(const ID & param) const; + virtual void setProperty(const ID & param, Real value); + /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// resistance to damage Real Yd; /// damage threshold Real Sd; /// randomness on Yd Real Yd_randomness; /// critical epsilon when the material is considered as broken Real epsilon_c; Real Yc; /// Yd random internal variable ByElementTypeReal Yd_rand; bool damage_in_y; bool yc_limit; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_marigo_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_MATERIAL_MARIGO_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_mazars.cc b/src/model/solid_mechanics/materials/material_mazars.cc index 19ffe6845..2532df89a 100644 --- a/src/model/solid_mechanics/materials/material_mazars.cc +++ b/src/model/solid_mechanics/materials/material_mazars.cc @@ -1,123 +1,123 @@ /** * @file material_mazars.cc * @author Nicolas Richart * @author Guillaume Anciaux * @author Marion Chambart * @date Tue Jul 27 11:53:52 2010 * * @brief Specialization of the material class for the damage material * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "material_mazars.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template MaterialMazars::MaterialMazars(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialElastic(model, id), MaterialDamage(model, id), damage_in_compute_stress(true) { AKANTU_DEBUG_IN(); + K0 = 1e-4; At = 0.8; Ac = 1.4; Bc = 1900; Bt = 12000; beta = 1.06; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialMazars::initMaterial() { AKANTU_DEBUG_IN(); MaterialDamage::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialMazars::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * dam = this->damage(el_type, ghost_type).storage(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; - Real Ehat; + Real Ehat = 0; computeStressOnQuad(grad_u, sigma, *dam, Ehat); ++dam; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; - if(!this->is_non_local) this->updateDissipatedEnergy(ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template bool MaterialMazars::setParam(const std::string & key, const std::string & value, const ID & id) { std::stringstream sstr(value); if(key == "K0") { sstr >> K0; } else if(key == "At") { sstr >> At; } else if(key == "Bt") { sstr >> Bt; } else if(key == "Ac") { sstr >> Ac; } else if(key == "Bc") { sstr >> Bc; } else if(key == "beta") { sstr >> beta; } else { return MaterialDamage::setParam(key, value, id); } return true; } /* -------------------------------------------------------------------------- */ template void MaterialMazars::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "MaterialMazars [" << std::endl; stream << space << " + K0 : " << K0 << std::endl; stream << space << " + At : " << At << std::endl; stream << space << " + Bt : " << Bt << std::endl; stream << space << " + Ac : " << Ac << std::endl; stream << space << " + Bc : " << Bc << std::endl; stream << space << " + beta : " << beta << std::endl; MaterialDamage::printself(stream, indent + 1); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialMazars); __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_mazars.hh b/src/model/solid_mechanics/materials/material_mazars.hh index a32af0ad6..3998cbd7b 100644 --- a/src/model/solid_mechanics/materials/material_mazars.hh +++ b/src/model/solid_mechanics/materials/material_mazars.hh @@ -1,131 +1,132 @@ /** * @file material_mazars.hh * @author Nicolas Richart * @author Guillaume Anciaux * @author Marion Chambart * @date Thu Jul 29 15:00:59 2010 * * @brief Material Following the Mazars law for damage evolution * * @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 "material_damage.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_MAZARS_HH__ #define __AKANTU_MATERIAL_MAZARS_HH__ __BEGIN_AKANTU__ /** * Material Mazars * * parameters in the material files : * - rho : density (default: 0) * - E : Young's modulus (default: 0) * - nu : Poisson's ratio (default: 1/2) * - K0 : Damage threshold * - At : Parameter damage traction 1 * - Bt : Parameter damage traction 2 * - Ac : Parameter damage compression 1 * - Bc : Parameter damage compression 2 * - beta : Parameter for shear */ template class MaterialMazars : public MaterialDamage { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialMazars(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialMazars() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); virtual bool setParam(const std::string & key, const std::string & value, const ID & id); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; protected: /// constitutive law for a given quadrature point - inline void computeStressOnQuad(types::Matrix & grad_u, + inline void computeStressOnQuad(const types::Matrix & grad_u, types::Matrix & sigma, Real & damage, Real & Ehat); - inline void computeDamageAndStressOnQuad(types::Matrix & grad_u, + inline void computeDamageAndStressOnQuad(const types::Matrix & grad_u, types::Matrix & sigma, Real & damage, Real & Ehat); - inline void computeDamageOnQuad(const Real & Ehat, - const types::RVector & FDiag, + inline void computeDamageOnQuad(const Real & epsilon_equ, + const types::Matrix & sigma, + const types::RVector & epsilon_princ, Real & dam); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// damage threshold Real K0; ///parameter damage traction 1 Real At ; ///parameter damage traction 2 Real Bt ; ///parameter damage compression 1 Real Ac ; ///parameter damage compression 2 Real Bc ; ///parameter for shear Real beta ; /// specify the variable to average false = ehat, true = damage (only valid for non local version) bool damage_in_compute_stress; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_mazars_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_MATERIAL_MAZARS_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_mazars_inline_impl.cc b/src/model/solid_mechanics/materials/material_mazars_inline_impl.cc index 7aa90c3b6..e239f31b3 100644 --- a/src/model/solid_mechanics/materials/material_mazars_inline_impl.cc +++ b/src/model/solid_mechanics/materials/material_mazars_inline_impl.cc @@ -1,140 +1,180 @@ /** * @file material_mazars_inline_impl.cc * @author Nicolas Richart * @author Marion Chambart * @date Tue Jul 27 11:57:43 2010 * * @brief Implementation of the inline functions of the material damage * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template inline void -MaterialMazars::computeStressOnQuad(types::Matrix & grad_u, +MaterialMazars::computeStressOnQuad(const types::Matrix & grad_u, types::Matrix & sigma, Real & dam, Real & Ehat) { - types::RVector Fdiag(3); - Fdiag.clear(); - types::RVector Fdiagp(3); - Fdiagp.clear(); + types::Matrix epsilon(3, 3); + epsilon.clear(); - Math::eigenvalues(grad_u.storage(), Fdiag.storage()); + for (UInt i = 0; i < spatial_dimension; ++i) + for (UInt j = 0; j < spatial_dimension; ++j) + epsilon(i,j) = .5*(grad_u(i,j) + grad_u(j,i)); - Fdiagp(0) = std::max(0., Fdiag(0)); - Fdiagp(1) = std::max(0., Fdiag(1)); - Fdiagp(2) = std::max(0., Fdiag(2)); + types::RVector Fdiag(3); + Math::matrixEig(3, epsilon.storage(), Fdiag.storage()); - Ehat = sqrt(Fdiagp(0)*Fdiagp(0) + Fdiagp(1)*Fdiagp(1) + Fdiagp(2)*Fdiagp(2)); + Ehat = 0.; + for (UInt i = 0; i < 3; ++i) { + Real epsilon_p = std::max(0., Fdiag(i)); + Ehat += epsilon_p * epsilon_p; + } + Ehat = sqrt(Ehat); MaterialElastic::computeStressOnQuad(grad_u, sigma); if(damage_in_compute_stress) { - computeDamageOnQuad(Ehat, Fdiag, dam); + computeDamageOnQuad(Ehat, sigma, Fdiag, dam); } if(!this->is_non_local) { computeDamageAndStressOnQuad(grad_u, sigma, dam, Ehat); } } /* -------------------------------------------------------------------------- */ template inline void -MaterialMazars::computeDamageAndStressOnQuad(types::Matrix & grad_u, +MaterialMazars::computeDamageAndStressOnQuad(const types::Matrix & grad_u, types::Matrix & sigma, Real & dam, Real & Ehat) { if(!damage_in_compute_stress) { types::RVector Fdiag(3); Fdiag.clear(); - Math::eigenvalues(grad_u.storage(), Fdiag.storage()); - computeDamageOnQuad(Ehat, Fdiag, dam); + types::Matrix epsilon(3, 3); + epsilon.clear(); + for (UInt i = 0; i < spatial_dimension; ++i) + for (UInt j = 0; j < spatial_dimension; ++j) + epsilon(i,j) = .5*(grad_u(i,j) + grad_u(j,i)); + + Math::matrixEig(3, epsilon.storage(), Fdiag.storage()); + + computeDamageOnQuad(Ehat, sigma, Fdiag, dam); } sigma *= 1 - dam; } /* -------------------------------------------------------------------------- */ template inline void -MaterialMazars::computeDamageOnQuad(const Real & Ehat, - const types::RVector & Fdiag, +MaterialMazars::computeDamageOnQuad(const Real & epsilon_equ, + const types::Matrix & sigma, + const types::RVector & epsilon_princ, Real & dam) { - Real Fs = Ehat - K0; +// if (epsilon_equ > K0) { +// Real dam_t; +// Real dam_c; +// dam_t = 1 - K0*(1 - At)/epsilon_equ - At / exp(Bt*(epsilon_equ - K0)); +// dam_c = 1 - K0*(1 - Ac)/epsilon_equ - Ac / exp(Bc*(epsilon_equ - K0)); +// +// dam_t = std::min(1., std::max(0., dam_t)); +// dam_c = std::min(1., std::max(0., dam_c)); +// +// types::RVector sigma_diag(3); +// Math::matrixEig(3, sigma.storage(), sigma_diag.storage()); +// +// types::RVector sigma_p(3); +// for (UInt i = 0; i < 3; ++i) sigma_p(i) = std::max(0., sigma_diag(i)); +// +// sigma_p *= 1-dam; +// +// Real trace_p = this->nu / this->E * (sigma_p(0) + sigma_p(1) + sigma_p(2)); +// +// Real alpha_t = 0; +// for (UInt i = 0; i < 3; ++i) { +// Real epsilon_t = (1 + this->nu)/this->E * sigma_p(i) - trace_p; +// Real epsilon_p = std::max(0., epsilon_princ(i)); +// alpha_t += epsilon_t * epsilon_p; +// } +// +// alpha_t /= epsilon_equ * epsilon_equ; +// alpha_t = std::max(0., std::min(alpha_t, 1.)); +// +// Real alpha_c = 1 - alpha_t; +// +// alpha_t = std::pow(alpha_t, beta); +// alpha_c = std::pow(alpha_c, beta); +// +// Real damtemp; +// damtemp = alpha_t * dam_t + alpha_c * dam_c; +// dam = std::max(damtemp, dam); +// dam = std::min(dam,1.); +// } + Real Fs = epsilon_equ - K0; if (Fs > 0.) { - types::RVector Fdiagp(3); - Fdiagp.clear(); - - Fdiagp(0) = std::max(0., Fdiag(0)); - Fdiagp(1) = std::max(0., Fdiag(1)); - Fdiagp(2) = std::max(0., Fdiag(2)); - - Real damt; - Real damc; - damt = 1 - K0*(1 - At)/Ehat - At*(exp(-Bt*(Ehat - K0))); - damc = 1 - K0*(1 - Ac)/Ehat - Ac*(exp(-Bc*(Ehat - K0))); + Real dam_t; + Real dam_c; + dam_t = 1 - K0*(1 - At)/epsilon_equ - At*(exp(-Bt*(epsilon_equ - K0))); + dam_c = 1 - K0*(1 - Ac)/epsilon_equ - Ac*(exp(-Bc*(epsilon_equ - K0))); Real Cdiag; Cdiag = this->E*(1-this->nu)/((1+this->nu)*(1-2*this->nu)); - - types::RVector SigDiag(3); - SigDiag(0) = Cdiag*Fdiag(0) + this->lambda*(Fdiag(1) + Fdiag(2)); - SigDiag(1) = Cdiag*Fdiag(1) + this->lambda*(Fdiag(0) + Fdiag(2)); - SigDiag(2) = Cdiag*Fdiag(2) + this->lambda*(Fdiag(1) + Fdiag(0)); - - types::RVector SigDiagT(3); - for (UInt i = 0; i < 3; i++) { - if(SigDiag(i) >= 0.) { - SigDiagT(i) = SigDiag(i); - } else { - SigDiagT(i) = 0.; - } - } - Real TraSigT; - TraSigT = SigDiagT(0) + SigDiagT(1) + SigDiagT(2); + types::RVector sigma_princ(3); + sigma_princ(0) = Cdiag*epsilon_princ(0) + this->lambda*(epsilon_princ(1) + epsilon_princ(2)); + sigma_princ(1) = Cdiag*epsilon_princ(1) + this->lambda*(epsilon_princ(0) + epsilon_princ(2)); + sigma_princ(2) = Cdiag*epsilon_princ(2) + this->lambda*(epsilon_princ(1) + epsilon_princ(0)); + + types::RVector sigma_p(3); + for (UInt i = 0; i < 3; i++) sigma_p(i) = std::max(0., sigma_princ(i)); + sigma_p *= 1-dam; - types::RVector FDiagT(3); - for (UInt i = 0; i < 3; i++){ - FDiagT (i)= (SigDiagT(i)*(1 + this->nu) - TraSigT*this->nu)/this->E; + Real trace_p = this->nu / this->E * (sigma_p(0) + sigma_p(1) + sigma_p(2)); + + Real alpha_t = 0; + for (UInt i = 0; i < 3; ++i) { + Real epsilon_t = (1 + this->nu)/this->E * sigma_p(i) - trace_p; + Real epsilon_p = std::max(0., epsilon_princ(i)); + alpha_t += epsilon_t * epsilon_p; } - Real alphat; - alphat = (FDiagT(0)*Fdiagp(0) + FDiagT(1)*Fdiagp(1) + FDiagT(2)*Fdiagp(2))/(Ehat*Ehat); - alphat = std::min(alphat, 1.); + alpha_t /= epsilon_equ * epsilon_equ; + alpha_t = std::min(alpha_t, 1.); + + Real alpha_c = 1 - alpha_t; - Real alphac; - alphac = 1 - alphat; + alpha_t = std::pow(alpha_t, beta); + alpha_c = std::pow(alpha_c, beta); Real damtemp; - damtemp = pow(alphat,beta)*damt + pow(alphac,beta)*damc; + damtemp = alpha_t * dam_t + alpha_c * dam_c; dam = std::max(damtemp, dam); + dam = std::min(dam,1.); } - - dam = std::min(dam,1.); } diff --git a/src/model/solid_mechanics/materials/material_mazars_non_local.cc b/src/model/solid_mechanics/materials/material_mazars_non_local.cc index dd62f8b75..e195b4441 100644 --- a/src/model/solid_mechanics/materials/material_mazars_non_local.cc +++ b/src/model/solid_mechanics/materials/material_mazars_non_local.cc @@ -1,179 +1,177 @@ /** * @file material_mazars_non_local.cc * @author Nicolas Richart * @author Marion Chambart * @date Tue Jul 27 11:53:52 2010 * * @brief Specialization of the material class for the non-local mazars material * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "material_mazars_non_local.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template MaterialMazarsNonLocal::MaterialMazarsNonLocal(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialElastic(model, id), MaterialMazars(model, id), MaterialNonLocalParent(model, id), - Ehat("equistrain", id) { + Ehat("epsilon_equ", id) { AKANTU_DEBUG_IN(); this->damage_in_compute_stress = false; this->is_non_local = true; this->initInternalVector(this->Ehat, 1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialMazarsNonLocal::initMaterial() { AKANTU_DEBUG_IN(); MaterialMazars::initMaterial(); MaterialNonLocalParent::initMaterial(); this->resizeInternalVector(this->Ehat); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialMazarsNonLocal::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); - Real * dam = this->damage(el_type, ghost_type).storage(); - Real * Ehatt = this->Ehat(el_type, ghost_type).storage(); + Real * damage = this->damage(el_type, ghost_type).storage(); + Real * epsilon_equ = this->Ehat(el_type, ghost_type).storage(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; MaterialMazars::computeStressOnQuad(grad_u, sigma, - *dam, *Ehatt); - ++dam; - ++Ehatt; + *damage, + *epsilon_equ); + ++damage; + ++epsilon_equ; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialMazarsNonLocal::computeNonLocalStress(GhostType ghost_type) { AKANTU_DEBUG_IN(); ByElementTypeReal nl_var("Non local variable", this->id); this->initInternalVector(nl_var, 1); this->resizeInternalVector(nl_var); if(this->damage_in_compute_stress) this->weightedAvergageOnNeighbours(this->damage, nl_var, 1); else this->weightedAvergageOnNeighbours(this->Ehat, nl_var, 1); Mesh::type_iterator it = this->model->getFEM().getMesh().firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = this->model->getFEM().getMesh().lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { this->computeNonLocalStress(nl_var(*it, ghost_type), *it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialMazarsNonLocal::computeNonLocalStress(Vector & non_loc_var, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); - Real * not_averaged; - if(this->damage_in_compute_stress) - not_averaged = this->Ehat(el_type, ghost_type).storage(); - else - not_averaged = this->damage(el_type, ghost_type).storage(); - - Real * nl_var = non_loc_var.storage(); + Real * damage; + Real * epsilon_equ; + if(this->damage_in_compute_stress){ + damage = non_loc_var.storage(); + epsilon_equ = this->Ehat(el_type, ghost_type).storage(); + } else { + damage = this->damage(el_type, ghost_type).storage(); + epsilon_equ = non_loc_var.storage(); + } MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; + this->computeDamageAndStressOnQuad(grad_u, sigma, *damage, *epsilon_equ); - if (this->damage_in_compute_stress) - this->computeDamageAndStressOnQuad(grad_u, sigma, *nl_var, *not_averaged); - else - this->computeDamageAndStressOnQuad(grad_u, sigma, *not_averaged, *nl_var); - - ++not_averaged; - ++nl_var; - + ++damage; + ++epsilon_equ; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; this->updateDissipatedEnergy(ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template bool MaterialMazarsNonLocal::setParam(const std::string & key, const std::string & value, const ID & id) { std::stringstream sstr(value); if(key == "average_on_damage") { sstr >> this->damage_in_compute_stress; } else { return MaterialNonLocalParent::setParam(key, value, id) || MaterialMazars::setParam(key, value, id); } return true; } /* -------------------------------------------------------------------------- */ template void MaterialMazarsNonLocal::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "MaterialMazarsNonLocal [" << std::endl; if(this->damage_in_compute_stress) stream << space << " + Average on damage" << std::endl; else stream << space << " + Average on Ehat" << std::endl; MaterialMazars::printself(stream, indent + 1); MaterialNonLocalParent::printself(stream, indent + 1); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialMazarsNonLocal); __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc b/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc index 6776095dd..1b1972d36 100644 --- a/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc +++ b/src/model/solid_mechanics/materials/material_non_local_inline_impl.cc @@ -1,555 +1,562 @@ /** * @file material_non_local_inline_impl.cc * @author Nicolas Richart * @date Thu Aug 25 11:59:39 2011 * * @brief * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ __END_AKANTU__ /* -------------------------------------------------------------------------- */ #include "aka_types.hh" #include "grid_synchronizer.hh" #include "synchronizer_registry.hh" +#include "integrator.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template class WeightFunction> MaterialNonLocal::MaterialNonLocal(SolidMechanicsModel & model, const ID & id) : Material(model, id), radius(100.), weight_func(NULL), cell_list(NULL), update_weigths(0), compute_stress_calls(0) { AKANTU_DEBUG_IN(); this->is_non_local = true; this->weight_func = new WeightFunction(*this); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template class WeightFunction> MaterialNonLocal::~MaterialNonLocal() { AKANTU_DEBUG_IN(); delete cell_list; delete weight_func; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template class WeightFunction> void MaterialNonLocal::initMaterial() { AKANTU_DEBUG_IN(); // Material::initMaterial(); ByElementTypeReal quadrature_points_coordinates("quadrature_points_coordinates_tmp_nl", id); computeQuadraturePointsCoordinates(quadrature_points_coordinates); weight_func->setRadius(radius); weight_func->init(); createCellList(quadrature_points_coordinates); updatePairList(quadrature_points_coordinates); computeWeights(quadrature_points_coordinates); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template class WeightFunction> void MaterialNonLocal::updateResidual(Vector & displacement, GhostType ghost_type) { AKANTU_DEBUG_IN(); // Update the weights for the non local variable averaging if(ghost_type == _not_ghost && this->update_weigths && (this->compute_stress_calls % this->update_weigths == 0)) { ByElementTypeReal quadrature_points_coordinates("quadrature_points_coordinates", id); computeQuadraturePointsCoordinates(quadrature_points_coordinates); computeWeights(quadrature_points_coordinates); } if(ghost_type == _not_ghost) ++this->compute_stress_calls; computeAllStresses(displacement, ghost_type); computeNonLocalStress(ghost_type); assembleResidual(ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template class WeightFunction> template void MaterialNonLocal::weightedAvergageOnNeighbours(const ByElementTypeVector & to_accumulate, ByElementTypeVector & accumulated, UInt nb_degree_of_freedom) const { AKANTU_DEBUG_IN(); std::set< std::pair >::const_iterator first_pair_types = existing_pairs.begin(); std::set< std::pair >::const_iterator last_pair_types = existing_pairs.end(); GhostType ghost_type1, ghost_type2; ghost_type1 = ghost_type2 = _not_ghost; for (; first_pair_types != last_pair_types; ++first_pair_types) { const Vector & pairs = pair_list(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2); const Vector & weights = pair_weight(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2); const Vector & to_acc = to_accumulate(first_pair_types->second, ghost_type2); Vector & acc = accumulated(first_pair_types->first, ghost_type1); acc.resize(to_acc.getSize()); acc.clear(); Vector::const_iterator< types::Vector > first_pair = pairs.begin(2); Vector::const_iterator< types::Vector > last_pair = pairs.end(2); Vector::const_iterator< types::Vector > pair_w = weights.begin(2); for(;first_pair != last_pair; ++first_pair, ++pair_w) { UInt q1 = (*first_pair)(0); UInt q2 = (*first_pair)(1); for(UInt d = 0; d < nb_degree_of_freedom; ++d){ acc(q1, d) += (*pair_w)(0) * to_acc(q2, d); acc(q2, d) += (*pair_w)(1) * to_acc(q1, d); } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template class WeightFunction> void MaterialNonLocal::createCellList(const ByElementTypeReal & quadrature_points_coordinates) { AKANTU_DEBUG_IN(); const Real safety_factor = 1.2; // for the cell grid spacing Mesh & mesh = this->model->getFEM().getMesh(); mesh.computeBoundingBox(); Real lower_bounds[spatial_dimension]; Real upper_bounds[spatial_dimension]; mesh.getLocalLowerBounds(lower_bounds); mesh.getLocalUpperBounds(upper_bounds); Real spacing[spatial_dimension]; for (UInt i = 0; i < spatial_dimension; ++i) { spacing[i] = radius * safety_factor; } cell_list = new RegularGrid(spatial_dimension, lower_bounds, upper_bounds, spacing); GhostType ghost_type = _not_ghost; Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type); // first generate the quad points coordinate and count the number of points per cell for(; it != last_type; ++it) { const Vector & quads = quadrature_points_coordinates(*it, ghost_type); Vector::const_iterator first_quad, last_quad; first_quad = quads.begin(spatial_dimension); last_quad = quads.end(spatial_dimension); for(;first_quad != last_quad; ++first_quad) { cell_list->count(*first_quad); } } QuadraturePoint q; q.ghost_type = ghost_type; // second insert the point in the cells cell_list->beginInsertions(); it = mesh.firstType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { Vector & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_quad = this->model->getFEM().getNbQuadraturePoints(*it, ghost_type); const Vector & quads = quadrature_points_coordinates(*it, ghost_type); q.type = *it; Vector::const_iterator quad = quads.begin(spatial_dimension); UInt * elem = elem_filter.storage(); for (UInt e = 0; e < nb_element; ++e) { q.element = *elem; for (UInt nq = 0; nq < nb_quad; ++nq) { q.num_point = nq; q.setPosition(*quad); cell_list->insert(q, *quad); ++quad; } ++elem; } } cell_list->endInsertions(); SynchronizerRegistry & synch_registry = this->model->getSynchronizerRegistry(); std::stringstream sstr; sstr << id << ":grid_synchronizer"; GridSynchronizer * synch = GridSynchronizer::createGridSynchronizer(mesh, *cell_list, sstr.str()); synch_registry.registerSynchronizer(*synch, _gst_mnl_damage); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template class WeightFunction> void MaterialNonLocal::updatePairList(const ByElementTypeReal & quadrature_points_coordinates) { AKANTU_DEBUG_IN(); Mesh & mesh = this->model->getFEM().getMesh(); GhostType ghost_type = _not_ghost; // generate the pair of neighbor depending of the cell_list Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { // Preparing datas const Vector & quads = quadrature_points_coordinates(*it, ghost_type); Vector::const_iterator first_quad = quads.begin(spatial_dimension); Vector::const_iterator last_quad = quads.end(spatial_dimension); ByElementTypeUInt & pairs = pair_list(ByElementTypeUInt("pairs", id, memory_id), *it, ghost_type); ElementType current_element_type = _not_defined; GhostType current_ghost_type = _casper; //Real * neigh_quad_positions = NULL; Vector * neighbors = NULL; UInt my_num_quad = 0; // loop over quad points - for(;first_quad != last_quad; ++first_quad, ++my_num_quad) { RegularGrid::Cell cell = cell_list->getCell(*first_quad); RegularGrid::neighbor_cells_iterator first_neigh_cell = cell_list->beginNeighborCells(cell); RegularGrid::neighbor_cells_iterator last_neigh_cell = cell_list->endNeighborCells(cell); - // loop over neighbor cells of the one containing the current quadrature + // loop over neighbors cells of the one containing the current quadrature // point for (; first_neigh_cell != last_neigh_cell; ++first_neigh_cell) { RegularGrid::iterator first_neigh_quad = cell_list->beginCell(*first_neigh_cell); RegularGrid::iterator last_neigh_quad = cell_list->endCell(*first_neigh_cell); // loop over the quadrature point in the current cell of the cell list for (;first_neigh_quad != last_neigh_quad; ++first_neigh_quad){ QuadraturePoint & quad = *first_neigh_quad; UInt nb_quad_per_elem = this->model->getFEM().getNbQuadraturePoints(quad.type, quad.ghost_type); UInt neigh_num_quad = quad.element * nb_quad_per_elem + quad.num_point; // little optimization to not search in the map at each quad points if(quad.type != current_element_type || quad.ghost_type != current_ghost_type) { // neigh_quad_positions = quadrature_points_coordinates(quad.type, // quad.ghost_type).storage(); current_element_type = quad.type; current_ghost_type = quad.ghost_type; if(!pairs.exists(current_element_type, current_ghost_type)) { neighbors = &(pairs.alloc(0, 2, current_element_type, current_ghost_type)); } else { neighbors = &(pairs(current_element_type, current_ghost_type)); } existing_pairs.insert(std::pair(*it, current_element_type)); } // types::RVector neigh_quad(neigh_quad_positions + neigh_num_quad * spatial_dimension, // spatial_dimension); const types::RVector & neigh_quad = quad.getPosition(); Real distance = first_quad->distance(neigh_quad); if(distance <= radius && my_num_quad <= neigh_num_quad) { // sotring only half lists UInt pair[2]; pair[0] = my_num_quad; pair[1] = neigh_num_quad; neighbors->push_back(pair); } // } } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template class WeightFunction> void MaterialNonLocal::computeWeights(const ByElementTypeReal & quadrature_points_coordinates) { AKANTU_DEBUG_IN(); std::set< std::pair >::iterator first_pair_types; std::set< std::pair >::iterator last_pair_types = existing_pairs.end(); GhostType ghost_type1, ghost_type2; ghost_type1 = ghost_type2 = _not_ghost; ByElementTypeReal quadrature_points_volumes("quadrature_points_volumes", id, memory_id); this->model->getFEM().getMesh().initByElementTypeVector(quadrature_points_volumes, 1, 0); + const ByElementTypeReal & jacobians_by_type = this->model->getFEM().getIntegratorInterface().getJacobians(); weight_func->updateInternals(quadrature_points_volumes); // Compute the weights first_pair_types = existing_pairs.begin(); for (; first_pair_types != last_pair_types; ++first_pair_types) { ElementType type1 = first_pair_types->first; ElementType type2 = first_pair_types->second; const Vector & pairs = pair_list(type1, ghost_type1)(type2, ghost_type2); std::string ghost_id = ""; if (ghost_type1 == _ghost) ghost_id = ":ghost"; ByElementTypeReal & weights_type_1 = pair_weight(type1, ghost_type1); std::stringstream sstr; sstr << id << ":pair_weight:" << type1 << ghost_id; weights_type_1.setID(sstr.str()); Vector * tmp_weight = NULL; if(!weights_type_1.exists(type2, ghost_type2)) { tmp_weight = &(weights_type_1.alloc(0, 2, type2, ghost_type2)); } else { tmp_weight = &(weights_type_1(type2, ghost_type2)); } Vector & weights = *tmp_weight; weights.resize(pairs.getSize()); weights.clear(); + const Vector & jacobians_1 = jacobians_by_type(type1, ghost_type1); + const Vector & jacobians_2 = jacobians_by_type(type2, ghost_type2); + const Vector & elem_filter = element_filter(type1, ghost_type1); UInt nb_quad1 = this->model->getFEM().getNbQuadraturePoints(type1); UInt nb_quad2 = this->model->getFEM().getNbQuadraturePoints(type2); UInt nb_tot_quad = nb_quad1 * elem_filter.getSize();; Vector & quads_volumes = quadrature_points_volumes(type1, ghost_type1); quads_volumes.resize(nb_tot_quad); quads_volumes.clear(); Vector::const_iterator iquads1; Vector::const_iterator iquads2; iquads1 = quadrature_points_coordinates(type1, ghost_type1).begin(spatial_dimension); iquads2 = quadrature_points_coordinates(type2, ghost_type2).begin(spatial_dimension); Vector::const_iterator< types::Vector > first_pair = pairs.begin(2); Vector::const_iterator< types::Vector > last_pair = pairs.end(2); Vector::iterator weight = weights.begin(2); this->weight_func->selectType(type1, ghost_type1, type2, ghost_type2); // Weight function for(;first_pair != last_pair; ++first_pair, ++weight) { UInt _q1 = (*first_pair)(0); UInt _q2 = (*first_pair)(1); const types::RVector & pos1 = iquads1[_q1]; const types::RVector & pos2 = iquads2[_q2]; QuadraturePoint q1(_q1 / nb_quad1, _q1 % nb_quad1, _q1, pos1, type1, ghost_type1); QuadraturePoint q2(_q2 / nb_quad2, _q2 % nb_quad2, _q2, pos2, type2, ghost_type2); Real r = pos1.distance(pos2); - (*weight)(0) = this->weight_func->operator()(r, q1, q2); - if(_q1 != _q2) - (*weight)(1) = this->weight_func->operator()(r, q2, q1); - else + + Real w2J2 = jacobians_2(_q2); + (*weight)(0) = w2J2 * this->weight_func->operator()(r, q1, q2); + if(_q1 != _q2) { + Real w1J1 = jacobians_1(_q1); + (*weight)(1) = w1J1 * this->weight_func->operator()(r, q2, q1); + } else (*weight)(1) = 0; quads_volumes(_q1) += (*weight)(0); quads_volumes(_q2) += (*weight)(1); } } //normalize the weights first_pair_types = existing_pairs.begin(); for (; first_pair_types != last_pair_types; ++first_pair_types) { ElementType type1 = first_pair_types->first; ElementType type2 = first_pair_types->second; const Vector & pairs = pair_list(type1, ghost_type1)(type2, ghost_type2); Vector & weights = pair_weight(type1, ghost_type1)(type2, ghost_type2); Vector & quads_volumes = quadrature_points_volumes(type1, ghost_type1); Vector::const_iterator< types::Vector > first_pair = pairs.begin(2); Vector::const_iterator< types::Vector > last_pair = pairs.end(2); Vector::iterator weight = weights.begin(2); for(;first_pair != last_pair; ++first_pair, ++weight) { UInt q1 = (*first_pair)(0); UInt q2 = (*first_pair)(1); (*weight)(0) *= 1. / quads_volumes(q1); (*weight)(1) *= 1. / quads_volumes(q2); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template class WeightFunction> bool MaterialNonLocal::setParam(const std::string & key, const std::string & value, __attribute__((unused)) const ID & id) { std::stringstream sstr(value); if(key == "radius") { sstr >> radius; } else if(key == "UpdateWeights") { sstr >> update_weigths; } else if(!weight_func->setParam(key, value)) return false; return true; } /* -------------------------------------------------------------------------- */ template class WeightFunction> void MaterialNonLocal::savePairs(const std::string & filename) const { std::ofstream pout; pout.open(filename.c_str()); std::set< std::pair >::const_iterator first_pair_types = existing_pairs.begin(); std::set< std::pair >::const_iterator last_pair_types = existing_pairs.end(); GhostType ghost_type1, ghost_type2; ghost_type1 = ghost_type2 = _not_ghost; for (; first_pair_types != last_pair_types; ++first_pair_types) { const Vector & pairs = pair_list(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2); const Vector & weights = pair_weight(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2); pout << "Types : " << first_pair_types->first << " " << first_pair_types->second << std::endl; Vector::const_iterator< types::Vector > first_pair = pairs.begin(2); Vector::const_iterator< types::Vector > last_pair = pairs.end(2); Vector::const_iterator pair_w = weights.begin(2); for(;first_pair != last_pair; ++first_pair, ++pair_w) { UInt q1 = (*first_pair)(0); UInt q2 = (*first_pair)(1); pout << q1 << " " << q2 << " "<< (*pair_w)(0) << " " << (*pair_w)(1) << std::endl; } } } /* -------------------------------------------------------------------------- */ template class WeightFunction> void MaterialNonLocal::neighbourhoodStatistics(const std::string & filename) const { std::ofstream pout; pout.open(filename.c_str()); std::set< std::pair >::const_iterator first_pair_types = existing_pairs.begin(); std::set< std::pair >::const_iterator last_pair_types = existing_pairs.end(); const Mesh & mesh = this->model->getFEM().getMesh(); ByElementTypeUInt nb_neighbors("nb_neighbours", id, memory_id); initInternalVector(nb_neighbors, 1); resizeInternalVector(nb_neighbors); GhostType ghost_type1, ghost_type2; ghost_type1 = ghost_type2 = _not_ghost; for (; first_pair_types != last_pair_types; ++first_pair_types) { const Vector & pairs = pair_list(first_pair_types->first, ghost_type1)(first_pair_types->second, ghost_type2); pout << "Types : " << first_pair_types->first << " " << first_pair_types->second << std::endl; Vector::const_iterator< types::Vector > first_pair = pairs.begin(2); Vector::const_iterator< types::Vector > last_pair = pairs.end(2); Vector & nb_neigh_1 = nb_neighbors(first_pair_types->first, ghost_type1); Vector & nb_neigh_2 = nb_neighbors(first_pair_types->second, ghost_type2); for(;first_pair != last_pair; ++first_pair) { UInt q1 = (*first_pair)(0); UInt q2 = (*first_pair)(1); ++(nb_neigh_1(q1)); if(q1 != q2) ++(nb_neigh_2(q2)); } } Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type1); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type1); UInt nb_quads = 0; Real mean_nb_neig = 0; UInt max_nb_neig = 0; UInt min_nb_neig = std::numeric_limits::max(); for(; it != last_type; ++it) { Vector & nb_neighor = nb_neighbors(*it, ghost_type1); Vector::iterator nb_neigh = nb_neighor.begin(); Vector::iterator end_neigh = nb_neighor.end(); for (; nb_neigh != end_neigh; ++nb_neigh, ++nb_quads) { UInt nb = *nb_neigh; mean_nb_neig += nb; max_nb_neig = std::max(max_nb_neig, nb); min_nb_neig = std::min(min_nb_neig, nb); } } mean_nb_neig /= Real(nb_quads); pout << "Nb quadrature points: " << nb_quads << std::endl; pout << "Average nb neighbors: " << mean_nb_neig << std::endl; pout << "Max nb neighbors: " << max_nb_neig << std::endl; pout << "Min nb neighbors: " << min_nb_neig << std::endl; pout.close(); } /* -------------------------------------------------------------------------- */ template class WeightFunction> void MaterialNonLocal::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Material<_non_local> [" << std::endl; stream << space << " + Radius : " << radius << std::endl; stream << space << " + UpdateWeights : " << update_weigths << std::endl; stream << space << " + Weight Function : " << *weight_func << std::endl; stream << space << "]" << std::endl; } diff --git a/src/model/solid_mechanics/materials/weight_function.hh b/src/model/solid_mechanics/materials/weight_function.hh index 1f3d2e42f..5081922c3 100644 --- a/src/model/solid_mechanics/materials/weight_function.hh +++ b/src/model/solid_mechanics/materials/weight_function.hh @@ -1,264 +1,264 @@ /** * @file weight_function.hh * @author Nicolas Richart * @date Thu Mar 8 16:17:00 2012 * * @brief Weight functions for non local materials * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_types.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ #include #ifndef __AKANTU_WEIGHT_FUNCTION_HH__ #define __AKANTU_WEIGHT_FUNCTION_HH__ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Normal weight function */ /* -------------------------------------------------------------------------- */ template class BaseWeightFunction { public: BaseWeightFunction(const Material & material) : material(material) {} virtual ~BaseWeightFunction() {} virtual void init() {}; virtual void updateInternals(__attribute__((unused)) const ByElementTypeReal & quadrature_points_coordinates) {}; /* ------------------------------------------------------------------------ */ inline void setRadius(Real radius) { R = radius; R2 = R * R; } /* ------------------------------------------------------------------------ */ inline void selectType(__attribute__((unused)) ElementType type1, __attribute__((unused)) GhostType ghost_type1, __attribute__((unused)) ElementType type2, __attribute__((unused)) GhostType ghost_type2) { } /* ------------------------------------------------------------------------ */ inline Real operator()(Real r, __attribute__((unused)) QuadraturePoint & q1, __attribute__((unused)) QuadraturePoint & q2) { Real w = 0; if(r <= R) { Real alpha = (1. - r*r / R2); w = alpha * alpha; // *weight = 1 - sqrt(r / radius); } return w; } /* ------------------------------------------------------------------------ */ bool setParam(__attribute__((unused)) const std::string & key, __attribute__((unused)) const std::string & value) { return false; } /* ------------------------------------------------------------------------ */ virtual void printself(std::ostream & stream) const { stream << "BaseWeightFunction"; } protected: const Material & material; Real R; Real R2; }; /* -------------------------------------------------------------------------- */ /* Damage weight function */ /* -------------------------------------------------------------------------- */ template class DamagedWeightFunction : public BaseWeightFunction { public: DamagedWeightFunction(const Material & material) : BaseWeightFunction(material) {} inline void selectType(__attribute__((unused)) ElementType type1, __attribute__((unused)) GhostType ghost_type1, ElementType type2, GhostType ghost_type2) { selected_damage = &(dynamic_cast &>(this->material).getDamage(type2, ghost_type2)); } inline Real operator()(Real r, __attribute__((unused)) QuadraturePoint & q1, QuadraturePoint & q2) { UInt quad = q2.global_num; Real D = (*selected_damage)(quad); Real Radius = (1.-D)*(1.-D) * this->R2; if(Radius < Math::getTolerance()) { Radius = 0.01 * 0.01 * this->R2; } Real alpha = std::max(0., 1. - r*r / Radius); Real w = alpha * alpha; return w; } /* ------------------------------------------------------------------------ */ bool setParam(__attribute__((unused)) const std::string & key, __attribute__((unused)) const std::string & value) { return false; } /* ------------------------------------------------------------------------ */ virtual void printself(std::ostream & stream) const { stream << "DamagedWeightFunction"; } private: const Vector * selected_damage; }; /* -------------------------------------------------------------------------- */ /* Remove damaged weight function */ /* -------------------------------------------------------------------------- */ template class RemoveDamagedWeightFunction : public BaseWeightFunction { public: RemoveDamagedWeightFunction(const Material & material) : BaseWeightFunction(material) {} inline void selectType(__attribute__((unused)) ElementType type1, __attribute__((unused)) GhostType ghost_type1, ElementType type2, GhostType ghost_type2) { selected_damage = - &(dynamic_cast &>(this->material).getDamage(type2, ghost_type2)); + &this->material.getVector("damage", type2, ghost_type2); } inline Real operator()(Real r, __attribute__((unused)) QuadraturePoint & q1, QuadraturePoint & q2) { UInt quad = q2.global_num; if(q1.global_num == quad) return 1.; Real D = (*selected_damage)(quad); Real w = 0.; if(D < damage_limit) { Real alpha = std::max(0., 1. - r*r / this->R2); w = alpha * alpha; } return w; } /* ------------------------------------------------------------------------ */ bool setParam(const std::string & key, const std::string & value) { std::stringstream sstr(value); if(key == "damage_limit") { sstr >> damage_limit; } else return BaseWeightFunction::setParam(key, value); return true; } /* ------------------------------------------------------------------------ */ virtual void printself(std::ostream & stream) const { stream << "RemoveDamagedWeightFunction [damage_limit: " << damage_limit << "]"; } private: /// limit at which a point is considered as complitely broken Real damage_limit; /// internal pointer to the current damage vector const Vector * selected_damage; }; /* -------------------------------------------------------------------------- */ /* Stress Based Weight */ /* -------------------------------------------------------------------------- */ template class StressBasedWeightFunction : public BaseWeightFunction { public: StressBasedWeightFunction(const Material & material); void init(); virtual void updateInternals(__attribute__((unused)) const ByElementTypeReal & quadrature_points_coordinates) { updatePrincipalStress(_not_ghost); updatePrincipalStress(_ghost); }; void updatePrincipalStress(GhostType ghost_type); inline void updateQuadraturePointsCoordinates(ByElementTypeReal & quadrature_points_coordinates); inline void selectType(ElementType type1, GhostType ghost_type1, ElementType type2, GhostType ghost_type2); inline Real operator()(Real r, QuadraturePoint & q1, QuadraturePoint & q2); inline Real computeRhoSquare(Real r, types::RVector & eigs, types::Matrix & eigenvects, types::RVector & x_s); /* ------------------------------------------------------------------------ */ bool setParam(const std::string & key, const std::string & value) { std::stringstream sstr(value); if(key == "ft") { sstr >> ft; } else return BaseWeightFunction::setParam(key, value); return true; } /* ------------------------------------------------------------------------ */ virtual void printself(std::ostream & stream) const { stream << "StressBasedWeightFunction [ft: " << ft << "]"; } private: Real ft; ByElementTypeReal stress_diag; Vector * selected_stress_diag; ByElementTypeReal stress_base; Vector * selected_stress_base; ByElementTypeReal quadrature_points_coordinates; Vector * selected_position_1; Vector * selected_position_2; ByElementTypeReal characteristic_size; Vector * selected_characteristic_size; }; template inline std::ostream & operator <<(std::ostream & stream, const BaseWeightFunction & _this) { _this.printself(stream); return stream; } #include "weight_function_tmpl.hh" __END_AKANTU__ #endif /* __AKANTU_WEIGHT_FUNCTION_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model.cc b/src/model/solid_mechanics/solid_mechanics_model.cc index 06f6edbe8..838539cc4 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.cc +++ b/src/model/solid_mechanics/solid_mechanics_model.cc @@ -1,1026 +1,1064 @@ /** * @file solid_mechanics_model.cc * @author Nicolas Richart * @date Thu Jul 22 14:35:38 2010 * * @brief Implementation of the SolidMechanicsModel class * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "aka_math.hh" #include "integration_scheme_2nd_order.hh" #include "static_communicator.hh" #include "dof_synchronizer.hh" #ifdef AKANTU_USE_MUMPS #include "solver_mumps.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /** * A solid mechanics model need a mesh and a dimension to be created. the model * by it self can not do a lot, the good init functions should be called in * order to configure the model depending on what we want to do. * * @param mesh mesh representing the model we want to simulate * @param dim spatial dimension of the problem, if dim = 0 (default value) the * dimension of the problem is assumed to be the on of the mesh * @param id an id to identify the model */ SolidMechanicsModel::SolidMechanicsModel(Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id) : Model(id, memory_id), time_step(NAN), f_m2a(1.0), mass_matrix(NULL), velocity_damping_matrix(NULL), stiffness_matrix(NULL), jacobian_matrix(NULL), element_material("element_material", id), element_index_by_material("element index by material", id), integrator(NULL), increment_flag(false), solver(NULL), spatial_dimension(dim), mesh(mesh) { AKANTU_DEBUG_IN(); createSynchronizerRegistry(this); if (spatial_dimension == 0) spatial_dimension = mesh.getSpatialDimension(); registerFEMObject("SolidMechanicsFEM", mesh, spatial_dimension); this->displacement = NULL; this->mass = NULL; this->velocity = NULL; this->acceleration = NULL; this->force = NULL; this->residual = NULL; this->boundary = NULL; this->increment = NULL; this->increment_acceleration = NULL; this->dof_synchronizer = NULL; materials.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolidMechanicsModel::~SolidMechanicsModel() { AKANTU_DEBUG_IN(); std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { delete *mat_it; } materials.clear(); delete integrator; if(solver) delete solver; if(mass_matrix) delete mass_matrix; if(velocity_damping_matrix) delete velocity_damping_matrix; if(stiffness_matrix && stiffness_matrix != jacobian_matrix) delete stiffness_matrix; if(jacobian_matrix) delete jacobian_matrix; if(dof_synchronizer) delete dof_synchronizer; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Initialisation */ /* -------------------------------------------------------------------------- */ /** * This function groups many of the initialization in on function. For most of * basics case the function should be enough. The functions initialize the * model, the internal vectors, set them to 0, and depending on the parameters * it also initialize the explicit or implicit solver. * * @param material_file the file containing the materials to use * @param method the analysis method wanted. See the akantu::AnalysisMethod for * the different possibilites */ void SolidMechanicsModel::initFull(std::string material_file, AnalysisMethod analysis_method) { method = analysis_method; // initialize the model initModel(); // initialize the vectors initVectors(); // set the initial condition to 0 force->clear(); velocity->clear(); acceleration->clear(); displacement->clear(); // initialize pcb if(pbc_pair.size()!=0) initPBC(); // initialize the time integration schemes switch(method) { case _explicit_dynamic: initExplicit(); break; case _implicit_dynamic: initImplicit(true); break; case _static: initImplicit(false); break; } // initialize the materials if(material_file != "") { readMaterials(material_file); initMaterials(); } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initParallel(MeshPartition * partition, DataAccessor * data_accessor) { AKANTU_DEBUG_IN(); if (data_accessor == NULL) data_accessor = this; Synchronizer & synch_parallel = createParallelSynch(partition,data_accessor); synch_registry->registerSynchronizer(synch_parallel,_gst_smm_mass); synch_registry->registerSynchronizer(synch_parallel,_gst_smm_for_strain); synch_registry->registerSynchronizer(synch_parallel,_gst_smm_boundary); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initFEMBoundary(bool create_surface) { if(create_surface) MeshUtils::buildFacets(mesh); FEM & fem_boundary = getFEMBoundary(); fem_boundary.initShapeFunctions(); fem_boundary.computeNormalsOnControlPoints(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initExplicit() { AKANTU_DEBUG_IN(); method = _explicit_dynamic; 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(); } /* -------------------------------------------------------------------------- */ /** * Allocate all the needed vectors. By default their are not necessarily set to * 0 * */ void SolidMechanicsModel::initVectors() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_disp; sstr_disp << id << ":displacement"; std::stringstream sstr_mass; sstr_mass << id << ":mass"; std::stringstream sstr_velo; sstr_velo << id << ":velocity"; std::stringstream sstr_acce; sstr_acce << id << ":acceleration"; std::stringstream sstr_forc; sstr_forc << id << ":force"; std::stringstream sstr_resi; sstr_resi << id << ":residual"; std::stringstream sstr_boun; sstr_boun << id << ":boundary"; displacement = &(alloc(sstr_disp.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); mass = &(alloc(sstr_mass.str(), nb_nodes, spatial_dimension, 0)); velocity = &(alloc(sstr_velo.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); acceleration = &(alloc(sstr_acce.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); force = &(alloc(sstr_forc.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); residual = &(alloc(sstr_resi.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); boundary = &(alloc(sstr_boun.str(), nb_nodes, spatial_dimension, false)); std::stringstream sstr_curp; sstr_curp << id << ":current_position"; current_position = &(alloc(sstr_curp.str(), 0, spatial_dimension, REAL_INIT_VALUE)); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt, _ek_not_defined); for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, gt); element_material.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 getFEM().initShapeFunctions(_not_ghost); getFEM().initShapeFunctions(_ghost); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initPBC() { Model::initPBC(); registerPBCSynchronizer(); // as long as there are ones on the diagonal of the matrix, we can put boudandary true for slaves std::map::iterator it = pbc_pair.begin(); std::map::iterator end = pbc_pair.end(); UInt dim = mesh.getSpatialDimension(); while(it != end) { for (UInt i=0; iregisterSynchronizer(*synch, _gst_smm_uv); synch_registry->registerSynchronizer(*synch, _gst_smm_mass); synch_registry->registerSynchronizer(*synch, _gst_smm_res); changeLocalEquationNumberforPBC(pbc_pair, mesh.getSpatialDimension()); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateCurrentPosition() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); current_position->resize(nb_nodes); Real * current_position_val = current_position->values; Real * position_val = mesh.getNodes().values; Real * displacement_val = displacement->values; /// compute current_position = initial_position + displacement memcpy(current_position_val, position_val, nb_nodes*spatial_dimension*sizeof(Real)); for (UInt n = 0; n < nb_nodes*spatial_dimension; ++n) { *current_position_val++ += *displacement_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initializeUpdateResidualData() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); residual->resize(nb_nodes); /// copy the forces in residual for boundary conditions memcpy(residual->values, force->values, nb_nodes*spatial_dimension*sizeof(Real)); 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(); // f = f_ext - f_int // f = f_ext if (need_initialize) initializeUpdateResidualData(); // f -= fint // start synchronization synch_registry->asynchronousSynchronize(_gst_smm_uv); synch_registry->waitEndSynchronize(_gst_smm_uv); synch_registry->asynchronousSynchronize(_gst_smm_for_strain); // call update residual on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { //(*mat_it)->updateResidual(*current_position, _not_ghost); (*mat_it)->updateResidual(*displacement, _not_ghost); } // finalize communications synch_registry->waitEndSynchronize(_gst_smm_for_strain); // call update residual on each ghost elements for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { //(*mat_it)->updateResidual(*current_position, _ghost); (*mat_it)->updateResidual(*displacement, _ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateResidualInternal() { AKANTU_DEBUG_IN(); // f = f_ext - f_int - Ma - Cv = r - Ma - Cv; if(method != _static) { // f -= Ma if(mass_matrix) { // if full mass_matrix Vector * Ma = new Vector(*acceleration, true, "Ma"); *Ma *= *mass_matrix; /// \todo check unit conversion for implicit dynamics // *Ma /= f_m2a *residual -= *Ma; delete Ma; } else { // else lumped mass UInt nb_nodes = acceleration->getSize(); UInt nb_degree_of_freedom = acceleration->getNbComponent(); Real * mass_val = mass->values; Real * accel_val = acceleration->values; Real * res_val = residual->values; bool * boundary_val = boundary->values; for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { if(!(*boundary_val)) { *res_val -= *accel_val * *mass_val /f_m2a; } boundary_val++; res_val++; mass_val++; accel_val++; } } // f -= Cv if(velocity_damping_matrix) { Vector * Cv = new Vector(*velocity); *Cv *= *velocity_damping_matrix; *residual -= *Cv; delete Cv; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateAcceleration() { AKANTU_DEBUG_IN(); updateResidualInternal(); if(method == _explicit_dynamic && !mass_matrix) { /* residual = residual_{n+1} - M * acceleration_n therefore solution = increment acceleration not acceleration */ solveLumped(*increment_acceleration, *mass, *residual, *boundary, f_m2a); } else { solveDynamic(*increment_acceleration); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveLumped(Vector & x, const Vector & A, const Vector & b, const Vector & boundary, Real alpha) { Real * A_val = A.storage(); Real * b_val = b.storage(); Real * x_val = x.storage(); bool * boundary_val = boundary.storage(); UInt nb_degrees_of_freedom = x.getSize() * x.getNbComponent(); for (UInt n = 0; n < nb_degrees_of_freedom; ++n) { if(!(*boundary_val)) { *x_val = alpha * (*b_val / *A_val); } x_val++; A_val++; b_val++; boundary_val++; } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::explicitPred() { AKANTU_DEBUG_IN(); if(increment_flag) { memcpy(increment->values, displacement->values, displacement->getSize()*displacement->getNbComponent()*sizeof(Real)); } AKANTU_DEBUG_ASSERT(integrator,"itegrator should have been allocated: " << "have called initExplicit ? " << "or initImplicit ?"); integrator->integrationSchemePred(time_step, *displacement, *velocity, *acceleration, *boundary); if(increment_flag) { Real * inc_val = increment->values; Real * dis_val = displacement->values; UInt nb_nodes = displacement->getSize(); for (UInt n = 0; n < nb_nodes; ++n) { *inc_val = *dis_val - *inc_val; inc_val++; dis_val++; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::explicitCorr() { AKANTU_DEBUG_IN(); integrator->integrationSchemeCorrAccel(time_step, *displacement, *velocity, *acceleration, *boundary, *increment_acceleration); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Implicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /** * Initialize the solver and create the sparse matrices needed. * */ void SolidMechanicsModel::initSolver(SolverOptions & options) { #if !defined(AKANTU_USE_MUMPS) // or other solver in the future \todo add AKANTU_HAS_SOLVER in CMake AKANTU_DEBUG_ERROR("You should at least activate one solver."); #else UInt nb_global_node = mesh.getNbGlobalNodes(); std::stringstream sstr; sstr << id << ":jacobian_matrix"; jacobian_matrix = new SparseMatrix(nb_global_node * spatial_dimension, _symmetric, spatial_dimension, sstr.str(), memory_id); // dof_synchronizer->initGlobalDOFEquationNumbers(); jacobian_matrix->buildProfile(mesh, *dof_synchronizer); #ifdef AKANTU_USE_MUMPS std::stringstream sstr_solv; sstr_solv << id << ":solver"; solver = new SolverMumps(*jacobian_matrix, sstr_solv.str()); dof_synchronizer->initScatterGatherCommunicationScheme(); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif //AKANTU_USE_MUMPS solver->initialize(options); #endif //AKANTU_HAS_SOLVER } /* -------------------------------------------------------------------------- */ /** * Initialize the implicit solver, either for dynamic or static cases, * * @param dynamic */ void SolidMechanicsModel::initImplicit(bool dynamic, SolverOptions & solver_options) { AKANTU_DEBUG_IN(); method = dynamic ? _implicit_dynamic : _static; initSolver(solver_options); if(method == _implicit_dynamic) { if(integrator) delete integrator; integrator = new TrapezoidalRule2(); std::stringstream sstr; sstr << id << ":stiffness_matrix"; stiffness_matrix = new SparseMatrix(*jacobian_matrix, sstr.str(), memory_id); } else { stiffness_matrix = jacobian_matrix; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initialAcceleration() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving Ma = f"); Solver * acc_solver = NULL; std::stringstream sstr; sstr << id << ":tmp_mass_matrix"; SparseMatrix * tmp_mass = new SparseMatrix(*mass_matrix, sstr.str(), memory_id); #ifdef AKANTU_USE_MUMPS std::stringstream sstr_solver; sstr << id << ":solver_mass_matrix"; acc_solver = new SolverMumps(*mass_matrix, sstr_solver.str()); dof_synchronizer->initScatterGatherCommunicationScheme(); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif //AKANTU_USE_MUMPS acc_solver->initialize(); tmp_mass->applyBoundary(*boundary); acc_solver->setRHS(*residual); acc_solver->solve(*acceleration); delete acc_solver; delete tmp_mass; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleStiffnessMatrix() { AKANTU_DEBUG_IN(); stiffness_matrix->clear(); // call compute stiffness matrix on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->assembleStiffnessMatrix(*displacement, _not_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveDynamic() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, "You should first initialize the implicit solver and assemble the stiffness matrix"); AKANTU_DEBUG_ASSERT(mass_matrix != NULL, "You should first initialize the implicit solver and assemble the mass matrix"); if(!increment) setIncrementFlagOn(); updateResidualInternal(); solveDynamic(*increment); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveStatic() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving Ku = f"); AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, "You should first initialize the implicit solver and assemble the stiffness matrix"); UInt nb_nodes = displacement->getSize(); UInt nb_degree_of_freedom = displacement->getNbComponent(); stiffness_matrix->applyBoundary(*boundary); if(method != _static) jacobian_matrix->copyContent(*stiffness_matrix); solver->setRHS(*residual); if(!increment) setIncrementFlagOn(); solver->solve(*increment); Real * increment_val = increment->values; Real * displacement_val = displacement->values; bool * boundary_val = boundary->values; for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { if(!(*boundary_val)) { *displacement_val += *increment_val; } displacement_val++; boundary_val++; increment_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance) { Real error; bool tmp = testConvergenceIncrement(tolerance, error); AKANTU_DEBUG_INFO("Norm of increment : " << error); return tmp; } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance, Real & error) { AKANTU_DEBUG_IN(); UInt nb_nodes = displacement->getSize(); UInt nb_degree_of_freedom = displacement->getNbComponent(); error = 0; Real norm[2] = {0., 0.}; Real * increment_val = increment->storage(); bool * boundary_val = boundary->storage(); Real * displacement_val = displacement->storage(); for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); for (UInt d = 0; d < nb_degree_of_freedom; ++d) { if(!(*boundary_val) && is_local_node) { norm[0] += *increment_val * *increment_val; norm[1] += *displacement_val * *displacement_val; } boundary_val++; increment_val++; displacement_val++; } } StaticCommunicator::getStaticCommunicator()->allReduce(norm, 2, _so_sum); norm[0] = sqrt(norm[0]); norm[1] = sqrt(norm[1]); AKANTU_DEBUG_ASSERT(!Math::isnan(norm[0]), "Something goes wrong in the solve phase"); AKANTU_DEBUG_OUT(); error = norm[0] / norm[1]; return (error < tolerance); } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceResidual(Real tolerance) { Real error; bool tmp = testConvergenceResidual(tolerance, error); AKANTU_DEBUG_INFO("Norm of residual : " << error); return tmp; } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceResidual(Real tolerance, Real & norm) { AKANTU_DEBUG_IN(); UInt nb_nodes = residual->getSize(); norm = 0; Real * residual_val = residual->values; bool * boundary_val = boundary->values; for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); if(is_local_node) { for (UInt d = 0; d < spatial_dimension; ++d) { if(!(*boundary_val)) { norm += *residual_val * *residual_val; } boundary_val++; residual_val++; } } else { boundary_val += spatial_dimension; residual_val += spatial_dimension; } } StaticCommunicator::getStaticCommunicator()->allReduce(&norm, 1, _so_sum); norm = sqrt(norm); AKANTU_DEBUG_ASSERT(!Math::isnan(norm), "Something goes wrong in the solve phase"); AKANTU_DEBUG_OUT(); return (norm < tolerance); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::implicitPred() { AKANTU_DEBUG_IN(); integrator->integrationSchemePred(time_step, *displacement, *velocity, *acceleration, *boundary); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::implicitCorr() { AKANTU_DEBUG_IN(); integrator->integrationSchemeCorrDispl(time_step, *displacement, *velocity, *acceleration, *boundary, *increment); 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(); Real * coord = mesh.getNodes().values; Real * disp_val = displacement->values; Element elem; elem.ghost_type = ghost_type; 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); UInt * conn = mesh.getConnectivity(*it, ghost_type).storage(); UInt * elem_mat_val = element_material(*it, ghost_type).storage(); Real * u = new Real[nb_nodes_per_element*spatial_dimension]; for (UInt el = 0; el < nb_element; ++el) { UInt el_offset = el * nb_nodes_per_element; elem.element = el; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n] * spatial_dimension; memcpy(u + n * spatial_dimension, coord + offset_conn, spatial_dimension * sizeof(Real)); for (UInt i = 0; i < spatial_dimension; ++i) { u[n * spatial_dimension + i] += disp_val[offset_conn + i]; } } Real el_size = getFEM().getElementInradius(u, *it); Real el_dt = mat_val[elem_mat_val[el]]->getStableTimeStep(el_size, elem); min_dt = min_dt > el_dt ? el_dt : min_dt; } delete [] u; } AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getPotentialEnergy() { AKANTU_DEBUG_IN(); Real energy = 0.; /// call update residual on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { energy += (*mat_it)->getPotentialEnergy(); } /// reduction sum over all processors StaticCommunicator::getStaticCommunicator()->allReduce(&energy, 1, _so_sum); AKANTU_DEBUG_OUT(); return energy; } -/* -------------------------------------------------------------------------- */ -Real SolidMechanicsModel::getEnergy(std::string id) { - AKANTU_DEBUG_IN(); - - if (id == "kinetic") { - return getKineticEnergy(); - } - - Real energy = 0.; - - std::vector::iterator mat_it; - for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { - energy += (*mat_it)->getEnergy(id); - } - - /// reduction sum over all processors - StaticCommunicator::getStaticCommunicator()->allReduce(&energy, 1, _so_sum); - - AKANTU_DEBUG_OUT(); - return energy; -} /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy() { AKANTU_DEBUG_IN(); Real ekin = 0.; UInt nb_nodes = mesh.getNbNodes(); Real * vel_val = velocity->values; Real * mass_val = mass->values; for (UInt n = 0; n < nb_nodes; ++n) { Real mv2 = 0; bool is_local_node = mesh.isLocalOrMasterNode(n); bool is_not_pbc_slave_node = !getIsPBCSlaveNode(n); for (UInt i = 0; i < spatial_dimension; ++i) { // if(is_local_node) { mv2 += is_local_node * is_not_pbc_slave_node * *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::getExternalWork() { + AKANTU_DEBUG_IN(); + + Real * velo = velocity->storage(); + Real * forc = force->storage(); + Real * resi = residual->storage(); + bool * boun = boundary->storage(); + + Real work = 0.; + + UInt nb_nodes = mesh.getNbNodes(); + + for (UInt n = 0; n < nb_nodes; ++n) { + bool is_local_node = mesh.isLocalOrMasterNode(n); + bool is_not_pbc_slave_node = !getIsPBCSlaveNode(n); + bool count_node = is_local_node && is_not_pbc_slave_node; + + for (UInt i = 0; i < spatial_dimension; ++i) { + if(*boun) + work -= count_node * *resi * *velo * time_step; + else + work += count_node * *forc * *velo * time_step; + + ++velo; + ++forc; + ++resi; + ++boun; + } + } + + StaticCommunicator::getStaticCommunicator()->allReduce(&work, 1, _so_sum); + + AKANTU_DEBUG_OUT(); + return work; +} + +/* -------------------------------------------------------------------------- */ +Real SolidMechanicsModel::getEnergy(std::string id) { + AKANTU_DEBUG_IN(); + + if (id == "kinetic") { + return getKineticEnergy(); + } else if (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(id); + } + + /// reduction sum over all processors + StaticCommunicator::getStaticCommunicator()->allReduce(&energy, 1, _so_sum); + + AKANTU_DEBUG_OUT(); + return energy; +} + /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Solid Mechanics Model [" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + spatial dimension : " << spatial_dimension << std::endl; - stream << space << " + fem [" << std::endl; getFEM().printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + nodals information [" << std::endl; displacement->printself(stream, indent + 2); mass ->printself(stream, indent + 2); velocity ->printself(stream, indent + 2); acceleration->printself(stream, indent + 2); force ->printself(stream, indent + 2); residual ->printself(stream, indent + 2); boundary ->printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + connectivity type information [" << std::endl; element_material.printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/model/solid_mechanics/solid_mechanics_model.hh b/src/model/solid_mechanics/solid_mechanics_model.hh index d1e07ee13..e5c03d1ee 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.hh +++ b/src/model/solid_mechanics/solid_mechanics_model.hh @@ -1,538 +1,545 @@ /** * @file solid_mechanics_model.hh * @author Nicolas Richart * @date[creation] Thu Jul 22 11:51:06 2010 * @date[last modification] Thu Oct 14 14:00:06 2010 * * @brief Model of Solid Mechanics * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLID_MECHANICS_MODEL_HH__ #define __AKANTU_SOLID_MECHANICS_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "model.hh" #include "data_accessor.hh" #include "integrator_gauss.hh" #include "shape_lagrange.hh" #include "integrator_cohesive.hh" #include "shape_cohesive.hh" #include "aka_types.hh" #include "integration_scheme_2nd_order.hh" #include "solver.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class Material; class IntegrationScheme2ndOrder; class Contact; class SparseMatrix; } __BEGIN_AKANTU__ class SolidMechanicsModel : public Model, public DataAccessor { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef FEMTemplate MyFEMType; typedef FEMTemplate< IntegratorCohesive, ShapeCohesive > MyFEMCohesiveType; SolidMechanicsModel(Mesh & mesh, UInt spatial_dimension = 0, const ID & id = "solid_mechanics_model", const MemoryID & memory_id = 0); virtual ~SolidMechanicsModel(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize completely the model virtual void initFull(std::string material_file, AnalysisMethod method = _explicit_dynamic); /// initialize the fem object needed for boundary conditions void initFEMBoundary(bool create_surface = true); /// register the tags associated with the parallel synchronizer void initParallel(MeshPartition * partition, DataAccessor * data_accessor=NULL); /// allocate all vectors void initVectors(); /// initialize all internal arrays for materials void initMaterials(); /// initialize the model virtual void initModel(); /// init PBC synchronizer void initPBC(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* PBC */ /* ------------------------------------------------------------------------ */ public: /// change the equation number for proper assembly when using PBC void changeEquationNumberforPBC(std::map & pbc_pair); /// synchronize Residual for output void synchronizeResidual(); protected: /// register PBC synchronizer void registerPBCSynchronizer(); /* ------------------------------------------------------------------------ */ /* Explicit */ /* ------------------------------------------------------------------------ */ public: /// initialize the stuff for the explicit scheme void initExplicit(); /// 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 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(); /// Solve the system @f[ A x = \alpha b @f] with A a lumped matrix void solveLumped(Vector & x, const Vector & A, const Vector & b, const Vector & boundary, Real alpha); /// explicit integration predictor void explicitPred(); /// explicit integration corrector void explicitCorr(); /* ------------------------------------------------------------------------ */ /* Implicit */ /* ------------------------------------------------------------------------ */ public: /// initialize the solver and the jacobian_matrix (called by initImplicit) void initSolver(SolverOptions & options = _solver_no_options); /// initialize the stuff for the implicit solver void initImplicit(bool dynamic = false, SolverOptions & solver_options = _solver_no_options); /// solve Ma = f to get the initial acceleration void initialAcceleration(); /// assemble the stiffness matrix void assembleStiffnessMatrix(); /// solve @f[ A\delta u = f_ext - f_int @f] in displacement void solveDynamic(); /// solve Ku = f void solveStatic(); /// test the convergence (norm of increment) bool testConvergenceIncrement(Real tolerance); bool testConvergenceIncrement(Real tolerance, Real & error); /// test the convergence (norm of residual) bool testConvergenceResidual(Real tolerance); bool testConvergenceResidual(Real tolerance, Real & error); /// implicit time integration predictor void implicitPred(); /// implicit time integration corrector void implicitCorr(); protected: /// finish the computation of residual to solve in increment void updateResidualInternal(); /// compute A and solve @f[ A\delta u = f_ext - f_int @f] template void solveDynamic(Vector & increment); /* ------------------------------------------------------------------------ */ /* Boundaries (solid_mechanics_model_boundary.cc) */ /* ------------------------------------------------------------------------ */ public: class SurfaceLoadFunctor { public: virtual void operator()(__attribute__ ((unused)) const types::Vector & position, __attribute__ ((unused)) types::Vector & traction, __attribute__ ((unused)) const types::Vector & normal, __attribute__ ((unused)) Surface surface_id) { AKANTU_DEBUG_TO_IMPLEMENT(); } virtual void operator()(__attribute__ ((unused)) const types::Vector & position, __attribute__ ((unused)) types::Matrix & stress, __attribute__ ((unused)) const types::Vector & normal, __attribute__ ((unused)) Surface surface_id) { AKANTU_DEBUG_TO_IMPLEMENT(); } }; /// compute force vector from a function(x,y,z) that describe stresses void computeForcesFromFunction(BoundaryFunction in_function, BoundaryFunctionType function_type) __attribute__((deprecated)); template void computeForcesFromFunction(Functor & functor, BoundaryFunctionType function_type); /// integrate a force on the boundary by providing a stress tensor void computeForcesByStressTensor(const Vector & stresses, const ElementType & type, const GhostType & ghost_type); /// integrate a force on the boundary by providing a traction vector void computeForcesByTractionVector(const Vector & tractions, const ElementType & type, const GhostType & ghost_type); /// synchronize the ghost element boundaries values void synchronizeBoundaries(); /* ------------------------------------------------------------------------ */ /* Materials (solid_mechanics_model_material.cc) */ /* ------------------------------------------------------------------------ */ public: + /// register a material in the dynamic database + Material & registerNewMaterial(const ID & mat_type, + const std::string & opt_param = ""); + + template + Material & registerNewCurtomMaterial(const ID & mat_type, + const std::string & opt_param = ""); /// read the material files to instantiate all the materials void readMaterials(const std::string & filename); /// read a custom material with a keyword and class as template template UInt readCustomMaterial(const std::string & filename, const std::string & keyword); /// Use a UIntData in the mesh to specify the material to use per element void setMaterialIDsFromIntData(const std::string & data_name); protected: - /// read properties part of a material file and create the material - template - Material * readMaterialProperties(std::ifstream & infile, - ID mat_id, - UInt ¤t_line); + // /// read properties part of a material file and create the material + // template + // Material * readMaterialProperties(std::ifstream & infile, + // ID mat_id, + // UInt ¤t_line); /* ------------------------------------------------------------------------ */ /* Mass (solid_mechanics_model_mass.cc) */ /* ------------------------------------------------------------------------ */ public: /// assemble the lumped mass matrix void assembleMassLumped(); /// assemble the mass matrix void assembleMass(); protected: /// assemble the lumped mass matrix for local and ghost elements void assembleMassLumped(GhostType ghost_type); void assembleMass(GhostType ghost_type); /// fill a vector of rho void computeRho(Vector & rho, ElementType type, GhostType ghost_type); /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ public: inline virtual UInt getNbDataToPack(const Element & element, SynchronizationTag tag) const; inline virtual UInt getNbDataToUnpack(const Element & element, SynchronizationTag tag) const; inline virtual void packData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag) const; inline virtual void unpackData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag); inline virtual UInt getNbDataToPack(SynchronizationTag tag) const; inline virtual UInt getNbDataToUnpack(SynchronizationTag tag) const; inline virtual void packData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const; inline virtual void unpackData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag); /* ------------------------------------------------------------------------ */ /* 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 AKANTU_SET_MACRO(TimeStep, time_step, Real); /// 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, Vector &); /// get the SolidMechanicsModel::current_position vector \warn only consistent /// after a call to SolidMechanicsModel::updateCurrentPosition AKANTU_GET_MACRO(CurrentPosition, *current_position, const Vector &); /// get the SolidMechanicsModel::increment vector \warn only consistent if /// SolidMechanicsModel::setIncrementFlagOn has been called before AKANTU_GET_MACRO(Increment, *increment, Vector &); /// get the lumped SolidMechanicsModel::mass vector AKANTU_GET_MACRO(Mass, *mass, Vector &); /// get the SolidMechanicsModel::velocity vector AKANTU_GET_MACRO(Velocity, *velocity, Vector &); /// get the SolidMechanicsModel::acceleration vector, updated by /// SolidMechanicsModel::updateAcceleration AKANTU_GET_MACRO(Acceleration, *acceleration, Vector &); /// get the SolidMechanicsModel::force vector (boundary forces) AKANTU_GET_MACRO(Force, *force, Vector &); /// get the SolidMechanicsModel::residual vector, computed by /// SolidMechanicsModel::updateResidual AKANTU_GET_MACRO(Residual, *residual, Vector &); /// get the SolidMechanicsModel::boundary vector AKANTU_GET_MACRO(Boundary, *boundary, Vector &); /// get the SolidMechnicsModel::incrementAcceleration vector AKANTU_GET_MACRO(IncrementAcceleration, *increment_acceleration, Vector &); /// get the value of the SolidMechanicsModel::increment_flag AKANTU_GET_MACRO(IncrementFlag, increment_flag, bool); /// get the SolidMechanicsModel::element_material vector corresponding to a /// given akantu::ElementType AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementMaterial, element_material, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementMaterial, element_material, UInt); /// vectors containing local material element index for each global element index AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementIndexByMaterial, element_index_by_material, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementIndexByMaterial, element_index_by_material, UInt); /// get a particular material inline Material & getMaterial(UInt mat_index); inline const Material & getMaterial(UInt mat_index) const; - /// push a new material object - void pushNewMaterial(Material * mat); - /// give the number of materials inline UInt getNbMaterials() const { return materials.size(); }; /// compute the stable time step Real getStableTimeStep(); /// compute the potential energy Real getPotentialEnergy(); /// compute the kinetic energy Real getKineticEnergy(); + /// compute the external work (for impose displacement, the velocity should be given too) + Real getExternalWork(); + /// get the energies Real getEnergy(std::string id); /// set the Contact object AKANTU_SET_MACRO(Contact, contact, Contact *); /** * @brief set the SolidMechanicsModel::increment_flag to on, the activate the * update of the SolidMechanicsModel::increment vector */ void setIncrementFlagOn(); /// get the stiffness matrix AKANTU_GET_MACRO(StiffnessMatrix, *stiffness_matrix, SparseMatrix &); /// get the mass matrix AKANTU_GET_MACRO(MassMatrix, *mass_matrix, SparseMatrix &); inline FEM & getFEMBoundary(std::string name = ""); /// get integrator AKANTU_GET_MACRO(Integrator, *integrator, const IntegrationScheme2ndOrder &); /// get access to the internal solver AKANTU_GET_MACRO(Solver, *solver, Solver &); protected: /// compute the stable time step Real getStableTimeStep(const GhostType & ghost_type); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// time step Real time_step; /// conversion coefficient form force/mass to acceleration Real f_m2a; /// displacements array Vector * displacement; /// lumped mass array Vector * mass; /// velocities array Vector * velocity; /// accelerations array Vector * acceleration; /// accelerations array Vector * increment_acceleration; /// forces array Vector * force; /// residuals array Vector * residual; /// boundaries array Vector * boundary; /// array of current position used during update residual Vector * current_position; /// mass matrix SparseMatrix * mass_matrix; /// velocity damping matrix SparseMatrix * velocity_damping_matrix; /// stiffness matrix SparseMatrix * stiffness_matrix; /// jacobian matrix @f[A = cM + dD + K@f] with @f[c = \frac{1}{\beta \Delta t^2}, d = \frac{\gamma}{\beta \Delta t} @f] SparseMatrix * jacobian_matrix; /// materials of all elements ByElementTypeUInt element_material; /// vectors containing local material element index for each global element index ByElementTypeUInt element_index_by_material; /// list of used materials std::vector materials; /// integration scheme of second order used IntegrationScheme2ndOrder * integrator; /// increment of displacement Vector * increment; /// flag defining if the increment must be computed or not bool increment_flag; /// solver for implicit Solver * solver; /// object to resolve the contact Contact * contact; /// the spatial dimension UInt spatial_dimension; /// Mesh Mesh & mesh; AnalysisMethod method; }; __END_AKANTU__ /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material.hh" #include "parser.hh" __BEGIN_AKANTU__ #include "solid_mechanics_model_tmpl.hh" #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "solid_mechanics_model_inline_impl.cc" #endif /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const SolidMechanicsModel & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_SOLID_MECHANICS_MODEL_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_material.cc b/src/model/solid_mechanics/solid_mechanics_model_material.cc index fd3b0e330..2bf6d78c0 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_material.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_material.cc @@ -1,199 +1,193 @@ /** * @file solid_mechanics_model_material.cc * @author Guillaume ANCIAUX * @date Thu Nov 25 10:48:53 2010 * * @brief * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "material.hh" #include "aka_math.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #define AKANTU_INTANTIATE_MATERIAL_BY_DYM_NO_TMPL(dim, elem) \ - material = parser.readSection< BOOST_PP_ARRAY_ELEM(1, elem)< dim >, \ - SolidMechanicsModel >(*this, mat_id) - + material = \ + &(registerNewCurtomMaterial< BOOST_PP_ARRAY_ELEM(1, elem)< dim > >(mat_type, \ + opt_param)) #define AKANTU_INTANTIATE_MATERIAL_BY_DYM_TMPL_EACH(r, data, i, elem) \ BOOST_PP_EXPR_IF(BOOST_PP_NOT_EQUAL(0, i), else ) \ if(opt_param == BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, elem))) { \ material = \ - parser.readSection< BOOST_PP_ARRAY_ELEM(1, data)< BOOST_PP_ARRAY_ELEM(0, data), \ - BOOST_PP_TUPLE_ELEM(2, 1, elem) >, \ - SolidMechanicsModel >(*this, mat_id); \ + &(registerNewCurtomMaterial< BOOST_PP_ARRAY_ELEM(1, data)< BOOST_PP_ARRAY_ELEM(0, data), \ + BOOST_PP_TUPLE_ELEM(2, 1, elem) > >(mat_type, opt_param)); \ } #define AKANTU_INTANTIATE_MATERIAL_BY_DYM_TMPL(dim, elem) \ BOOST_PP_SEQ_FOR_EACH_I(AKANTU_INTANTIATE_MATERIAL_BY_DYM_TMPL_EACH, \ (2, (dim, BOOST_PP_ARRAY_ELEM(1, elem))), \ BOOST_PP_ARRAY_ELEM(2, elem)) \ else { \ AKANTU_INTANTIATE_MATERIAL_BY_DYM_NO_TMPL(dim, elem); \ } -// #define AKANTU_INTANTIATE_MATERIAL_BY_DIM(dim, elem) -// material = -// parser.readSection, -// SolidMechanicsModel>(*this, mat_id) - #define AKANTU_INTANTIATE_MATERIAL_BY_DIM(dim, elem) \ BOOST_PP_IF(BOOST_PP_EQUAL(3, BOOST_PP_ARRAY_SIZE(elem) ), \ AKANTU_INTANTIATE_MATERIAL_BY_DYM_TMPL, \ AKANTU_INTANTIATE_MATERIAL_BY_DYM_NO_TMPL)(dim, elem) #define AKANTU_INTANTIATE_MATERIAL(elem) \ switch(spatial_dimension) { \ case 1: { AKANTU_INTANTIATE_MATERIAL_BY_DIM(1, elem); break; } \ case 2: { AKANTU_INTANTIATE_MATERIAL_BY_DIM(2, elem); break; } \ case 3: { AKANTU_INTANTIATE_MATERIAL_BY_DIM(3, elem); break; } \ } #define AKANTU_INTANTIATE_MATERIAL_IF(elem) \ if (mat_type == BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(0, elem))) { \ AKANTU_INTANTIATE_MATERIAL(elem); \ } #define AKANTU_INTANTIATE_OTHER_MATERIAL(r, data, elem) \ else AKANTU_INTANTIATE_MATERIAL_IF(elem) #define AKANTU_INSTANTIATE_MATERIALS() \ do { \ AKANTU_INTANTIATE_MATERIAL_IF(BOOST_PP_SEQ_HEAD(AKANTU_MATERIAL_LIST)) \ BOOST_PP_SEQ_FOR_EACH(AKANTU_INTANTIATE_OTHER_MATERIAL, \ _, \ BOOST_PP_SEQ_TAIL(AKANTU_MATERIAL_LIST)) \ else \ AKANTU_DEBUG_ERROR("Malformed material file : unknown material type " \ << mat_type); \ } while(0) /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::readMaterials(const std::string & filename) { Parser parser; parser.open(filename); std::string opt_param; std::string mat_type = parser.getNextSection("material", opt_param); - UInt mat_count = 0; while (mat_type != ""){ - std::stringstream sstr_mat; sstr_mat << id << ":" << mat_count++ << ":" << mat_type; - Material * material; - ID mat_id = sstr_mat.str(); - /// read the material properties - - // add all the new materials in the AKANTU_MATERIAL_LIST in the material.hh file - AKANTU_INSTANTIATE_MATERIALS(); - - materials.push_back(material); + Material & mat = registerNewMaterial(mat_type, opt_param); + parser.readSection(mat.getID(), mat); mat_type = parser.getNextSection("material", opt_param); } parser.close(); } +/* -------------------------------------------------------------------------- */ +Material & SolidMechanicsModel::registerNewMaterial(const ID & mat_type, + const std::string & opt_param) { + // UInt mat_count = materials.size(); + + // std::stringstream sstr_mat; sstr_mat << id << ":" << mat_count << ":" << mat_type; + // Material * material; + // ID mat_id = sstr_mat.str(); + + // // add all the new materials in the AKANTU_MATERIAL_LIST in the material.hh file + // AKANTU_INSTANTIATE_MATERIALS(); + // materials.push_back(material); + Material * material; + + AKANTU_INSTANTIATE_MATERIALS(); + + return *material; +} + /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initMaterials() { AKANTU_DEBUG_ASSERT(materials.size() != 0, "No material to initialize !"); Material ** mat_val = &(materials.at(0)); /// @todo synchronize element material for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; /// fill the element filters of the materials using the element_material arrays Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt); Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt); for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, gt); UInt * elem_mat_val = element_material(*it, gt).storage(); element_index_by_material.alloc(nb_element, 1, *it, gt); for (UInt el = 0; el < nb_element; ++el) { UInt index = mat_val[elem_mat_val[el]]->addElement(*it, el, gt); element_index_by_material(*it, gt)(el) = index; } } } std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { /// init internals properties (*mat_it)->initMaterial(); } synch_registry->synchronize(_gst_smm_init_mat); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::setMaterialIDsFromIntData(const std::string & data_name) { for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt); Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt); for(; it != end; ++it) { try { const Vector & data = mesh.getUIntData(*it, data_name, gt); AKANTU_DEBUG_ASSERT(element_material.exists(*it, gt), "element_material for type (" << gt << ":" << *it << ") does not exists!"); element_material(*it, gt).copy(data); } catch(...) { AKANTU_DEBUG_ERROR("No data named " << data_name << " present in the mesh " << id << " for the element type " << *it); } } } } /* -------------------------------------------------------------------------- */ -void SolidMechanicsModel::pushNewMaterial(Material * mat){ - materials.push_back(mat); -} -/* -------------------------------------------------------------------------- */ - - - - __END_AKANTU__ diff --git a/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh b/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh index 00a98ca67..7aefeef82 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh +++ b/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh @@ -1,143 +1,162 @@ /** * @file solid_mechanics_model_tmpl.hh * @author Nicolas Richart * @date Thu Nov 24 08:45:57 2011 * * @brief template part of solid mechanics model * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ +/* -------------------------------------------------------------------------- */ +template +Material & SolidMechanicsModel::registerNewCurtomMaterial(const ID & mat_type, + const std::string & opt_param) { + UInt mat_count = materials.size(); + + std::stringstream sstr_mat; sstr_mat << id << ":" << mat_count << ":" << mat_type; + Material * material; + ID mat_id = sstr_mat.str(); + + // add all the new materials in the AKANTU_MATERIAL_LIST in the material.hh file + material = new M(*this, mat_id); + materials.push_back(material); + + return *material; +} + + + /* -------------------------------------------------------------------------- */ template UInt SolidMechanicsModel::readCustomMaterial(const std::string & filename, const std::string & keyword) { Parser parser; parser.open(filename); std::string key = keyword; std::string opt_param; std::string mat_name = parser.getNextSection("material", opt_param); while (mat_name != ""){ if (mat_name == key) break; mat_name = parser.getNextSection("material", opt_param); } if (mat_name != key) AKANTU_DEBUG_ERROR("material " << key << " not found in file " << filename); - std::stringstream sstr_mat; sstr_mat << id << ":" << materials.size() << ":" << key; - ID mat_id = sstr_mat.str(); - Material * mat = parser.readSection(*this, mat_id); - materials.push_back(mat); + + Material & mat = registerNewCurtomMaterial(key, opt_param); + parser.readSection(mat.getID(), mat); + materials.push_back(&mat); return materials.size();; } /* -------------------------------------------------------------------------- */ template void SolidMechanicsModel::computeForcesFromFunction(Functor & functor, BoundaryFunctionType function_type) { /** function type is ** _bft_forces : traction function is given ** _bft_stress : stress function is given */ GhostType ghost_type = _not_ghost; UInt nb_component = 0; switch(function_type) { case _bft_stress: nb_component = spatial_dimension * spatial_dimension; break; case _bft_traction: nb_component = spatial_dimension; break; } Vector funct(0, nb_component, "traction_stress"); Vector quad_coords(0, spatial_dimension, "quad_coords"); //prepare the loop over element types Mesh::type_iterator it = getFEMBoundary().getMesh().firstType(getFEMBoundary().getElementDimension(), ghost_type); Mesh::type_iterator end = getFEMBoundary().getMesh().lastType(getFEMBoundary().getElementDimension(), ghost_type); for(; it != end; ++it) { UInt nb_quad = getFEMBoundary().getNbQuadraturePoints(*it, ghost_type); UInt nb_element = getFEMBoundary().getMesh().getNbElement(*it, ghost_type); funct.resize(nb_element * nb_quad); quad_coords.resize(nb_element * nb_quad); const Vector & normals_on_quad = getFEMBoundary().getNormalsOnQuadPoints(*it, ghost_type); getFEMBoundary().interpolateOnQuadraturePoints(getFEMBoundary().getMesh().getNodes(), quad_coords, spatial_dimension, *it, ghost_type); Vector::const_iterator< types::Vector > normals = normals_on_quad.begin(spatial_dimension); Vector::iterator< types::Vector > qcoord = quad_coords.begin(spatial_dimension); Vector::iterator< UInt > surface_id; bool has_surface_id; try { surface_id = mesh.getSurfaceID(*it, ghost_type).begin(); has_surface_id = true; } catch (...) { has_surface_id = false; } if(function_type == _bft_stress) { Vector::iterator< types::Matrix > stress = funct.begin(spatial_dimension, spatial_dimension); for (UInt el = 0; el < nb_element; ++el) { Surface surf_id = 0; if(has_surface_id) { surf_id = *surface_id; ++surface_id; } for (UInt q = 0; q < nb_quad; ++q, ++stress, ++qcoord, ++normals) { functor(*qcoord, *stress, *normals, surf_id); } } } else if (function_type == _bft_traction) { Vector::iterator< types::Vector > force = funct.begin(spatial_dimension); for (UInt el = 0; el < nb_element; ++el) { Surface surf_id = 0; if(has_surface_id) { surf_id = *surface_id; ++surface_id; } for (UInt q = 0; q < nb_quad; ++q, ++force, ++qcoord, ++normals) { functor(*qcoord, *force, *normals, surf_id); } } } switch(function_type) { case _bft_stress: computeForcesByStressTensor(funct, *it, ghost_type); break; case _bft_traction: computeForcesByTractionVector(funct, *it, ghost_type); break; } } } /* -------------------------------------------------------------------------- */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3789362cf..a523db9f4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,49 +1,49 @@ #=============================================================================== # @file CMakeLists.txt # @author Nicolas Richart # @author Guillaume Anciaux # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== INCLUDE(${AKANTU_CMAKE_DIR}/AkantuTestAndExamples.cmake) #=============================================================================== # List of tests #=============================================================================== -add_akantu_test(test_vector "Test akantu vector") +add_akantu_test(test_common "Test the common part of Akantu") add_akantu_test(test_static_memory "Test static memory") add_akantu_test(test_fem "Test finite element functionalties") add_akantu_test(test_mesh_utils "Test mesh utils") add_akantu_test(test_model "Test model objects") add_akantu_test(test_solver "Test solver function") if(AKANTU_CONTACT) #add_akantu_test(test_contact_neighbor_structure "Test contact neighbor structure") add_akantu_test(test_surface_extraction "Test mesh utils surface extraction") endif(AKANTU_CONTACT) if(AKANTU_MPI) add_akantu_test(test_synchronizer "Test synchronizers") endif(AKANTU_MPI) diff --git a/test/test_vector/CMakeLists.txt b/test/test_common/CMakeLists.txt similarity index 83% copy from test/test_vector/CMakeLists.txt copy to test/test_common/CMakeLists.txt index fd01e5e57..c3b42cd46 100644 --- a/test/test_vector/CMakeLists.txt +++ b/test/test_common/CMakeLists.txt @@ -1,29 +1,28 @@ #=============================================================================== # @file CMakeLists.txt -# @author Guillaume Anciaux -# @date Fri Jun 11 09:46:59 2010 +# @author Nicolas Richart +# @date Mon Jul 23 17:11:41 2012 +# +# @brief # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # -# @section DESCRIPTION -# #=============================================================================== - -REGISTER_TEST(test_vector test_vector.cc) -REGISTER_TEST(test_matrix test_matrix.cc) +add_akantu_test(test_vector "Test akantu vector") +REGISTER_TEST(test_csr test_csr.cc) \ No newline at end of file diff --git a/test/test_common/test_csr.cc b/test/test_common/test_csr.cc new file mode 100644 index 000000000..af712d7c3 --- /dev/null +++ b/test/test_common/test_csr.cc @@ -0,0 +1,119 @@ +/** + * @file test_csr.cc + * @author Nicolas Richart + * @date Mon Jul 23 16:40:06 2012 + * + * @brief Test the CSR (compressed sparse row) data structure + * + * @section LICENSE + * + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see . + * + */ + +/* -------------------------------------------------------------------------- */ + +#include + + +#include "aka_common.hh" +#include "aka_csr.hh" + +using namespace akantu; + +#define N 1000 + +int main(int argc, char *argv[]) { + + CSR csr; + + std::vector nb_cols_per_row; + + csr.resizeRows(N); + csr.clearRows(); + + for (UInt i = 0; i < N; ++i) { + UInt nb_cols(rand()*double(N)/(RAND_MAX+1.)); + nb_cols_per_row.push_back(nb_cols); + for (UInt j = 0; j < nb_cols; ++j) { + ++csr.rowOffset(i); + } + } + + csr.countToCSR(); + csr.resizeCols(); + + csr.beginInsertions(); + for (UInt i = 0; i < N; ++i) { + UInt nb_cols = nb_cols_per_row[i]; + for (UInt j = 0; j < nb_cols; ++j) { + csr.insertInRow(i, nb_cols - j); + } + } + csr.endInsertions(); + + if(csr.getNbRows() != N) { + AKANTU_DEBUG_ERROR("The number of rows does not correspond: " + << csr.getNbRows() + << " != " + << N); + } + + for (UInt i = 0; i < csr.getNbRows(); ++i) { + CSR::iterator it = csr.begin(i); + CSR::iterator end = csr.end(i); + UInt nb_cols = nb_cols_per_row[i]; + for (; it != end; ++it) { + if(nb_cols != *it) { + AKANTU_DEBUG_ERROR("The numbers stored in the row " << i << " are not correct: " + << nb_cols + << " != " + << *it); + } + nb_cols--; + } + + if(nb_cols != 0) { + AKANTU_DEBUG_ERROR("Not enough columns in the row " << i << ": " + << nb_cols); + } + } + + for (UInt i = 0; i < csr.getNbRows(); ++i) { + CSR::iterator it = csr.rbegin(i); + CSR::iterator end = csr.rend(i); + + UInt nb_cols = nb_cols_per_row[i]; + UInt j = nb_cols; + + for (; it != end; --it) { + if((nb_cols - j + 1) != *it) { + AKANTU_DEBUG_ERROR("Reverse: The numbers stored in the row " << i << " are not correct: " + << (nb_cols - j + 1) + << " != " + << *it); + } + j--; + } + + if(j != 0) AKANTU_DEBUG_ERROR("Reverse: Not enough columns in the row " << i << ": " + << j); + } + + + return EXIT_SUCCESS; +} diff --git a/test/test_vector/CMakeLists.txt b/test/test_common/test_vector/CMakeLists.txt similarity index 88% rename from test/test_vector/CMakeLists.txt rename to test/test_common/test_vector/CMakeLists.txt index fd01e5e57..ee6657254 100644 --- a/test/test_vector/CMakeLists.txt +++ b/test/test_common/test_vector/CMakeLists.txt @@ -1,29 +1,30 @@ #=============================================================================== # @file CMakeLists.txt # @author Guillaume Anciaux # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== -REGISTER_TEST(test_vector test_vector.cc) -REGISTER_TEST(test_matrix test_matrix.cc) +register_test(test_vector test_vector.cc) +register_test(test_vector_iterator test_vector_iterator.cc) +register_test(test_matrix test_matrix.cc) diff --git a/test/test_vector/test_matrix.cc b/test/test_common/test_vector/test_matrix.cc similarity index 100% rename from test/test_vector/test_matrix.cc rename to test/test_common/test_vector/test_matrix.cc diff --git a/test/test_vector/test_vector.cc b/test/test_common/test_vector/test_vector.cc similarity index 76% copy from test/test_vector/test_vector.cc copy to test/test_common/test_vector/test_vector.cc index 424eac070..4c97bc7af 100644 --- a/test/test_vector/test_vector.cc +++ b/test/test_common/test_vector/test_vector.cc @@ -1,96 +1,73 @@ /** * @file test_vector.cc * @author Nicolas Richart * @date Tue Jun 29 17:32:23 2010 * * @brief test of the vector 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 #include /* -------------------------------------------------------------------------- */ #include "aka_types.hh" #include "aka_vector.hh" /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { int def_value[3]; def_value[0] = 10; def_value[1] = 20; def_value[2] = 30; std::cout << "Creating a vector" << std::endl; akantu::Vector int_vect(10, 3, def_value, "test1"); for (unsigned int i = 5; i < int_vect.getSize(); ++i) { for (unsigned int j = 0; j < int_vect.getNbComponent(); ++j) { int_vect.values[i*int_vect.getNbComponent() + j] = def_value[j]*10; } } std::cerr << int_vect; int new_elem[3]; new_elem[0] = 1; new_elem[1] = 2; new_elem[2] = 3; std::cout << "Testing push_back" << std::endl; int_vect.push_back(new_elem); int_vect.push_back(200); int_vect.erase(0); std::cerr << int_vect; akantu::Vector int_vect0(0, 3, def_value, "test2"); std::cerr << int_vect0; int_vect0.push_back(new_elem); std::cerr << int_vect0; - std::cout << "Creating a vector of matrices (2,2)" << std::endl; - akantu::Vector mat_vect(10, 4, 1.); - memset(mat_vect.values, 0, 10*4*sizeof(double)); - - typedef akantu::Vector RealVector; - - akantu::types::Matrix m1(2, 3, 1.); - akantu::types::Matrix m2(3, 5, 2.); - akantu::types::Matrix m3; - m3 = m1 * m2; - std::cout << m1 << m2 << m3; - - std::cout << "Iterating on a Matrix(2,2)" << std::endl; - RealVector::iterator itm; - itm = mat_vect.begin(2, 2); - RealVector::iterator endm = mat_vect.end(2, 2); - - for (; itm != endm; ++itm) { - std::cout << *itm << std::endl; - } - - int_vect0.resize(0); - return EXIT_SUCCESS; } diff --git a/test/test_vector/test_vector.cc b/test/test_common/test_vector/test_vector_iterator.cc similarity index 57% rename from test/test_vector/test_vector.cc rename to test/test_common/test_vector/test_vector_iterator.cc index 424eac070..69fc690b1 100644 --- a/test/test_vector/test_vector.cc +++ b/test/test_common/test_vector/test_vector_iterator.cc @@ -1,96 +1,85 @@ /** - * @file test_vector.cc + * @file test_vector_iterator.cc * @author Nicolas Richart - * @date Tue Jun 29 17:32:23 2010 + * @date Fri Jul 27 11:24:44 2012 * - * @brief test of the vector class + * @brief test the iterator present in the vector 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 #include +#include +#include /* -------------------------------------------------------------------------- */ -#include "aka_types.hh" +#include "aka_common.hh" #include "aka_vector.hh" - - +#include "aka_types.hh" /* -------------------------------------------------------------------------- */ -int main(int argc, char *argv[]) { - int def_value[3]; - def_value[0] = 10; - def_value[1] = 20; - def_value[2] = 30; - - std::cout << "Creating a vector" << std::endl; - akantu::Vector int_vect(10, 3, def_value, "test1"); - - for (unsigned int i = 5; i < int_vect.getSize(); ++i) { - for (unsigned int j = 0; j < int_vect.getNbComponent(); ++j) { - int_vect.values[i*int_vect.getNbComponent() + j] = def_value[j]*10; - } - } - - std::cerr << int_vect; - - int new_elem[3]; - new_elem[0] = 1; - new_elem[1] = 2; - new_elem[2] = 3; - std::cout << "Testing push_back" << std::endl; - int_vect.push_back(new_elem); +using namespace akantu; - int_vect.push_back(200); +#define N 10 - int_vect.erase(0); - - std::cerr << int_vect; - akantu::Vector int_vect0(0, 3, def_value, "test2"); - std::cerr << int_vect0; - int_vect0.push_back(new_elem); - std::cerr << int_vect0; +int main(int argc, char *argv[]) { + typedef Vector RealVector; std::cout << "Creating a vector of matrices (2,2)" << std::endl; - akantu::Vector mat_vect(10, 4, 1.); - memset(mat_vect.values, 0, 10*4*sizeof(double)); - - typedef akantu::Vector RealVector; - - akantu::types::Matrix m1(2, 3, 1.); - akantu::types::Matrix m2(3, 5, 2.); - akantu::types::Matrix m3; - m3 = m1 * m2; - std::cout << m1 << m2 << m3; + RealVector mat_vect(N, 4, 0.); std::cout << "Iterating on a Matrix(2,2)" << std::endl; RealVector::iterator itm; itm = mat_vect.begin(2, 2); RealVector::iterator endm = mat_vect.end(2, 2); for (; itm != endm; ++itm) { std::cout << *itm << std::endl; } - int_vect0.resize(0); + std::cout << "Creating a vector of UInt" << std::endl; + Vector vect(N, 1, 0.); + + std::cout << "Iterating on a UInt" << std::endl; + Vector::iterator it = vect.begin(); + Vector::iterator end = vect.end(); + + std::vector test_vect; + + for (; it != end; ++it) { + UInt r = rand() % N; + *it = r; + test_vect.push_back(r); + std::cout << *it <::iterator itv = test_vect.begin(); + for (it = vect.begin(); it != end; ++it, ++itv) { + std::cout << *it << " " << *itv << std::endl; + if(*it != *itv) + AKANTU_DEBUG_ERROR("The sort of the vector gived bad results ("<< *it << " != " << *itv << ")"); + } return EXIT_SUCCESS; } diff --git a/test/test_fem/CMakeLists.txt b/test/test_fem/CMakeLists.txt index 4b0a83eaa..daffde655 100644 --- a/test/test_fem/CMakeLists.txt +++ b/test/test_fem/CMakeLists.txt @@ -1,78 +1,78 @@ #=============================================================================== # @file CMakeLists.txt # @author Guillaume Anciaux # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== #=============================================================================== -register_test(test_interpolate_bernoulli_beam_2 test_interpolate_bernoulli_beam_2.cc) +#register_test(test_interpolate_bernoulli_beam_2 test_interpolate_bernoulli_beam_2.cc) #=============================================================================== set(LIST_TYPES segment_2 segment_3 triangle_3 triangle_6 quadrangle_4 quadrangle_8 tetrahedron_4 tetrahedron_10 hexahedron_8 ) add_mesh(test_fem_segment_2_mesh line.geo 1 1 OUTPUT segment_2.msh) add_mesh(test_fem_segment_3_mesh line.geo 1 2 OUTPUT segment_3.msh) add_mesh(test_fem_triangle_3_mesh square.geo 2 1 OUTPUT triangle_3.msh) add_mesh(test_fem_triangle_6_mesh square.geo 2 2 OUTPUT triangle_6.msh) add_mesh(test_fem_quadrangle_4_mesh square_structured.geo 2 1 OUTPUT quadrangle_4.msh) add_mesh(test_fem_quadrangle_8_mesh square_structured.geo 2 2 OUTPUT quadrangle_8.msh) add_mesh(test_fem_tetrahedron_4_mesh cube.geo 3 1 OUTPUT tetrahedron_4.msh) add_mesh(test_fem_tetrahedron_10_mesh cube.geo 3 2 OUTPUT tetrahedron_10.msh) add_mesh(test_fem_hexahedron_8_mesh hexa_structured.geo 3 1 OUTPUT hexahedron_8.msh) macro(register_fem_test operation type) set(_target test_${operation}_${_type}) register_test(${_target} test_${operation}.cc) set_target_properties(${_target} PROPERTIES COMPILE_DEFINITIONS TYPE=_${_type}) if(NOT EXISTS ${_type}.msh) add_dependencies(${_target} test_fem_${_type}_mesh) endif() endmacro() foreach(_type ${LIST_TYPES}) register_fem_test(interpolate ${_type}) register_fem_test(gradient ${_type}) register_fem_test(integrate ${_type}) register_fem_test(inverse_map ${_type}) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_type}.msh) file(COPY ${_type}.msh DESTINATION .) endif() endforeach() #add_mesh(test_fem_circle_1_mesh circle.geo 2 1 OUTPUT circle1.msh) #add_mesh(test_fem_circle_2_mesh circle.geo 2 2 OUTPUT circle2.msh) diff --git a/test/test_fem/test_gradient.cc b/test/test_fem/test_gradient.cc index 1db1772db..f8e0e1630 100644 --- a/test/test_fem/test_gradient.cc +++ b/test/test_fem/test_gradient.cc @@ -1,147 +1,147 @@ /** * @file test_gradient_XXXX.cc * @author Nicolas Richart * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * * @section DESCRIPTION * * This code is computing the gradient of a linear field and check that it gives * a constant result. It also compute the gradient the coordinates of the mesh * and check that it gives the identity * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "shape_lagrange.hh" #include "integrator_gauss.hh" /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { akantu::initialize(argc, argv); debug::setDebugLevel(dblTest); const ElementType type = TYPE; UInt dim = ElementClass::getSpatialDimension(); - Real eps = 3e-13; + Real eps = 1e-12; std::cout << "Epsilon : " << eps << std::endl; MeshIOMSH mesh_io; Mesh my_mesh(dim); std::stringstream meshfilename; meshfilename << type << ".msh"; mesh_io.read(meshfilename.str(), my_mesh); FEM *fem = new FEMTemplate(my_mesh, dim, "my_fem"); std::stringstream outfilename; outfilename << "out_" << type << ".txt"; std::ofstream my_file(outfilename.str().c_str()); fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Real alpha[2][3] = {{13, 23, 31}, {11, 7, 5}}; /// create the 2 component field const Vector & position = fem->getMesh().getNodes(); Vector const_val(fem->getMesh().getNbNodes(), 2, "const_val"); UInt nb_element = my_mesh.getNbElement(type); UInt nb_quadrature_points = fem->getNbQuadraturePoints(type) * nb_element; Vector grad_on_quad(nb_quadrature_points, 2 * dim, "grad_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val(i, 0) = 0; const_val(i, 1) = 0; for (UInt d = 0; d < dim; ++d) { const_val(i, 0) += alpha[0][d] * position(i, d); const_val(i, 1) += alpha[1][d] * position(i, d); } } /// compute the gradient fem->gradientOnQuadraturePoints(const_val, grad_on_quad, 2, type); my_file << const_val << std::endl; my_file << grad_on_quad << std::endl; std::cout << grad_on_quad << std::endl; /// check the results Vector::iterator it = grad_on_quad.begin(2,dim); Vector::iterator it_end = grad_on_quad.end(2,dim); for (;it != it_end; ++it) { for (UInt d = 0; d < dim; ++d) { if(!(std::abs((*it)(0, d) - alpha[0][d]) < eps) || !(std::abs((*it)(1, d) - alpha[1][d]) < eps)) { std::cout << "Error gradient is not correct " << (*it)(0, d) << " " << alpha[0][d] << " (" << std::abs((*it)(0, d) - alpha[0][d]) << ")" << " - " << (*it)(1, d) << " " << alpha[1][d] << " (" << std::abs((*it)(1, d) - alpha[1][d]) << ")" << " - " << d << std::endl; std::cout << *it << std::endl; exit(EXIT_FAILURE); } } } // compute gradient of coordinates Vector grad_coord_on_quad(nb_quadrature_points, dim * dim, "grad_coord_on_quad"); fem->gradientOnQuadraturePoints(my_mesh.getNodes(), grad_coord_on_quad, my_mesh.getSpatialDimension(), type); my_file << my_mesh.getNodes() << std::endl; my_file << grad_coord_on_quad << std::endl; Vector::iterator itp = grad_coord_on_quad.begin(dim, dim); Vector::iterator itp_end = grad_coord_on_quad.end(dim, dim); for (;itp != itp_end; ++itp) { for (UInt i = 0; i < dim; ++i) { for (UInt j = 0; j < dim; ++j) { if(!(std::abs((*itp)(i,j) - (i == j)) < eps)) { std::cout << *itp << std::endl; exit(EXIT_FAILURE); } } } } delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_inverse_map.cc b/test/test_fem/test_inverse_map.cc index 9547fd526..e28b540de 100644 --- a/test/test_fem/test_inverse_map.cc +++ b/test/test_fem/test_inverse_map.cc @@ -1,103 +1,110 @@ /** * @file test_inverse_map_XXXX.cc * @author Guillaume Anciaux * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "shape_lagrange.hh" #include "integrator_gauss.hh" /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { akantu::initialize(argc, argv); debug::setDebugLevel(dblTest); const ElementType type = TYPE; UInt dim = ElementClass::getSpatialDimension(); MeshIOMSH mesh_io; Mesh my_mesh(dim); + Real lower[dim]; + Real upper[dim]; + + my_mesh.computeBoundingBox(); + my_mesh.getLowerBounds(lower); + my_mesh.getUpperBounds(upper); + std::stringstream meshfilename; meshfilename << type << ".msh"; mesh_io.read(meshfilename.str(), my_mesh); UInt nb_elements = my_mesh.getNbElement(type); /// FEMTemplate *fem = new FEMTemplate(my_mesh, dim, "my_fem"); fem->initShapeFunctions(); UInt nb_quad_points = fem->getNbQuadraturePoints(type); /// get the quadrature points coordinates Vector coord_on_quad(nb_quad_points*nb_elements, my_mesh.getSpatialDimension(), "coord_on_quad"); fem->interpolateOnQuadraturePoints(my_mesh.getNodes(), coord_on_quad, my_mesh.getSpatialDimension(), type); /// loop over the quadrature points Vector::iterator it = coord_on_quad.begin(dim); types::RVector natural_coords(dim); Real * quad = ElementClass::getQuadraturePoints(); for(UInt el = 0 ; el < nb_elements ; ++el){ for(UInt q = 0 ; q < nb_quad_points ; ++q){ fem->inverseMap(*it, el, type, natural_coords); for (UInt i = 0; i < dim; ++i) { - const Real eps = 1e-15; - AKANTU_DEBUG_ASSERT(fabs(natural_coords[i] - quad[i]) < eps, + const Real eps = 1e-13; + AKANTU_DEBUG_ASSERT(std::abs((natural_coords[i] - quad[i])/(upper[i]-lower[i])) < eps, "real coordinates inversion test failed:" << natural_coords[i] << " - " << quad[i] - << " = " << natural_coords[i] - quad[i]); + << " = " << (natural_coords[i] - quad[i])/(upper[i]-lower[i])); } ++it; } } std::cout << "inverse completed over " << nb_elements << " elements" << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_utils/CMakeLists.txt b/test/test_mesh_utils/CMakeLists.txt index 37f631b0f..06d3be99f 100644 --- a/test/test_mesh_utils/CMakeLists.txt +++ b/test/test_mesh_utils/CMakeLists.txt @@ -1,39 +1,42 @@ #=============================================================================== # @file CMakeLists.txt # @author Nicolas Richart # @date Wed Feb 2 14:46:59 2011 # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== #=============================================================================== # List of tests #=============================================================================== add_akantu_test(test_mesh_io "Test mesh io object") add_akantu_test(test_facet_extraction "Test mesh utils facet extraction") add_akantu_test(test_pbc_tweak "Test pbc facilities") +register_test(test_purify_mesh test_purify_mesh.cc) +file(COPY purify_mesh.msh DESTINATION .) + if(AKANTU_SCOTCH) add_akantu_test(test_mesh_partitionate "Test mesh partition creation") endif(AKANTU_SCOTCH) diff --git a/test/test_mesh_utils/purify_mesh.msh b/test/test_mesh_utils/purify_mesh.msh new file mode 100644 index 000000000..6781c5086 --- /dev/null +++ b/test/test_mesh_utils/purify_mesh.msh @@ -0,0 +1,38 @@ +$MeshFormat +2.2 0 8 +$EndMeshFormat +$Nodes +25 +1 0 0 0 +2 1 0 0 +3 1 1 0 +4 0 1 0 +5 0.6 0 0 +6 1 0.7 0 +7 0.6 1 0 +8 0 0.7 0 +9 0.6 0.7 0 +10 0.3 0 0 +11 0.6 0.35 0 +12 0.3 0.7 0 +13 0 0.35 0 +14 0.3 0.35 0 +15 0.6 0.85 0 +16 0.3 1 0 +17 0 0.85 0 +18 0.3 0.85 0 +19 0.8 0 0 +20 1 0.35 0 +21 0.8 0.7 0 +22 0.8 0.35 0 +23 1 0.85 0 +24 0.8 1 0 +25 0.8 0.85 0 +$EndNodes +$Elements +4 +1 16 2 6 101 1 5 9 8 10 11 12 13 +2 16 2 6 101 8 9 7 4 12 15 16 17 +3 16 2 6 101 5 2 6 9 19 20 21 11 +4 16 2 6 101 9 6 3 7 21 23 24 15 +$EndElements diff --git a/test/test_mesh_utils/test_purify_mesh.cc b/test/test_mesh_utils/test_purify_mesh.cc new file mode 100644 index 000000000..1cc009141 --- /dev/null +++ b/test/test_mesh_utils/test_purify_mesh.cc @@ -0,0 +1,59 @@ +/** + * @file test_purify_mesh.cc + * @author Nicolas Richart + * @date Fri Jul 27 17:15:11 2012 + * + * @brief Test the purifyMesh function from MeshUtils + * + * @section LICENSE + * + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see . + * + */ + +/* -------------------------------------------------------------------------- */ + +#include "mesh.hh" +#include "mesh_utils.hh" +#include "mesh_io.hh" + +using namespace akantu; + +int main(int argc, char *argv[]) { + akantu::initialize(argc, argv); + + Mesh mesh(2); + + MeshIOMSH mesh_io; + mesh_io.read("purify_mesh.msh", mesh); + + MeshUtils::purifyMesh(mesh); + + mesh_io.write("purify_mesh_after.msh", mesh); + + if(mesh.getNbNodes() != 21) + AKANTU_DEBUG_ERROR("The purified mesh does not contain the good number of nodes."); + + if(mesh.getNbElement(_quadrangle_8) != 4) + AKANTU_DEBUG_ERROR("The purified mesh does not contain the good number of element."); + + + akantu::finalize(); + + return EXIT_SUCCESS; +} + diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/patch_tests/CMakeLists.txt index a2dae61b6..66bd432f8 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/patch_tests/CMakeLists.txt @@ -1,60 +1,63 @@ #=============================================================================== # @file CMakeLists.txt # @author David Kammer # @date Wed Feb 16 09:46:59 2010 # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== add_mesh(test_weight_hexa_mesh colone_hexa.geo 3 1) add_mesh(test_weight_tetra_mesh colone_tetra.geo 3 1) register_test(test_weight colone_weight.cc) add_dependencies(test_weight test_weight_hexa_mesh test_weight_tetra_mesh) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/material_colone.dat ${CMAKE_CURRENT_BINARY_DIR}/material_colone.dat COPYONLY ) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview/test_weight_hexa) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview/test_weight_tetra) #=============================================================================== set(LIST_TYPES segment_2 segment_3 - triangle_3 - triangle_6 - quadrangle_4 - quadrangle_8 tetrahedron_4 tetrahedron_10 hexahedron_8 ) +set(LIST_TYPES_2D + triangle_3 + triangle_6 + quadrangle_4 + quadrangle_8 +) + add_subdirectory(explicit) if(AKANTU_MUMPS) add_subdirectory(implicit) endif() diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress.dat b/test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress.dat index 37b88c936..e4758573c 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress.dat +++ b/test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress.dat @@ -1,7 +1,7 @@ material elastic [ name = steel rho = 7800 # density E = 2.1e11 # young's modulus nu = 0.3 # poisson's ratio - Plane_stress = 1 # plane stress + Plane_stress = 0 # plane stress ] diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress.dat b/test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress_plane_strain.dat similarity index 75% copy from test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress.dat copy to test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress_plane_strain.dat index 37b88c936..c140637d3 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress.dat +++ b/test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress_plane_strain.dat @@ -1,7 +1,7 @@ material elastic [ name = steel rho = 7800 # density E = 2.1e11 # young's modulus nu = 0.3 # poisson's ratio - Plane_stress = 1 # plane stress + Plane_Stress = 0 # plane strain ] diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress.dat b/test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress_plane_stress.dat similarity index 75% copy from test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress.dat copy to test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress_plane_stress.dat index 37b88c936..91d80b72f 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress.dat +++ b/test/test_model/test_solid_mechanics_model/patch_tests/data/material_check_stress_plane_stress.dat @@ -1,7 +1,7 @@ material elastic [ name = steel rho = 7800 # density E = 2.1e11 # young's modulus nu = 0.3 # poisson's ratio - Plane_stress = 1 # plane stress + Plane_Stress = 1 # plane stress ] diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/data/quadrangle_8.msh b/test/test_model/test_solid_mechanics_model/patch_tests/data/quadrangle_8.msh index 0f9328ba8..88f6875d9 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/data/quadrangle_8.msh +++ b/test/test_model/test_solid_mechanics_model/patch_tests/data/quadrangle_8.msh @@ -1,18 +1,34 @@ $MeshFormat -2.1 0 8 +2.2 0 8 $EndMeshFormat $Nodes -8 +21 1 0 0 0 2 1 0 0 3 1 1 0 4 0 1 0 -5 0.4999999999986718 0 0 -6 1 0.4999999999986718 0 -7 0.5000000000013305 1 0 -8 0 0.5000000000013305 0 +5 0.6 0 0 +6 1 0.7 0 +7 0.6 1 0 +8 0 0.7 0 +9 0.6 0.7 0 +10 0.3 0 0 +11 0.6 0.35 0 +12 0.3 0.7 0 +13 0 0.35 0 +14 0.6 0.85 0 +15 0.3 1 0 +16 0 0.85 0 +17 0.8 0 0 +18 1 0.35 0 +19 0.8 0.7 0 +20 1 0.85 0 +21 0.8 1 0 $EndNodes $Elements -1 -1 16 3 6 101 0 1 2 3 4 5 6 7 8 +4 +1 16 2 6 101 1 5 9 8 10 11 12 13 +2 16 2 6 101 8 9 7 4 12 14 15 16 +3 16 2 6 101 5 2 6 9 17 18 19 11 +4 16 2 6 101 9 6 3 7 19 20 21 14 $EndElements diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/explicit/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/patch_tests/explicit/CMakeLists.txt index 39e852d5c..95dd46001 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/explicit/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/patch_tests/explicit/CMakeLists.txt @@ -1,37 +1,47 @@ #=============================================================================== # @file CMakeLists.txt # @author David Kammer # @date Wed Feb 16 09:46:59 2010 # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== +macro(register_patch_test name type plane_strain) + register_test(patch_test_explicit_${name} patch_test_explicit.cc) + file(COPY ../data/${type}.msh DESTINATION .) + set_target_properties(patch_test_explicit_${name} + PROPERTIES COMPILE_DEFINITIONS "TYPE=_${type};PLANE_STRAIN=${plane_strain}") +endmacro() + foreach(_type ${LIST_TYPES}) - register_test(patch_test_explicit_${_type} patch_test_explicit.cc) - set_target_properties(patch_test_explicit_${_type} - PROPERTIES COMPILE_DEFINITIONS TYPE=_${_type}) - file(COPY ../data/${_type}.msh DESTINATION .) + register_patch_test(${_type} ${_type} true) +endforeach() + +foreach(_type ${LIST_TYPES_2D}) + register_patch_test(plane_strain_${_type} ${_type} true) + register_patch_test(plane_stress_${_type} ${_type} false) endforeach() #=============================================================================== -file(COPY ../data/material_check_stress.dat DESTINATION .) +file(COPY ../data/material_check_stress_plane_strain.dat DESTINATION .) +file(COPY ../data/material_check_stress_plane_stress.dat DESTINATION .) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) \ No newline at end of file diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit.cc b/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit.cc index 6cd223c84..7b6053c70 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit.cc +++ b/test/test_model/test_solid_mechanics_model/patch_tests/explicit/patch_test_explicit.cc @@ -1,355 +1,360 @@ /** * @file test_check_stress.cc * @author David Kammer * @date Wed Feb 16 13:56:42 2011 * * @brief patch test for elastic material in solid mechanics model * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "element_class.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.hh" #endif //AKANTU_USE_IOHELPER using namespace akantu; -bool plane_strain = true; + Real alpha [3][4] = { { 0.01, 0.02, 0.03, 0.04 }, { 0.05, 0.06, 0.07, 0.08 }, { 0.09, 0.10, 0.11, 0.12 } }; #ifdef AKANTU_USE_IOHELPER static void paraviewInit(iohelper::Dumper & dumper, const SolidMechanicsModel & model); static void paraviewDump(iohelper::Dumper & dumper); #endif /* -------------------------------------------------------------------------- */ -template +template static types::Matrix prescribed_strain() { UInt spatial_dimension = ElementClass::getSpatialDimension(); types::Matrix strain(spatial_dimension, spatial_dimension); for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < spatial_dimension; ++j) { strain(i, j) = alpha[i][j + 1]; } } return strain; } -template +template static types::Matrix prescribed_stress() { UInt spatial_dimension = ElementClass::getSpatialDimension(); types::Matrix stress(spatial_dimension, spatial_dimension); //plane strain in 2d types::Matrix strain(spatial_dimension, spatial_dimension); - types::Matrix pstrain; pstrain = prescribed_strain(); + types::Matrix pstrain; pstrain = prescribed_strain(); Real nu = 0.3; Real E = 2.1e11; Real trace = 0; /// symetric part of the strain tensor for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) strain(i,j) = 0.5 * (pstrain(i, j) + pstrain(j, i)); for (UInt i = 0; i < spatial_dimension; ++i) trace += strain(i,i); - - if (plane_strain){ - Real Ep = E / (1 + nu); - for (UInt i = 0; i < spatial_dimension; ++i) - for (UInt j = 0; j < spatial_dimension; ++j) { - stress(i, j) = Ep * strain(i,j); - if(i == j) stress(i, j) += Ep * (nu / (1 - 2*nu)) * trace; - } - } - - if (!plane_strain){ - Real Ep = E / (1 + nu); - for (UInt i = 0; i < spatial_dimension; ++i) - for (UInt j = 0; j < spatial_dimension; ++j) { - stress(i, j) = Ep * strain(i,j); - if(i == j) stress(i, j) += (nu * E)/(1-(nu*nu)) * trace; + if(spatial_dimension == 1) { + stress(0, 0) = E * strain(0, 0); + } else { + if (is_plane_strain) { + Real Ep = E / (1 + nu); + for (UInt i = 0; i < spatial_dimension; ++i) + for (UInt j = 0; j < spatial_dimension; ++j) { + stress(i, j) = Ep * strain(i,j); + if(i == j) stress(i, j) += Ep * (nu / (1 - 2*nu)) * trace; + } + } else { + Real Ep = E / (1 + nu); + for (UInt i = 0; i < spatial_dimension; ++i) + for (UInt j = 0; j < spatial_dimension; ++j) { + stress(i, j) = Ep * strain(i,j); + if(i == j) stress(i, j) += (nu * E)/(1-(nu*nu)) * trace; + } } } return stress; } /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { initialize(argc, argv); debug::setDebugLevel(dblWarning); UInt dim = ElementClass::getSpatialDimension(); const ElementType element_type = TYPE; - UInt damping_steps = 400000; + UInt damping_steps = 600000; UInt damping_interval = 50; Real damping_ratio = 0.99; UInt additional_steps = 20000; UInt max_steps = damping_steps + additional_steps; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; std::stringstream filename; filename << TYPE << ".msh"; mesh_io.read(filename.str(), my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization - my_model.initVectors(); - // initialize the vectors - my_model.getForce().clear(); - my_model.getVelocity().clear(); - my_model.getAcceleration().clear(); - my_model.getDisplacement().clear(); - - my_model.initExplicit(); - my_model.initModel(); - my_model.readMaterials("material_check_stress.dat"); - my_model.initMaterials(); + if(PLANE_STRAIN) + my_model.initFull("material_check_stress_plane_strain.dat", _explicit_dynamic); + else + my_model.initFull("material_check_stress_plane_stress.dat", _explicit_dynamic); + std::cout << my_model.getMaterial(0) << std::endl; Real time_step = my_model.getStableTimeStep()/5.; my_model.setTimeStep(time_step); my_model.assembleMassLumped(); std::cout << "The number of time steps is: " << max_steps << " (" << time_step << "s)" << std::endl; // boundary conditions const Vector & coordinates = my_mesh.getNodes(); Vector & displacement = my_model.getDisplacement(); Vector & boundary = my_model.getBoundary(); MeshUtils::buildFacets(my_mesh); MeshUtils::buildSurfaceID(my_mesh); CSR surface_nodes; MeshUtils::buildNodesPerSurface(my_mesh, surface_nodes); for (UInt s = 0; s < surface_nodes.getNbRows(); ++s) { CSR::iterator snode = surface_nodes.begin(s); for(; snode != surface_nodes.end(s); ++snode) { UInt n = *snode; std::cout << "Node " << n << std::endl; for (UInt i = 0; i < dim; ++i) { displacement(n, i) = alpha[i][0]; for (UInt j = 0; j < dim; ++j) { displacement(n, i) += alpha[i][j + 1] * coordinates(n, j); } boundary(n, i) = true; } } } Vector & velocity = my_model.getVelocity(); #ifdef AKANTU_USE_IOHELPER my_model.updateResidual(); iohelper::DumperParaview dumper; paraviewInit(dumper, my_model); #endif std::ofstream energy; std::stringstream energy_filename; energy_filename << "energy_" << TYPE << ".csv"; energy.open(energy_filename.str().c_str()); energy << "id,time,ekin" << std::endl; Real ekin_mean = 0.; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ - for(UInt s = 1; s <= max_steps; ++s) { + UInt s; + for(s = 1; s <= max_steps; ++s) { if(s % 10000 == 0) std::cout << "passing step " << s << "/" << max_steps << " (" << s*time_step << "s)" < & stress_vect = const_cast &>(my_model.getMaterial(0).getStress(element_type)); Vector & strain_vect = const_cast &>(my_model.getMaterial(0).getStrain(element_type)); Vector::iterator stress_it = stress_vect.begin(dim, dim); Vector::iterator strain_it = strain_vect.begin(dim, dim); - types::Matrix presc_stress; presc_stress = prescribed_stress(); - types::Matrix presc_strain; presc_strain = prescribed_strain(); + types::Matrix presc_stress; presc_stress = prescribed_stress(); + types::Matrix presc_strain; presc_strain = prescribed_strain(); UInt nb_element = my_mesh.getNbElement(TYPE); + Real strain_tolerance = 1e-9; + Real stress_tolerance = 1e2; + if(s > max_steps) { + stress_tolerance = 1e4; + strain_tolerance = 1e-7; + } + for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quadrature_points; ++q) { types::Matrix & stress = *stress_it; types::Matrix & strain = *strain_it; for (UInt i = 0; i < dim; ++i) { for (UInt j = 0; j < dim; ++j) { - if(!(std::abs(strain(i, j) - presc_strain(i, j)) < 1e-9)) { + if(!(std::abs(strain(i, j) - presc_strain(i, j)) < strain_tolerance)) { std::cerr << "strain[" << i << "," << j << "] = " << strain(i, j) << " but should be = " << presc_strain(i, j) << " (-" << std::abs(strain(i, j) - presc_strain(i, j)) << ") [el : " << el<< " - q : " << q << "]" << std::endl; std::cerr << strain << presc_strain << std::endl; return EXIT_FAILURE; } - if(!(std::abs(stress(i, j) - presc_stress(i, j)) < 1e2)) { + if(!(std::abs(stress(i, j) - presc_stress(i, j)) < stress_tolerance)) { std::cerr << "stress[" << i << "," << j << "] = " << stress(i, j) << " but should be = " << presc_stress(i, j) << " (-" << std::abs(stress(i, j) - presc_stress(i, j)) << ") [el : " << el<< " - q : " << q << "]" << std::endl; std::cerr << stress << presc_stress << std::endl; return EXIT_FAILURE; } } } ++stress_it; ++strain_it; } } for (UInt n = 0; n < nb_nodes; ++n) { for (UInt i = 0; i < dim; ++i) { Real disp = alpha[i][0]; for (UInt j = 0; j < dim; ++j) { disp += alpha[i][j + 1] * coordinates(n, j); } if(!(std::abs(displacement(n,i) - disp) < 1e-7)) { std::cerr << "displacement(" << n << ", " << i <<")=" << displacement(n,i) << " should be equal to " << disp << "(" << displacement(n,i) - disp << ")" << std::endl; return EXIT_FAILURE; } } } finalize(); return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ /* iohelper::Dumper vars */ /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER template static iohelper::ElemType paraviewType(); template <> iohelper::ElemType paraviewType<_segment_2>() { return iohelper::LINE1; } template <> iohelper::ElemType paraviewType<_segment_3>() { return iohelper::LINE2; } template <> iohelper::ElemType paraviewType<_triangle_3>() { return iohelper::TRIANGLE1; } template <> iohelper::ElemType paraviewType<_triangle_6>() { return iohelper::TRIANGLE2; } template <> iohelper::ElemType paraviewType<_quadrangle_4>() { return iohelper::QUAD1; } template <> iohelper::ElemType paraviewType<_quadrangle_8>() { return iohelper::QUAD2; } template <> iohelper::ElemType paraviewType<_tetrahedron_4>() { return iohelper::TETRA1; } template <> iohelper::ElemType paraviewType<_tetrahedron_10>() { return iohelper::TETRA2; } template <> iohelper::ElemType paraviewType<_hexahedron_8>() { return iohelper::HEX1; } void paraviewInit(iohelper::Dumper & dumper, const SolidMechanicsModel & model) { UInt spatial_dimension = ElementClass::getSpatialDimension(); UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); UInt nb_element = model.getFEM().getMesh().getNbElement(TYPE); std::stringstream filename; filename << "out_" << TYPE; dumper.SetMode(iohelper::TEXT); dumper.SetPoints(model.getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, filename.str().c_str()); dumper.SetConnectivity((int *)model.getFEM().getMesh().getConnectivity(TYPE).values, paraviewType(), nb_element, iohelper::C_MODE); dumper.AddNodeDataField(model.getDisplacement().values, spatial_dimension, "displacements"); dumper.AddNodeDataField(model.getVelocity().values, spatial_dimension, "velocity"); dumper.AddNodeDataField(model.getResidual().values, spatial_dimension, "force"); dumper.AddNodeDataField(model.getMass().values, spatial_dimension, "mass"); dumper.AddNodeDataField(model.getForce().values, spatial_dimension, "applied_force"); dumper.AddElemDataField(model.getMaterial(0).getStrain(TYPE).values, spatial_dimension*spatial_dimension, "strain"); dumper.AddElemDataField(model.getMaterial(0).getStrain(TYPE).values, spatial_dimension*spatial_dimension, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); } /* -------------------------------------------------------------------------- */ void paraviewDump(iohelper::Dumper & dumper) { dumper.Dump(); } #endif diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/implicit/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/patch_tests/implicit/CMakeLists.txt index 34334a5d3..1bf4cbcc4 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/implicit/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/patch_tests/implicit/CMakeLists.txt @@ -1,37 +1,48 @@ #=============================================================================== # @file CMakeLists.txt # @author David Kammer # @date Wed Feb 16 09:46:59 2010 # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== + +macro(register_patch_test name type plane_strain) + register_test(patch_test_implicit_${name} patch_test_implicit.cc) + file(COPY ../data/${type}.msh DESTINATION .) + set_target_properties(patch_test_implicit_${name} + PROPERTIES COMPILE_DEFINITIONS "TYPE=_${type};PLANE_STRAIN=${plane_strain}") +endmacro() + foreach(_type ${LIST_TYPES}) - register_test(patch_tests_implicit_${_type} patch_test_implicit.cc) - set_target_properties(patch_tests_implicit_${_type} - PROPERTIES COMPILE_DEFINITIONS TYPE=_${_type}) - file(COPY ../data/${_type}.msh DESTINATION .) + register_patch_test(${_type} ${_type} true) +endforeach() + +foreach(_type ${LIST_TYPES_2D}) + register_patch_test(plane_strain_${_type} ${_type} true) + register_patch_test(plane_stress_${_type} ${_type} false) endforeach() #=============================================================================== -file(COPY ../data/material_check_stress.dat DESTINATION .) +file(COPY ../data/material_check_stress_plane_strain.dat DESTINATION .) +file(COPY ../data/material_check_stress_plane_stress.dat DESTINATION .) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) \ No newline at end of file +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) diff --git a/test/test_model/test_solid_mechanics_model/patch_tests/implicit/patch_test_implicit.cc b/test/test_model/test_solid_mechanics_model/patch_tests/implicit/patch_test_implicit.cc index 1455a8bd9..f6ff8855c 100644 --- a/test/test_model/test_solid_mechanics_model/patch_tests/implicit/patch_test_implicit.cc +++ b/test/test_model/test_solid_mechanics_model/patch_tests/implicit/patch_test_implicit.cc @@ -1,308 +1,312 @@ /** * @file test_check_stress.cc * @author David Kammer * @date Wed Feb 16 13:56:42 2011 * * @brief patch test for elastic material in solid mechanics model * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "element_class.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.hh" #endif //AKANTU_USE_IOHELPER using namespace akantu; Real alpha [3][4] = { { 0.01, 0.02, 0.03, 0.04 }, { 0.05, 0.06, 0.07, 0.08 }, { 0.09, 0.10, 0.11, 0.12 } }; /* -------------------------------------------------------------------------- */ -template +template static types::Matrix prescribed_strain() { UInt spatial_dimension = ElementClass::getSpatialDimension(); types::Matrix strain(spatial_dimension, spatial_dimension); for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < spatial_dimension; ++j) { strain(i, j) = alpha[i][j + 1]; } } return strain; } -template +template static types::Matrix prescribed_stress() { UInt spatial_dimension = ElementClass::getSpatialDimension(); types::Matrix stress(spatial_dimension, spatial_dimension); //plane strain in 2d types::Matrix strain(spatial_dimension, spatial_dimension); - types::Matrix pstrain; pstrain = prescribed_strain(); + types::Matrix pstrain; pstrain = prescribed_strain(); Real nu = 0.3; Real E = 2.1e11; Real trace = 0; /// symetric part of the strain tensor for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) strain(i,j) = 0.5 * (pstrain(i, j) + pstrain(j, i)); for (UInt i = 0; i < spatial_dimension; ++i) trace += strain(i,i); - Real Ep = E / (1 + nu); - for (UInt i = 0; i < spatial_dimension; ++i) - for (UInt j = 0; j < spatial_dimension; ++j) { - stress(i, j) = Ep * strain(i,j); - if(i == j) stress(i, j) += Ep * (nu / (1 - 2*nu)) * trace; - } + Real lambda = nu * E / ((1 + nu) * (1 - 2*nu)); + Real mu = E / (2 * (1 + nu)); + + if(!is_plane_strain) { + std::cout << "toto" << std::endl; + lambda = nu * E / (1 - nu*nu); + } + + if(spatial_dimension == 1) { + stress(0, 0) = E * strain(0, 0); + } else { + for (UInt i = 0; i < spatial_dimension; ++i) + for (UInt j = 0; j < spatial_dimension; ++j) { + stress(i, j) = (i == j)*lambda*trace + 2*mu*strain(i, j); + } + } return stress; } /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER static void paraviewInit(iohelper::Dumper & dumper, const SolidMechanicsModel & model); static void paraviewDump(iohelper::Dumper & dumper); #endif /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { initialize(argc, argv); UInt dim = ElementClass::getSpatialDimension(); const ElementType element_type = TYPE; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; std::stringstream filename; filename << TYPE << ".msh"; mesh_io.read(filename.str(), my_mesh); + MeshUtils::purifyMesh(my_mesh); + UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization - my_model.initVectors(); - // initialize the vectors - my_model.getForce().clear(); - my_model.getVelocity().clear(); - my_model.getAcceleration().clear(); - my_model.getDisplacement().clear(); - - my_model.initModel(); - my_model.readMaterials("material_check_stress.dat"); - my_model.initMaterials(); - - my_model.initImplicit(); + if(PLANE_STRAIN) + my_model.initFull("material_check_stress_plane_strain.dat", _static); + else + my_model.initFull("material_check_stress_plane_stress.dat", _static); const Vector & coordinates = my_mesh.getNodes(); Vector & displacement = my_model.getDisplacement(); Vector & boundary = my_model.getBoundary(); MeshUtils::buildFacets(my_mesh); MeshUtils::buildSurfaceID(my_mesh); CSR surface_nodes; MeshUtils::buildNodesPerSurface(my_mesh, surface_nodes); for (UInt s = 0; s < surface_nodes.getNbRows(); ++s) { CSR::iterator snode = surface_nodes.begin(s); for(; snode != surface_nodes.end(s); ++snode) { UInt n = *snode; std::cout << "Node " << n << std::endl; for (UInt i = 0; i < dim; ++i) { displacement(n, i) = alpha[i][0]; for (UInt j = 0; j < dim; ++j) { displacement(n, i) += alpha[i][j + 1] * coordinates(n, j); } boundary(n, i) = true; } } } /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ akantu::UInt count = 0; my_model.updateResidual(); #ifdef AKANTU_USE_IOHELPER iohelper::DumperParaview dumper; paraviewInit(dumper, my_model); #endif while(!my_model.testConvergenceResidual(2e-4) && (count < 100)) { std::cout << "Iter : " << ++count << std::endl; my_model.assembleStiffnessMatrix(); my_model.solveStatic(); my_model.updateResidual(); } #ifdef AKANTU_USE_IOHELPER paraviewDump(dumper); #endif if(count > 1) { std::cerr << "The code did not converge in 1 step !" << std::endl; return EXIT_FAILURE; } /* ------------------------------------------------------------------------ */ /* Checks */ /* ------------------------------------------------------------------------ */ UInt nb_quadrature_points = my_model.getFEM().getNbQuadraturePoints(element_type); Vector & stress_vect = const_cast &>(my_model.getMaterial(0).getStress(element_type)); Vector & strain_vect = const_cast &>(my_model.getMaterial(0).getStrain(element_type)); Vector::iterator stress_it = stress_vect.begin(dim, dim); Vector::iterator strain_it = strain_vect.begin(dim, dim); - types::Matrix presc_stress; presc_stress = prescribed_stress(); - types::Matrix presc_strain; presc_strain = prescribed_strain(); + types::Matrix presc_stress; presc_stress = prescribed_stress(); + types::Matrix presc_strain; presc_strain = prescribed_strain(); UInt nb_element = my_mesh.getNbElement(TYPE); for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quadrature_points; ++q) { types::Matrix & stress = *stress_it; types::Matrix & strain = *strain_it; for (UInt i = 0; i < dim; ++i) { for (UInt j = 0; j < dim; ++j) { - if(!(std::abs(strain(i, j) - presc_strain(i, j)) < 1e-15)) { + if(!(std::abs(strain(i, j) - presc_strain(i, j)) < 2e-15)) { std::cerr << "strain[" << i << "," << j << "] = " << strain(i, j) << " but should be = " << presc_strain(i, j) << " (-" << std::abs(strain(i, j) - presc_strain(i, j)) << ") [el : " << el<< " - q : " << q << "]" << std::endl; std::cerr << "computed : " << strain << "reference : " << presc_strain << std::endl; return EXIT_FAILURE; } if(!(std::abs(stress(i, j) - presc_stress(i, j)) < 1e-3)) { std::cerr << "stress[" << i << "," << j << "] = " << stress(i, j) << " but should be = " << presc_stress(i, j) << " (-" << std::abs(stress(i, j) - presc_stress(i, j)) << ") [el : " << el<< " - q : " << q << "]" << std::endl; std::cerr << "computed : " << stress << "reference : " << presc_stress << std::endl; return EXIT_FAILURE; } } } ++stress_it; ++strain_it; } } for (UInt n = 0; n < nb_nodes; ++n) { for (UInt i = 0; i < dim; ++i) { Real disp = alpha[i][0]; for (UInt j = 0; j < dim; ++j) { disp += alpha[i][j + 1] * coordinates(n, j); } - if(!(std::abs(displacement(n,i) - disp) < 1e-15)) { + if(!(std::abs(displacement(n,i) - disp) < 2e-15)) { std::cerr << "displacement(" << n << ", " << i <<")=" << displacement(n,i) << " should be equal to " << disp << std::endl; return EXIT_FAILURE; } } } // std::cout << "Strain : " << strain; // std::cout << "Stress : " << stress; // finalize(); return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ /* iohelper::Dumper vars */ /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER template static iohelper::ElemType paraviewType(); template <> iohelper::ElemType paraviewType<_segment_2>() { return iohelper::LINE1; } template <> iohelper::ElemType paraviewType<_segment_3>() { return iohelper::LINE2; } template <> iohelper::ElemType paraviewType<_triangle_3>() { return iohelper::TRIANGLE1; } template <> iohelper::ElemType paraviewType<_triangle_6>() { return iohelper::TRIANGLE2; } template <> iohelper::ElemType paraviewType<_quadrangle_4>() { return iohelper::QUAD1; } template <> iohelper::ElemType paraviewType<_quadrangle_8>() { return iohelper::QUAD2; } template <> iohelper::ElemType paraviewType<_tetrahedron_4>() { return iohelper::TETRA1; } template <> iohelper::ElemType paraviewType<_tetrahedron_10>() { return iohelper::TETRA2; } template <> iohelper::ElemType paraviewType<_hexahedron_8>() { return iohelper::HEX1; } void paraviewInit(iohelper::Dumper & dumper, const SolidMechanicsModel & model) { UInt spatial_dimension = ElementClass::getSpatialDimension(); UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); UInt nb_element = model.getFEM().getMesh().getNbElement(TYPE); std::stringstream filename; filename << "out_" << TYPE; dumper.SetMode(iohelper::TEXT); dumper.SetPoints(model.getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, filename.str().c_str()); dumper.SetConnectivity((int *)model.getFEM().getMesh().getConnectivity(TYPE).values, paraviewType(), nb_element, iohelper::C_MODE); dumper.AddNodeDataField(model.getDisplacement().values, spatial_dimension, "displacements"); dumper.AddNodeDataField(model.getVelocity().values, spatial_dimension, "velocity"); dumper.AddNodeDataField(model.getResidual().values, spatial_dimension, "force"); dumper.AddNodeDataField(model.getMass().values, spatial_dimension, "mass"); dumper.AddNodeDataField(model.getForce().values, spatial_dimension, "applied_force"); dumper.AddElemDataField(model.getMaterial(0).getStrain(TYPE).values, spatial_dimension*spatial_dimension, "strain"); dumper.AddElemDataField(model.getMaterial(0).getStrain(TYPE).values, spatial_dimension*spatial_dimension, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); } /* -------------------------------------------------------------------------- */ void paraviewDump(iohelper::Dumper & dumper) { dumper.Dump(); } #endif diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.sh b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.sh index f325948ee..31667f7a7 100755 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.sh +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.sh @@ -1,11 +1,11 @@ #!/bin/bash rm energy_bar_2d.csv ./test_solid_mechanics_model_bar_traction2d -ret = $? +ret=$? if [ $ret -eq 0 ] then ./test_cst_energy.pl energy_bar_2d.csv 1e-2 else return $ret fi \ No newline at end of file diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.sh b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.sh index 0499a30a3..7cec5fd0f 100755 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.sh +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.sh @@ -1,13 +1,13 @@ #!/bin/bash rm energy_bar_2d_para.csv mpirun -np 2 ./test_solid_mechanics_model_bar_traction2d_parallel - -if [ $? -eq 0 ] +ret=$? +if [ $ret -eq 0 ] then ./test_cst_energy.pl energy_bar_2d_para.csv 1e-2 else - return $? + return $ret fi diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured.sh b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured.sh index a91cb303f..91e957fc1 100755 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured.sh +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured.sh @@ -1,12 +1,12 @@ #!/bin/bash rm energy.csv ./test_solid_mechanics_model_bar_traction2d_structured - -if [ $? -eq 0 ] +ret=$? +if [ $ret -eq 0 ] then ./test_cst_energy.pl energy.csv 1e-3 else - return $? + return $ret fi diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured_pbc.sh b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured_pbc.sh index 1e51cc008..c9333f4eb 100755 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured_pbc.sh +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured_pbc.sh @@ -1,11 +1,11 @@ #!/bin/bash rm energy_2d_pbc.csv ./test_solid_mechanics_model_bar_traction2d_structured_pbc -ret = $? +ret=$? if [ $ret -eq 0 ] then ./test_cst_energy.pl energy_2d_pbc.csv 1e-4 else return $ret fi \ No newline at end of file