diff --git a/CMakeLists.txt b/CMakeLists.txt index 747f97119..3e35f2761 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,190 +1,186 @@ #=============================================================================== # @file CMakeLists.txt # # @author Nicolas Richart # # @date creation: Mon Jun 14 2010 # @date last modification: Mon Sep 15 2014 # # @brief main configuration file # # @section LICENSE # # Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION #------------------------------------------------------------------------------- # _ _ # | | | | # __ _| | ____ _ _ __ | |_ _ _ # / _` | |/ / _` | '_ \| __| | | | # | (_| | < (_| | | | | |_| |_| | # \__,_|_|\_\__,_|_| |_|\__|\__,_| # #=============================================================================== #=============================================================================== # CMake Project #=============================================================================== cmake_minimum_required(VERSION 2.8.12) # add this options before PROJECT keyword set(CMAKE_DISABLE_SOURCE_CHANGES ON) set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) project(Akantu) enable_language(CXX) #=============================================================================== # Misc. config for cmake #=============================================================================== set(AKANTU_CMAKE_DIR "${PROJECT_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/Modules") set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries.") mark_as_advanced(BUILD_SHARED_LIBS) if(NOT AKANTU_TARGETS_EXPORT) set(AKANTU_TARGETS_EXPORT AkantuLibraryDepends) endif() include(CMakeVersionGenerator) include(CMakePackagesSystem) include(CMakeFlagsHandling) include(AkantuPackagesSystem) include(AkantuMacros) #cmake_activate_debug_message() #=============================================================================== # Version Number #=============================================================================== # AKANTU version number. An even minor number corresponds to releases. set(AKANTU_MAJOR_VERSION 2) set(AKANTU_MINOR_VERSION 2) set(AKANTU_PATCH_VERSION 0) define_project_version() #=============================================================================== # Options #=============================================================================== # Debug set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -DAKANTU_NDEBUG" CACHE STRING "Flags used by the compiler during release builds" FORCE) add_flags(cxx "-Wall") #Profiling set(CMAKE_CXX_FLAGS_PROFILING "-g -pg -DNDEBUG -DAKANTU_NDEBUG -O2" CACHE STRING "Flags used by the compiler during profiling builds") set(CMAKE_C_FLAGS_PROFILING "-g -pg -DNDEBUG -DAKANTU_NDEBUG -O2" CACHE STRING "Flags used by the compiler during profiling builds") set(CMAKE_Fortran_FLAGS_PROFILING "-g -pg -DNDEBUG -DAKANTU_NDEBUG -O2" 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 CMAKE_C_FLAGS_PROFILING CMAKE_Fortran_FLAGS_PROFILING CMAKE_EXE_LINKER_FLAGS_PROFILING CMAKE_SHARED_LINKER_FLAGS_PROFILING ) include(CMakeDetermineCCompiler) #=============================================================================== # Dependencies #=============================================================================== -option(AKANTU_PYTHON_INTERFACE "Generates the Akantu Python module" OFF) -if(AKANTU_PYTHON_INTERFACE) - list(APPEND AKANTU_BOOST_COMPONENTS python) -endif() - declare_akantu_types() package_list_packages(${PROJECT_SOURCE_DIR}/packages EXTRA_PACKAGES_FOLDER ${PROJECT_SOURCE_DIR}/extra_packages) ## meta option \todo better way to do it when multiple package give enable the ## same feature 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() #=============================================================================== # Akantu library #=============================================================================== add_subdirectory(src) #=============================================================================== # Documentation #=============================================================================== if(AKANTU_DOCUMENTATION_DOXYGEN OR AKANTU_DOCUMENTATION_MANUAL) add_subdirectory(doc) else() set(AKANTU_DOC_EXCLUDE_FILES "${PROJECT_SOURCE_DIR}/doc/manual" CACHE INTERNAL "") endif() #=============================================================================== # Examples and tests #=============================================================================== option(AKANTU_EXAMPLES "Activate examples" OFF) option(AKANTU_TESTS "Activate tests" OFF) include(AkantuTestsMacros) include(AkantuExamplesMacros) if(AKANTU_EXAMPLES OR AKANTU_TESTS) option(AKANTU_BUILD_ALL_EXAMPLES "Build all examples") option(AKANTU_BUILD_ALL_TESTS "Build all tests") find_package(GMSH REQUIRED) endif() if(AKANTU_EXAMPLES) add_subdirectory(examples) endif() add_test_tree(test) #=============================================================================== # Install and Packaging #=============================================================================== include(AkantuInstall) if(NOT AKANTU_DISABLE_CPACK) include(AkantuCPack) endif() #=============================================================================== # Install and Packaging #=============================================================================== -if(AKANTU_PYTHON_INTERFACE) +package_is_activated(python_interface _python_act) +if(_python_act) add_subdirectory(python) # add_subdirectory(akantu4py) endif() diff --git a/cmake/AkantuCPack.cmake b/cmake/AkantuCPack.cmake index 26e420b05..952fbf0f2 100644 --- a/cmake/AkantuCPack.cmake +++ b/cmake/AkantuCPack.cmake @@ -1,88 +1,121 @@ #=============================================================================== # @file AkantuCPack.cmake # # @author Nicolas Richart # # @date creation: Wed Oct 17 2012 # @date last modification: Tue May 13 2014 # # @brief Configure the packaging system # # @section LICENSE # # Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # #=============================================================================== set(PACKAGE_FILE_NAME "akantu" CACHE STRING "Name of package to be generated") mark_as_advanced(PACKAGE_FILE_NAME) #set(CPACK_GENERATOR "DEB;TGZ;TBZ2;STGZ;RPM") -set(CPACK_GENERATOR "TGZ") +if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(CPACK_GENERATOR "TGZ") +else() + set(CPACK_GENERATOR "TGZ;NSIS") -# General configuration -set(CPACK_PACKAGE_VENDOR "LSMS") -set(CPACK_PACKAGE_FILE_NAME "${PACKAGE_FILE_NAME}-${AKANTU_VERSION}-${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") -set(CPACK_PACKAGE_VERSION "${AKANTU_VERSION}") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A multipurpose finite element library, Akantu") -set(CPACK_PACKAGE_NAME "akantu") + package_get_all_external_informations( + _external_include_dirs + _external_libraries + ) + set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS ${_external_libraries}) -# Debian config package -set(CPACK_DEBIAN_PACKAGE_MAINTAINER "nicolas.richart@epfl.ch, guillaume.anciaux@epfl.ch") -if(CMAKE_SYSTEM_PROCESSOR MATCHES "i.86" OR CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") + include(InstallRequiredSystemLibraries) +endif() + +if(CMAKE_SYSTEM_PROCESSOR MATCHES "i.86" OR CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "[aA][mM][dD]64") if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64" CACHE STRING "Architecture of debian package generation") + set(_arch "amd64") else() - set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386" CACHE STRING "Architecture of debian package generation") + set(_arch "i386") endif() elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc") - set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "powerpc" CACHE STRING "Architecture of debian package generation") + set(_arch "powerpc") else() - set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "unknown" CACHE STRING "Architecture of debian package generation") + set(_arch "unknown") +endif() + +if(WIN32 AND MINGW) + set(_arch "mingw32") endif() +# General configuration +set(CPACK_PACKAGE_VENDOR "LSMS") +set(CPACK_PACKAGE_FILE_NAME "${PACKAGE_FILE_NAME}-${AKANTU_VERSION}-${_arch}") +set(CPACK_PACKAGE_VERSION "${AKANTU_VERSION}") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A multipurpose finite element library, Akantu") +set(CPACK_PACKAGE_NAME "akantu") +#set(CMAKE_PACKAGE_ICON "${PROJECT_SOURCE_DIR}/cmake/akantu.ico") + +# Debian config package +set(CPACK_DEBIAN_PACKAGE_MAINTAINER "nicolas.richart@epfl.ch, guillaume.anciaux@epfl.ch") +set(CPACK_DEBIAN_PACKAGE_SECTION "Science") +set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${_arch}" CACHE STRING "Architecture of akantu's package") set(CPACK_DEBIAN_PACKAGE_DEPENDS "${${_project}_PACKAGE_SYSTEM_DEBIAN_PACKAGE_DEPENDS}") mark_as_advanced(CPACK_DEBIAN_PACKAGE_ARCHITECTURE) # RPM package configuration #set(CPACK_RPM_PACKAGE_REQUIRES "${${_project}_PACKAGE_SYSTEM_DEBIAN_PACKAGE_DEPENDS}") +# NSIS Windows installer +#set(CPACK_NSIS_MUI_ICON "${PROJECT_SOURCE_DIR}/cmake/akantu.ico") +#set(CPACK_NSIS_CONTACT "akantu@akantu.ch") +#set(CPACK_NSIS_MODIFY_PATH ON) -set(CPACK_COMPONENTS_ALL lib dev) +# Components description +set(CPACK_COMPONENTS_ALL lib dev bin python) set(CPACK_COMPONENT_LIB_DISPLAY_NAME "Libraries") +set(CPACK_COMPONENT_BIN_DISPLAY_NAME "Examples") +set(CPACK_COMPONENT_PYTHON_DISPLAY_NAME "Python interface") set(CPACK_COMPONENT_DEV_DISPLAY_NAME "C++ Headers") set(CPACK_COMPONENT_DEV_DEPENDS lib) +set(CPACK_COMPONENT_BIN_DEPENDS lib) +set(CPACK_COMPONENT_PYTHON_DEPENDS lib) set(CPACK_COMPONENT_LIB_DESCRIPTION "Akantu libraries") set(CPACK_COMPONENT_DEV_DESCRIPTION "Akantu C/C++ header files") -set(CPACK_COMPONENT_LIB_GROUP "Akantu Libraries") +set(CPACK_COMPONENT_LIB_GROUP "Akantu Libraries and Executables") +set(CPACK_COMPONENT_BIN_GROUP "Akantu Libraries and Executables") +set(CPACK_COMPONENT_PYTHON_GROUP "Akantu Libraries and Executables") set(CPACK_COMPONENT_DEV_GROUP "Development") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PACKAGE_FILE_NAME}-${AKANTU_VERSION}-src") set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/COPYING") string(TOUPPER ${PROJECT_NAME} _project) -list(APPEND CPACK_SOURCE_IGNORE_FILES ${AKANTU_EXCLUDE_SOURCE_FILES} ${AKANTU_TESTS_EXCLUDE_FILES} ${AKANTU_DOC_EXCLUDE_FILES}) -foreach(_pkg ${${_project}_PACKAGE_SYSTEM_PACKAGES_OFF}) - string(TOUPPER "${_pkg}" _pkg) - list(APPEND CPACK_SOURCE_IGNORE_FILES ${CMAKE_SOURCE_DIR}/packages/${${_project}_${_pkg}_FILE}) -endforeach() +unset(CPACK_SOURCE_IGNORE_FILES) +package_get_all_deactivated_packages(_deactivated_packages) +foreach(_pkg ${_deactivated_packages}}) + _package_get_filename(${_pkg} _file_name) + list(APPEND CPACK_SOURCE_IGNORE_FILES ${_file_name}) + _package_get_source_files(${_pkg} _srcs _pub_hdrs _priv_hdrs) + list(APPEND CPACK_SOURCE_IGNORE_FILES ${_srcs} ${_pub_hdrs} ${_priv_hdrs}) +endforeach() list(APPEND CPACK_SOURCE_IGNORE_FILES "/.*build.*/;/CVS/;/\\\\.svn/;/\\\\.bzr/;/\\\\.hg/;/\\\\.hgignore;/\\\\.git/;\\\\.swp$;\\\\.#;/#;~") include(CPack) diff --git a/cmake/AkantuConfig.cmake.in b/cmake/AkantuConfig.cmake.in index 08b71ee19..455433c99 100644 --- a/cmake/AkantuConfig.cmake.in +++ b/cmake/AkantuConfig.cmake.in @@ -1,65 +1,66 @@ #=============================================================================== # @file AkantuConfig.cmake.in # # @author Nicolas Richart # # @date Thu Dec 01 18:00:05 2011 # # @brief CMake file for the library # # @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 . # #=============================================================================== # Compute paths get_filename_component(AKANTU_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) set(AKANTU_USE_FILE "${AKANTU_CMAKE_DIR}/AkantuUse.cmake") include(${AKANTU_USE_FILE}) if(EXISTS "${AKANTU_CMAKE_DIR}/CMakeCache.txt") # In build tree include("${AKANTU_CMAKE_DIR}/AkantuBuildTreeSettings.cmake") - include("${AKANTU_CMAKE_DIR}/../cmake/AkantuExamplesMacros.cmake") -else() + include(AkantuExamplesMacros) + else() + # In install tree set(AKANTU_INCLUDE_DIR "${AKANTU_CMAKE_DIR}/../../include/akantu") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${AKANTU_CMAKE_DIR}/cmake") include(AkantuExamplesMacros) endif() include("${AKANTU_CMAKE_DIR}/AkantuLibraryDepends.cmake") # Dependencies include("${AKANTU_CMAKE_DIR}/AkantuConfigInclude.cmake") set(AKANTU_BUILD_TYPE @CMAKE_BUILD_TYPE@) # find_akantu_dependencies() set(AKANTU_LIBRARY akantu) if(AKANTU_HAS_CORE_CXX11) add_definitions(-std=c++0x) endif() list(APPEND AKANTU_LIBRARIES ${AKANTU_LIBRARY} ${AKANTU_EXTRA_LIBRARIES}) list(APPEND AKANTU_INCLUDE_DIR ${AKANTU_EXTRA_INCLUDE_DIR}) # set(AKANTU_VERSION @AKANTU_VERSION@) # @PACKAGE_INIT@ # set_and_check(AKANTU_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") # check_required_components(Akantu) diff --git a/cmake/Modules/CMakePackagesSystem.cmake b/cmake/Modules/CMakePackagesSystem.cmake index 6b306a20e..a5eef7072 100644 --- a/cmake/Modules/CMakePackagesSystem.cmake +++ b/cmake/Modules/CMakePackagesSystem.cmake @@ -1,840 +1,841 @@ #=============================================================================== # @file CMakePackagesSystem.cmake # # @author Nicolas Richart # @author Guillaume Anciaux # # @date creation: Thu Dec 20 2012 # @date last modification: Wed Sep 10 2014 # # @brief Set of macros used by akantu to handle the package system # # @section DESCRIPTION # # This package defines multiple function to handle packages. This packages can # be of two kinds regular ones and extra_packages (ex: in akantu the LGPL part # is regular packages and extra packages are on Propetary license) # # Package are loaded with the help of the command: # package_list_packages( # [ EXTRA_PACKAGE_FOLDER ] # [ SOURCE_FOLDER ] # [ TEST_FOLDER ] # [ MANUAL_FOLDER ] # ) # # This command will look for packages name like # /.cmake # OR //package.cmake # # A package is a cmake script that should contain at list the declaration of a # package # # package_declare( # [EXTERNAL] [META] [ADVANCED] [NOT_OPTIONAL] # [DESCRIPTION ] [DEFAULT ] # [DEPENDS ...] # [BOOST_COMPONENTS ...] # [EXTRA_PACKAGE_OPTIONS ...] # [COMPILE_FLAGS ] # [SYSTEM [ ]]) # # It can also declare multiple informations: # source files: # package_declare_sources( # ... ) # # a LaTeX documentation: # package_declare_documentation( # ...) # # LaTeX documentation files # package_declare_documentation_files( # ... ) # # Different function can also be retrieved from the package system by using the # different accessors # package_get_name( ) # package_get_real_name( ) # # package_get_option_name( ) # # package_use_system( ) # # package_get_nature( ) # # package_get_description( ) # # package_get_filename( ) # # package_get_sources_folder( ) # package_get_tests_folder( ) # package_get_manual_folder( ) # # package_get_find_package_extra_options( ) # # package_get_compile_flags( ) # # package_get_include_dir( ) # package_set_include_dir( ... ) # # package_get_libraries( ) # package_set_libraries( ... ) # # package_add_extra_dependency(pkg ... ) # package_rm_extra_dependency( ) # package_get_extra_dependencies( ) # # package_is_activated( ) # package_is_deactivated( ) # # package_get_dependencies( ) # package_add_dependencies( ... ) # # package_get_all_source_files( ) # package_get_all_include_directories() # package_get_all_external_informations( ) # package_get_all_definitions() # package_get_all_extra_dependencies() # package_get_all_test_folders() # package_get_all_documentation_files() # package_get_all_activated_packages() +# package_get_all_deactivated_packages() # package_get_all_packages() # # # @section LICENSE # # Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # #=============================================================================== include(CMakeParseArguments) #=============================================================================== # Package Management #=============================================================================== if(__CMAKE_PACKAGES_SYSTEM) return() endif() set(__CMAKE_PACKAGES_SYSTEM TRUE) if(CMAKE_VERSION VERSION_GREATER 3.1.2) cmake_policy(SET CMP0054 NEW) endif() #=============================================================================== option(AUTO_MOVE_UNKNOWN_FILES "Give to cmake the permission to move the unregistered files to the ${PROJECT_SOURCE_DIR}/tmp directory" FALSE) mark_as_advanced(AUTO_MOVE_UNKNOWN_FILES) include(CMakePackagesSystemGlobalFunctions) include(CMakePackagesSystemPrivateFunctions) # ============================================================================== # "Public" Accessors # ============================================================================== # ------------------------------------------------------------------------------ # Package name # ------------------------------------------------------------------------------ function(package_get_name pkg pkg_name) string(TOUPPER ${PROJECT_NAME} _project) string(REPLACE "-" "_" _str_pkg "${pkg}") string(TOUPPER ${_str_pkg} _u_package) set(${pkg_name} ${_project}_PKG_${_u_package} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Real name # ------------------------------------------------------------------------------ function(package_get_real_name pkg ret) package_get_name(${pkg} _pkg_name) _package_get_real_name(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Option name # ------------------------------------------------------------------------------ function(package_get_option_name pkg ret) package_get_name(${pkg} _pkg_name) _package_get_option_name(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Set if system package or compile external lib # ------------------------------------------------------------------------------ function(package_use_system pkg ret) package_get_name(${pkg} _pkg_name) _package_use_system(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() function(package_add_third_party_script_variable pkg var) package_get_name(${pkg} _pkg_name) _package_add_third_party_script_variable(${_pkg_name} ${var} ${ARGN}) set(${var} ${ARGN} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Set if system package or compile external lib # ------------------------------------------------------------------------------ function(package_add_to_export_list pkg) package_get_name(${pkg} _pkg_name) _package_add_to_export_list(${_pkg_name} ${ARGN}) endfunction() # ------------------------------------------------------------------------------ # Nature # ------------------------------------------------------------------------------ function(package_get_nature pkg ret) package_get_name(${pkg} _pkg_name) _package_get_nature(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Description # ------------------------------------------------------------------------------ function(package_get_description pkg ret) package_get_name(${pkg} _pkg_name) _package_get_description(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Package file name # ------------------------------------------------------------------------------ function(package_get_filename pkg ret) package_get_name(${pkg} _pkg_name) _package_get_filename(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Source files # ------------------------------------------------------------------------------ function(package_get_source_files pkg ret_srcs ret_pub ret_priv) package_get_name(${pkg} _pkg_name) _package_get_source_files(${_pkg_name} _tmp_srcs _tmp_pub _tmp_priv) set(${ret_srcs} ${_tmp_srcs} PARENT_SCOPE) set(${ret_pub} ${_tmp_pub} PARENT_SCOPE) set(${ret_priv} ${_tmp_pric} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Source folder # ------------------------------------------------------------------------------ function(package_get_sources_folder pkg ret) package_get_name(${pkg} _pkg_name) _package_get_sources_folder(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Test folder # ------------------------------------------------------------------------------ function(package_get_tests_folder pkg ret) package_get_name(${pkg} _pkg_name) _package_get_tests_folder(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Manual folder # ------------------------------------------------------------------------------ function(package_get_manual_folder pkg ret) package_get_name(${pkg} _pkg_name) _package_get_manual_folder(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Extra option for the find_package # ------------------------------------------------------------------------------ function(package_get_find_package_extra_options pkg ret) package_get_name(${pkg} _pkg_name) _package_get_find_package_extra_options(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() function(package_set_find_package_extra_options pkg) package_get_name(${pkg} _pkg_name) _package_set_find_package_extra_options(${_pkg_name} ${ARGN}) endfunction() # ------------------------------------------------------------------------------ # Compilation flags # ------------------------------------------------------------------------------ function(package_get_compile_flags pkg ret) package_get_name(${pkg} _pkg_name) _package_get_compile_flags(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Include dir # ------------------------------------------------------------------------------ function(package_get_include_dir pkg ret) package_get_name(${pkg} _pkg_name) _package_get_include_dir(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() function(package_set_include_dir pkg) package_get_name(${pkg} _pkg_name) _package_set_include_dir(${_pkg_name} ${ARGN}) endfunction() # ------------------------------------------------------------------------------ # Libraries # ------------------------------------------------------------------------------ function(package_get_libraries pkg ret) package_get_name(${pkg} _pkg_name) _package_get_libraries(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() function(package_set_libraries pkg) package_get_name(${pkg} _pkg_name) _package_set_libraries(${_pkg_name} ${ARGN}) endfunction() # ------------------------------------------------------------------------------ # Extra dependencies like custom commands of ExternalProject # ------------------------------------------------------------------------------ function(package_add_extra_dependency pkg) package_get_name(${pkg} _pkg_name) _package_add_extra_dependency(${_pkg_name} ${ARGN}) endfunction() function(package_rm_extra_dependency pkg dep) package_get_name(${pkg} _pkg_name) _package_rm_extra_dependency(${_pkg_name} ${dep}) endfunction() function(package_get_extra_dependencies pkg ret) package_get_name(${pkg} _pkg_name) _package_get_extra_dependencies(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Activate/deactivate # ------------------------------------------------------------------------------ function(package_is_activated pkg ret) package_get_name(${pkg} _pkg_name) _package_is_activated(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() function(package_is_deactivated pkg ret) package_get_name(${pkg} _pkg_name) _package_is_deactivated(${_pkg_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Direct dependencies # ------------------------------------------------------------------------------ function(package_get_dependencies pkg ret) package_get_name(${pkg} _pkg_name) _package_get_dependencies(${_pkg_name} _tmp_name) _package_get_real_name(${_tmp_name} _tmp) set(${ret} ${_tmp} PARENT_SCOPE) endfunction() function(package_add_dependencies pkg) package_get_name(${pkg} _pkg_name) foreach(_dep ${ARGN}) package_get_name(${_dep} _dep_pkg_name) list(APPEND _tmp_deps ${_dep_pkg_name}) endforeach() _package_add_dependencies(${_pkg_name} ${_tmp_deps}) endfunction() # ------------------------------------------------------------------------------ # Documentation related functions # ------------------------------------------------------------------------------ function(package_declare_documentation pkg) package_get_name(${pkg} _pkg_name) _package_set_documentation(${_pkg_name} ${ARGN}) endfunction() function(package_declare_documentation_files pkg) package_get_name(${pkg} _pkg_name) _package_set_documentation_files(${_pkg_name} ${ARGN}) endfunction() # ------------------------------------------------------------------------------ # Set any user variables needed # ------------------------------------------------------------------------------ function(package_set_variable variable pkg) package_get_name(${pkg} _pkg_name) _package_set_variable(${variable} ${_pkg_name} ${ARGN}) endfunction() macro(package_get_variable variable pkg value) package_get_name(${pkg} _pkg_name) _package_get_variable(${variable} ${_pkg_name} _value_tmp) set(${value} ${_value_tmp} PARENT_SCOPE) endmacro() # ============================================================================== # Global accessors # ============================================================================== # ------------------------------------------------------------------------------ # get the list of source files # ------------------------------------------------------------------------------ function(package_get_all_source_files SRCS PUBLIC_HEADERS PRIVATE_HEADERS) string(TOUPPER ${PROJECT_NAME} _project) - set(tmp_SRCS) - set(tmp_PUBLIC_HEADERS) - set(tmp_PRIVATE_HEADERS) + unset(_tmp_srcs) + unset(_tmp_public_headers) + unset(_tmp_private_headers) package_get_all_activated_packages(_activated_list) foreach(_pkg_name ${_activated_list}) _package_get_source_files(${_pkg_name} - _tmp_SRCS - _tmp_PUBLIC_HEADERS - _tmp_PRIVATE_HEADERS + _pkg_srcs + _pkg_public_headers + _pkg_private_headers ) - list(APPEND tmp_SRCS ${_tmp_SRCS}) - list(APPEND tmp_PUBLIC_HEADERS ${tmp_PUBLIC_HEADERS}) - list(APPEND tmp_PRIVATE_HEADERS ${tmp_PRIVATE_HEADERS}) + list(APPEND _tmp_srcs ${_pkg_srcs}) + list(APPEND _tmp_public_headers ${_pkg_public_headers}) + list(APPEND _tmp_private_headers ${_pkg_private_headers}) endforeach() - set(${SRCS} ${tmp_SRCS} PARENT_SCOPE) - set(${PUBLIC_HEADERS} ${tmp_PUBLIC_HEADERS} PARENT_SCOPE) - set(${PRIVATE_HEADERS} ${tmp_PRIVATE_HEADERS} PARENT_SCOPE) + set(${SRCS} ${_tmp_srcs} PARENT_SCOPE) + set(${PUBLIC_HEADERS} ${_tmp_public_headers} PARENT_SCOPE) + set(${PRIVATE_HEADERS} ${_tmp_private_headers} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get include directories # ------------------------------------------------------------------------------ function(package_get_all_include_directories inc_dirs) set(_tmp) package_get_all_activated_packages(_activated_list) foreach(_pkg_name ${_activated_list}) foreach(_type SRCS PUBLIC_HEADERS PRIVATE_HEADERS) foreach(_file ${${_pkg_name}_${_type}}) get_filename_component(_path "${_file}" PATH) list(APPEND _tmp "${_path}") endforeach() endforeach() endforeach() if(_tmp) list(REMOVE_DUPLICATES _tmp) endif() set(${inc_dirs} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get external libraries informations # ------------------------------------------------------------------------------ function(package_get_all_external_informations INCLUDE_DIR LIBRARIES) _package_get_variable_for_activated(INCLUDE_DIR tmp_INCLUDE_DIR) _package_get_variable_for_activated(LIBRARIES tmp_LIBRARIES) set(${INCLUDE_DIR} ${tmp_INCLUDE_DIR} PARENT_SCOPE) set(${LIBRARIES} ${tmp_LIBRARIES} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get export list for all activated packages # ------------------------------------------------------------------------------ function(package_get_all_export_list export_list) _package_get_variable_for_activated(EXPORT_LIST _tmp) set(${export_list} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get definitions like external projects # ------------------------------------------------------------------------------ function(package_get_all_definitions definitions) _package_get_variable_for_activated(OPTION_NAME _tmp) set(${definitions} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get extra dependencies like external projects # ------------------------------------------------------------------------------ function(package_get_all_extra_dependencies deps) _package_get_variable_for_activated(EXTRA_DEPENDENCY _tmp) set(${deps} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get extra infos # ------------------------------------------------------------------------------ function(package_get_all_test_folders TEST_DIRS) _package_get_variable_for_activated(TEST_FOLDER _tmp) set(${TEST_DIRS} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Documentation informations # ------------------------------------------------------------------------------ function(package_get_all_documentation_files doc_files) set(_tmp_DOC_FILES) package_get_all_activated_packages(_activated_list) foreach(_pkg_name ${_activated_list}) _package_get_manual_folder(${_pkg_name} _doc_dir) _package_get_documentation_files(${_pkg_name} _doc_files) foreach(_doc_file ${_doc_files}) list(APPEND _tmp_DOC_FILES ${_doc_dir}/${_doc_file}) endforeach() endforeach() if(_tmp_DOC_FILES) list(REMOVE_DUPLICATES _tmp_DOC_FILES) endif() set(${doc_files} ${_tmp_DOC_FILES} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # List packages # ------------------------------------------------------------------------------ function(package_get_all_activated_packages activated_list) package_get_project_variable(ACTIVATED_PACKAGE_LIST _activated_list) set(${activated_list} ${_activated_list} PARENT_SCOPE) endfunction() function(package_get_all_deactivated_packages deactivated_list) package_get_project_variable(DEACTIVATED_PACKAGE_LIST _deactivated_list) set(${deactivated_list} ${_deactivated_list} PARENT_SCOPE) endfunction() function(package_get_all_packages packages_list) package_get_project_variable(ALL_PACKAGES_LIST _packages_list) set(${packages_list} ${_packages_list} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Callbacks # ------------------------------------------------------------------------------ function(package_on_enabled_script pkg script) package_get_name(${pkg} _pkg_name) string(TOLOWER "${_pkg_name}" _l_pkg_name) set(_output_file "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_l_pkg_name}.cmake") file(WRITE "${_output_file}" "${script}") endfunction() # ------------------------------------------------------------------------------ # list all the packages in the PACKAGE_FOLDER # extra packages can be given with an EXTRA_PACKAGE_FOLDER # /.cmake # # Extra packages folder structure # //package.cmake # /src # /test # /manual # # ------------------------------------------------------------------------------ function(package_list_packages PACKAGE_FOLDER) cmake_parse_arguments(_opt_pkg "" "SOURCE_FOLDER;EXTRA_PACKAGES_FOLDER;TEST_FOLDER;MANUAL_FOLDER" "" ${ARGN}) string(TOUPPER ${PROJECT_NAME} _project) # Cleaning some states to start correctly package_get_all_packages(_already_loaded_pkg) foreach(_pkg_name ${_already_loaded_pkg}) _package_unset_extra_dependencies(${_pkg_name}) _package_unset_dependencies(${_pkg_name}) _package_unset_activated(${_pkg_name}) endforeach() if(_opt_pkg_SOURCE_FOLDER) set(_src_folder "${_opt_pkg_SOURCE_FOLDER}") else() set(_src_folder "src/") endif() get_filename_component(_abs_src_folder ${_src_folder} ABSOLUTE) if(_opt_pkg_TEST_FOLDER) set(_test_folder "${_opt_pkg_TEST_FOLDER}") else() set(_test_folder "test/") endif() if(_opt_pkg_MANUAL_FOLDER) set(_manual_folder "${_opt_pkg_MANUAL_FOLDER}") else() set(_manual_folder "doc/manual") endif() get_filename_component(_abs_test_folder ${_test_folder} ABSOLUTE) get_filename_component(_abs_manual_folder ${_manual_folder} ABSOLUTE) # check all the packages in the file(GLOB _package_list "${PACKAGE_FOLDER}/*.cmake") set(_package_files) foreach(_pkg ${_package_list}) get_filename_component(_basename ${_pkg} NAME) if(NOT _basename MATCHES "^\\.#.*") list(APPEND _package_files ${_basename}) endif() endforeach() if(_package_files) list(SORT _package_files) endif() # check all packages set(_packages_list_all) foreach(_pkg_file ${_package_files}) string(REGEX REPLACE "[0-9]+_" "" _pkg_file_stripped ${_pkg_file}) string(REGEX REPLACE "\\.cmake" "" _pkg ${_pkg_file_stripped}) package_get_name(${_pkg} _pkg_name) _package_set_filename(${_pkg_name} "${PACKAGE_FOLDER}/${_pkg_file}") _package_set_sources_folder(${_pkg_name} "${_abs_src_folder}") _package_set_tests_folder(${_pkg_name} "${_abs_test_folder}") _package_set_manual_folder(${_pkg_name} "${_abs_manual_folder}") list(APPEND _packages_list_all ${_pkg_name}) include("${PACKAGE_FOLDER}/${_pkg_file}") endforeach() # check the extra_packages if they exists if(_opt_pkg_EXTRA_PACKAGES_FOLDER) file(GLOB _extra_package_list RELATIVE "${_opt_pkg_EXTRA_PACKAGES_FOLDER}" "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/*") foreach(_pkg ${_extra_package_list}) if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake") package_get_name(${_pkg} _pkg_name) _package_set_filename(${_pkg_name} "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake") _package_set_sources_folder(${_pkg_name} "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/src") if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/test") _package_set_tests_folder(${_pkg_name} "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/test") endif() if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/manual") _package_set_manual_folder(${_pkg_name} "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/manual") endif() list(APPEND _extra_pkg_src_folders "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/src") list(APPEND _packages_list_all ${_pkg_name}) include("${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake") endif() endforeach() endif() # Store the list of packages string(TOUPPER ${PROJECT_NAME} _project) set(${_project}_ALL_PACKAGES_LIST ${_packages_list_all} CACHE INTERNAL "List of available packages" FORCE) _package_build_rdependencies() _package_load_packages() _package_check_files_exists() _package_check_files_registered(${_abs_src_folder} ${_extra_pkg_src_folders}) # Load boost components if boost was loaded package_is_activated(Boost _ret) if(_ret) _package_load_boost_components() endif() endfunction() # ------------------------------------------------------------------------------ # macro to include internal/external packages packages # package_declare( # [EXTERNAL] [META] [ADVANCED] [NOT_OPTIONAL] # [DESCRIPTION ] [DEFAULT ] # [DEPENDS ...] # [BOOST_COMPONENTS ...] # [EXTRA_PACKAGE_OPTIONS ...] # [COMPILE_FLAGS ] # [SYSTEM [ ]]) # ------------------------------------------------------------------------------ function(package_declare pkg) package_get_name(${pkg} _pkg_name) _package_set_real_name(${_pkg_name} ${pkg}) cmake_parse_arguments(_opt_pkg "EXTERNAL;NOT_OPTIONAL;META;ADVANCED" "DEFAULT;DESCRIPTION" "DEPENDS;EXTRA_PACKAGE_OPTIONS;COMPILE_FLAGS;BOOST_COMPONENTS;SYSTEM" ${ARGN}) if(_opt_pkg_UNPARSED_ARGUMENTS) message("You gave to many arguments while registering the package ${pkg} \"${_opt_pkg_UNPARSED_ARGUMENTS}\"") endif() # set the nature if(_opt_pkg_EXTERNAL) _package_set_nature(${_pkg_name} "external") elseif(_opt_pkg_META) _package_set_nature(${_pkg_name} "meta") else() _package_set_nature(${_pkg_name} "internal") endif() _package_declare_option(${_pkg_name}) # set description if(_opt_pkg_DESCRIPTION) _package_set_description(${_pkg_name} ${_opt_pkg_DESCRIPTION}) else() _package_set_description(${_pkg_name} "") endif() _package_get_option_name(${_pkg_name} _option_name) _package_get_description(${_pkg_name} _description) # get the default value if(DEFINED _opt_pkg_DEFAULT) set(_default ${_opt_pkg_DEFAULT}) else() if(_opt_pkg_NOT_OPTIONAL) set(_default ON) else() set(_default OFF) endif() endif() # set the option if needed if(_opt_pkg_NOT_OPTIONAL) _package_get_nature(${_pkg_name} _nature) _package_set_nature(${_pkg_name} "${_nature}_not_optional") set(${_option_name} ${_default} CACHE INTERNAL "${_description}" FORCE) else() option(${_option_name} "${_description}" ${_default}) if(_opt_pkg_ADVANCED OR _opt_pkg_EXTERNAL) mark_as_advanced(${_option_name}) endif() endif() # Set the option for third-partie that can be compiled as an ExternalProject if(DEFINED _opt_pkg_SYSTEM) list(LENGTH _opt_pkg_SYSTEM _length) list(GET _opt_pkg_SYSTEM 0 _bool) _package_set_system_option(${_pkg_name} ${_bool}) if(_length GREATER 1) list(GET _opt_pkg_SYSTEM 1 _script) _package_set_system_script(${_pkg_name} ${_script}) endif() endif() # set the dependecies if(_opt_pkg_DEPENDS) set(_depends) foreach(_dep ${_opt_pkg_DEPENDS}) package_get_name(${_dep} _dep_pkg_name) list(APPEND _depends ${_dep_pkg_name}) endforeach() _package_add_dependencies(${_pkg_name} ${_depends}) endif() # keep the extra option for the future find package if(_opt_pkg_EXTRA_PACKAGE_OPTIONS) _package_set_find_package_extra_options(${_pkg_name} "${_opt_pkg_EXTRA_PACKAGE_OPTIONS}") endif() # register the compilation flags if(_opt_pkg_COMPILE_FLAGS) _package_set_compile_flags(${_pkg_name} "${_opt_pkg_COMPILE_FLAGS}") endif() # set the boost dependencies if(_opt_pkg_BOOST_COMPONENTS) _package_set_boost_component_needed(${_pkg_name} "${_opt_pkg_BOOST_COMPONENTS}") endif() endfunction() # ------------------------------------------------------------------------------ # declare the source files of a given package # # package_declare_sources( # SOURCES ... # PUBLIC_HEADER
... # PRIVATE_HEADER
...) # ------------------------------------------------------------------------------ function(package_declare_sources pkg) package_get_name(${pkg} _pkg_name) # get 3 lists, if none of the options given try to distinguish the different lists cmake_parse_arguments(_opt_pkg "" "" "SOURCES;PUBLIC_HEADERS;PRIVATE_HEADERS" ${ARGN}) set(_tmp_srcs ${_opt_pkg_SOURCES}) set(_tmp_pub_hdrs ${_opt_pkg_PUBLIC_HEADER}) set(_tmp_pri_hdrs ${_opt_pkg_PRIVATE_HEADERS}) foreach(_file ${_opt_pkg_UNPARSED_ARGUMENTS}) if(${_file} MATCHES ".*inline.*\\.cc") list(APPEND _tmp_pub_hdrs ${_file}) elseif(${_file} MATCHES ".*\\.h+") list(APPEND _tmp_pub_hdrs ${_file}) else() list(APPEND _tmp_srcs ${_file}) endif() endforeach() _package_get_sources_folder(${_pkg_name} _src_folder) foreach(_type _srcs _pub_hdrs _pri_hdrs) set(${_type}) foreach(_file ${_tmp${_type}}) # get the full name list(APPEND ${_type} "${_src_folder}/${_file}") endforeach() endforeach() set(${_pkg_name}_SRCS "${_srcs}" CACHE INTERNAL "List of sources files" FORCE) set(${_pkg_name}_PUBLIC_HEADERS "${_pub_hdrs}" CACHE INTERNAL "List of public header files" FORCE) set(${_pkg_name}_PRIVATE_HEADERS "${_pri_hdrs}" CACHE INTERNAL "List of private header files" FORCE) endfunction() diff --git a/extra_packages/igfem b/extra_packages/igfem index dac505891..da70af36a 160000 --- a/extra_packages/igfem +++ b/extra_packages/igfem @@ -1 +1 @@ -Subproject commit dac505891dae7b6a6734153dabc9797cce24daf0 +Subproject commit da70af36a7facda89a77c36930c52da746eaa7af diff --git a/packages/core.cmake b/packages/core.cmake index 14faac512..09a4e3c11 100644 --- a/packages/core.cmake +++ b/packages/core.cmake @@ -1,484 +1,483 @@ #=============================================================================== # @file 00_core.cmake # # @author Guillaume Anciaux # @author Nicolas Richart # # @date creation: Mon Nov 21 2011 # @date last modification: Fri Sep 19 2014 # # @brief package description for core # # @section LICENSE # # Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # #=============================================================================== package_declare(core NOT_OPTIONAL DESCRIPTION "core package for Akantu") package_declare_sources(core common/aka_array.cc common/aka_array.hh common/aka_array_tmpl.hh common/aka_blas_lapack.hh common/aka_circular_array.hh common/aka_circular_array_inline_impl.cc common/aka_common.cc common/aka_common.hh common/aka_common_inline_impl.cc common/aka_csr.hh common/aka_element_classes_info_inline_impl.cc common/aka_error.cc common/aka_error.hh common/aka_event_handler_manager.hh common/aka_extern.cc common/aka_fwd.hh common/aka_grid_dynamic.hh common/aka_math.cc common/aka_math.hh common/aka_math_tmpl.hh common/aka_memory.cc common/aka_memory.hh common/aka_memory_inline_impl.cc common/aka_random_generator.hh common/aka_safe_enum.hh common/aka_static_memory.cc common/aka_static_memory.hh common/aka_static_memory_inline_impl.cc common/aka_static_memory_tmpl.hh common/aka_typelist.hh common/aka_types.hh common/aka_visitor.hh common/aka_voigthelper.hh common/aka_voigthelper.cc fe_engine/element_class.cc fe_engine/element_class.hh fe_engine/element_class_tmpl.hh fe_engine/element_classes/element_class_hexahedron_8_inline_impl.cc fe_engine/element_classes/element_class_hexahedron_20_inline_impl.cc fe_engine/element_classes/element_class_pentahedron_6_inline_impl.cc fe_engine/element_classes/element_class_pentahedron_15_inline_impl.cc fe_engine/element_classes/element_class_point_1_inline_impl.cc fe_engine/element_classes/element_class_quadrangle_4_inline_impl.cc fe_engine/element_classes/element_class_quadrangle_8_inline_impl.cc fe_engine/element_classes/element_class_segment_2_inline_impl.cc fe_engine/element_classes/element_class_segment_3_inline_impl.cc fe_engine/element_classes/element_class_tetrahedron_10_inline_impl.cc fe_engine/element_classes/element_class_tetrahedron_4_inline_impl.cc fe_engine/element_classes/element_class_triangle_3_inline_impl.cc fe_engine/element_classes/element_class_triangle_6_inline_impl.cc fe_engine/fe_engine.cc fe_engine/fe_engine.hh fe_engine/fe_engine_inline_impl.cc fe_engine/fe_engine_template.hh fe_engine/fe_engine_template_tmpl.hh fe_engine/geometrical_element.cc fe_engine/integration_element.cc fe_engine/integrator.hh fe_engine/integrator_gauss.hh fe_engine/integrator_gauss_inline_impl.cc fe_engine/interpolation_element.cc fe_engine/interpolation_element_tmpl.hh fe_engine/integration_point.hh fe_engine/shape_functions.hh fe_engine/shape_functions_inline_impl.cc fe_engine/shape_lagrange.cc fe_engine/shape_lagrange.hh fe_engine/shape_lagrange_inline_impl.cc fe_engine/shape_linked.cc fe_engine/shape_linked.hh fe_engine/shape_linked_inline_impl.cc fe_engine/element.hh io/dumper/dumpable.hh io/dumper/dumpable.cc io/dumper/dumpable_dummy.hh io/dumper/dumpable_inline_impl.hh io/dumper/dumper_field.hh io/dumper/dumper_material_padders.hh io/dumper/dumper_filtered_connectivity.hh io/dumper/dumper_element_partition.hh io/mesh_io.cc io/mesh_io.hh io/mesh_io/mesh_io_abaqus.cc io/mesh_io/mesh_io_abaqus.hh io/mesh_io/mesh_io_diana.cc io/mesh_io/mesh_io_diana.hh io/mesh_io/mesh_io_msh.cc io/mesh_io/mesh_io_msh.hh io/model_io.cc io/model_io.hh io/parser/algebraic_parser.hh io/parser/input_file_parser.hh io/parser/parsable.cc io/parser/parsable.hh io/parser/parsable_tmpl.hh io/parser/parser.cc io/parser/parser_real.cc io/parser/parser_random.cc io/parser/parser_types.cc io/parser/parser_input_files.cc io/parser/parser.hh io/parser/parser_tmpl.hh io/parser/parser_grammar_tmpl.hh io/parser/cppargparse/cppargparse.hh io/parser/cppargparse/cppargparse.cc io/parser/cppargparse/cppargparse_tmpl.hh mesh/element_group.cc mesh/element_group.hh mesh/element_group_inline_impl.cc mesh/element_type_map.hh mesh/element_type_map_tmpl.hh mesh/element_type_map_filter.hh mesh/group_manager.cc mesh/group_manager.hh mesh/group_manager_inline_impl.cc mesh/mesh.cc mesh/mesh.hh mesh/mesh_accessor.hh mesh/mesh_events.hh mesh/mesh_filter.hh mesh/mesh_data.cc mesh/mesh_data.hh mesh/mesh_data_tmpl.hh mesh/mesh_inline_impl.cc mesh/node_group.cc mesh/node_group.hh mesh/node_group_inline_impl.cc mesh_utils/mesh_partition.cc mesh_utils/mesh_partition.hh mesh_utils/mesh_partition/mesh_partition_mesh_data.cc mesh_utils/mesh_partition/mesh_partition_mesh_data.hh mesh_utils/mesh_partition/mesh_partition_scotch.hh mesh_utils/mesh_utils_pbc.cc mesh_utils/mesh_utils.cc mesh_utils/mesh_utils.hh mesh_utils/mesh_utils_inline_impl.cc mesh_utils/global_ids_updater.hh mesh_utils/global_ids_updater.cc mesh_utils/global_ids_updater_inline_impl.cc model/boundary_condition.hh model/boundary_condition_functor.hh model/boundary_condition_functor_inline_impl.cc model/boundary_condition_tmpl.hh - model/boundary_condition_python_functor.hh - model/boundary_condition_python_functor.cc model/integration_scheme/generalized_trapezoidal.hh model/integration_scheme/generalized_trapezoidal_inline_impl.cc model/integration_scheme/integration_scheme_1st_order.hh model/integration_scheme/integration_scheme_2nd_order.hh model/integration_scheme/newmark-beta.hh model/integration_scheme/newmark-beta_inline_impl.cc model/model.cc model/model.hh model/model_inline_impl.cc model/solid_mechanics/material.cc model/solid_mechanics/material.hh model/solid_mechanics/material_inline_impl.cc model/solid_mechanics/material_selector.hh model/solid_mechanics/material_selector_tmpl.hh model/solid_mechanics/materials/internal_field.hh model/solid_mechanics/materials/internal_field_tmpl.hh model/solid_mechanics/materials/random_internal_field.hh model/solid_mechanics/materials/random_internal_field_tmpl.hh model/solid_mechanics/solid_mechanics_model.cc model/solid_mechanics/solid_mechanics_model.hh model/solid_mechanics/solid_mechanics_model_inline_impl.cc model/solid_mechanics/solid_mechanics_model_mass.cc model/solid_mechanics/solid_mechanics_model_material.cc model/solid_mechanics/solid_mechanics_model_tmpl.hh model/solid_mechanics/solid_mechanics_model_event_handler.hh model/solid_mechanics/materials/plane_stress_toolbox.hh model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh model/solid_mechanics/materials/material_core_includes.hh model/solid_mechanics/materials/material_elastic.cc model/solid_mechanics/materials/material_elastic.hh model/solid_mechanics/materials/material_elastic_inline_impl.cc model/solid_mechanics/materials/material_thermal.cc model/solid_mechanics/materials/material_thermal.hh model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh model/solid_mechanics/materials/material_elastic_orthotropic.cc model/solid_mechanics/materials/material_elastic_orthotropic.hh model/solid_mechanics/materials/material_damage/material_damage.hh model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh model/solid_mechanics/materials/material_damage/material_marigo.cc model/solid_mechanics/materials/material_damage/material_marigo.hh model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.cc model/solid_mechanics/materials/material_damage/material_mazars.cc model/solid_mechanics/materials/material_damage/material_mazars.hh model/solid_mechanics/materials/material_damage/material_mazars_inline_impl.cc model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh model/solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.cc model/solid_mechanics/materials/material_plastic/material_plastic.cc model/solid_mechanics/materials/material_plastic/material_plastic.hh model/solid_mechanics/materials/material_plastic/material_plastic_inline_impl.cc model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.cc model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh model/common/neighborhood_base.hh model/common/neighborhood_base.cc model/common/neighborhood_base_inline_impl.cc model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.hh model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc model/common/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.cc solver/solver.cc solver/solver.hh solver/solver_inline_impl.cc solver/sparse_matrix.cc solver/sparse_matrix.hh solver/sparse_matrix_inline_impl.cc solver/static_solver.hh solver/static_solver.cc synchronizer/communication_buffer.hh synchronizer/communication_buffer_inline_impl.cc synchronizer/data_accessor.cc synchronizer/data_accessor.hh synchronizer/data_accessor_inline_impl.cc synchronizer/distributed_synchronizer.cc synchronizer/distributed_synchronizer.hh synchronizer/distributed_synchronizer_tmpl.hh synchronizer/dof_synchronizer.cc synchronizer/dof_synchronizer.hh synchronizer/dof_synchronizer_inline_impl.cc synchronizer/filtered_synchronizer.cc synchronizer/filtered_synchronizer.hh synchronizer/pbc_synchronizer.cc synchronizer/pbc_synchronizer.hh synchronizer/real_static_communicator.hh synchronizer/static_communicator.cc synchronizer/static_communicator.hh synchronizer/static_communicator_dummy.hh synchronizer/static_communicator_inline_impl.hh synchronizer/synchronizer.cc synchronizer/synchronizer.hh synchronizer/synchronizer_registry.cc synchronizer/synchronizer_registry.hh synchronizer/grid_synchronizer.cc synchronizer/grid_synchronizer.hh ) package_declare_elements(core ELEMENT_TYPES _point_1 _segment_2 _segment_3 _triangle_3 _triangle_6 _quadrangle_4 _quadrangle_8 _tetrahedron_4 _tetrahedron_10 _pentahedron_6 _pentahedron_15 _hexahedron_8 _hexahedron_20 KIND regular GEOMETRICAL_TYPES _gt_point _gt_segment_2 _gt_segment_3 _gt_triangle_3 _gt_triangle_6 _gt_quadrangle_4 _gt_quadrangle_8 _gt_tetrahedron_4 _gt_tetrahedron_10 _gt_hexahedron_8 _gt_hexahedron_20 _gt_pentahedron_6 _gt_pentahedron_15 INTERPOLATION_TYPES _itp_lagrange_point_1 _itp_lagrange_segment_2 _itp_lagrange_segment_3 _itp_lagrange_triangle_3 _itp_lagrange_triangle_6 _itp_lagrange_quadrangle_4 _itp_serendip_quadrangle_8 _itp_lagrange_tetrahedron_4 _itp_lagrange_tetrahedron_10 _itp_lagrange_hexahedron_8 _itp_serendip_hexahedron_20 _itp_lagrange_pentahedron_6 _itp_lagrange_pentahedron_15 GEOMETRICAL_SHAPES _gst_point _gst_triangle _gst_square _gst_prism GAUSS_INTEGRATION_TYPES _git_point _git_segment _git_triangle _git_tetrahedron _git_pentahedron INTERPOLATION_KIND _itk_lagrangian FE_ENGINE_LISTS gradient_on_integration_points interpolate_on_integration_points interpolate compute_normals_on_integration_points inverse_map contains compute_shapes compute_shapes_derivatives get_shapes_derivatives ) package_declare_material_infos(core LIST AKANTU_CORE_MATERIAL_LIST INCLUDE material_core_includes.hh ) package_declare_documentation_files(core manual.sty manual.cls manual.tex manual-macros.sty manual-titlepages.tex manual-introduction.tex manual-gettingstarted.tex manual-io.tex manual-solidmechanicsmodel.tex manual-constitutive-laws.tex manual-lumping.tex manual-elements.tex manual-appendix-elements.tex manual-appendix-materials.tex manual-appendix-packages.tex manual-backmatter.tex manual-bibliography.bib manual-bibliographystyle.bst figures/bc_and_ic_example.pdf figures/boundary.pdf figures/boundary.svg figures/dirichlet.pdf figures/dirichlet.svg figures/doc_wheel.pdf figures/doc_wheel.svg figures/dynamic_analysis.png figures/explicit_dynamic.pdf figures/explicit_dynamic.svg figures/static.pdf figures/static.svg figures/hooke_law.pdf figures/hot-point-1.png figures/hot-point-2.png figures/implicit_dynamic.pdf figures/implicit_dynamic.svg figures/insertion.pdf figures/interpolate.pdf figures/interpolate.svg figures/problemDomain.pdf_tex figures/problemDomain.pdf figures/static_analysis.png figures/stress_strain_el.pdf figures/tangent.pdf figures/tangent.svg figures/vectors.pdf figures/vectors.svg figures/stress_strain_neo.pdf figures/visco_elastic_law.pdf figures/isotropic_hardening_plasticity.pdf figures/stress_strain_visco.pdf figures/elements/hexahedron_8.pdf figures/elements/hexahedron_8.svg figures/elements/quadrangle_4.pdf figures/elements/quadrangle_4.svg figures/elements/quadrangle_8.pdf figures/elements/quadrangle_8.svg figures/elements/segment_2.pdf figures/elements/segment_2.svg figures/elements/segment_3.pdf figures/elements/segment_3.svg figures/elements/tetrahedron_10.pdf figures/elements/tetrahedron_10.svg figures/elements/tetrahedron_4.pdf figures/elements/tetrahedron_4.svg figures/elements/triangle_3.pdf figures/elements/triangle_3.svg figures/elements/triangle_6.pdf figures/elements/triangle_6.svg figures/elements/xtemp.pdf ) package_declare_documentation(core "This package is the core engine of \\akantu. It depends on:" "\\begin{itemize}" "\\item A C++ compiler (\\href{http://gcc.gnu.org/}{GCC} >= 4, or \\href{https://software.intel.com/en-us/intel-compilers}{Intel})." "\\item The cross-platform, open-source \\href{http://www.cmake.org/}{CMake} build system." "\\item The \\href{http://www.boost.org/}{Boost} C++ portable libraries." "\\item The \\href{http://www.zlib.net/}{zlib} compression library." "\\end{itemize}" "" "Under Ubuntu (14.04 LTS) the installation can be performed using the commands:" "\\begin{command}" " > sudo apt-get install cmake libboost-dev zlib1g-dev g++" "\\end{command}" "" "Under Mac OS X the installation requires the following steps:" "\\begin{itemize}" "\\item Install Xcode" "\\item Install the command line tools." "\\item Install the MacPorts project which allows to automatically" "download and install opensource packages." "\\end{itemize}" "Then the following commands should be typed in a terminal:" "\\begin{command}" " > sudo port install cmake gcc48 boost" "\\end{command}" ) find_program(READLINK_COMMAND readlink) find_program(ADDR2LINE_COMMAND addr2line) +find_program(PATCH_COMMAND patch) mark_as_advanced(READLINK_COMMAND) mark_as_advanced(ADDR2LINE_COMMAND) include(CheckFunctionExists) check_function_exists(clock_gettime _clock_gettime) include(CheckCXXSymbolExists) check_cxx_symbol_exists(strdup cstring AKANTU_HAS_STRDUP) if(NOT _clock_gettime) set(AKANTU_USE_OBSOLETE_GETTIMEOFDAY ON CACHE INTERNAL "" FORCE) else() set(AKANTU_USE_OBSOLETE_GETTIMEOFDAY OFF CACHE INTERNAL "" FORCE) endif() diff --git a/packages/python_interface.cmake b/packages/python_interface.cmake new file mode 100644 index 000000000..52d3cc380 --- /dev/null +++ b/packages/python_interface.cmake @@ -0,0 +1,31 @@ +#=============================================================================== +# @file python_interface.cmake +# +# @author Nicolas Richart +# +# @brief package description for the python interface +# +# @section LICENSE +# +# Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see . +# +#=============================================================================== + +package_declare(python_interface + DESCRIPTION "Akantu's python interface" + DEPENDS PythonLibs) + diff --git a/packages/pythonlibs.cmake b/packages/pythonlibs.cmake new file mode 100644 index 000000000..8d393dae6 --- /dev/null +++ b/packages/pythonlibs.cmake @@ -0,0 +1,40 @@ +#=============================================================================== +# @file pythonlibs.cmake +# +# @author Nicolas Richart +# +# @brief package description for the python library +# +# @section LICENSE +# +# Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see . +# +#=============================================================================== +set(Python_ADDITIONAL_VERSIONS 2.7) + +package_declare(PythonLibs EXTERNAL DESCRIPTION "Akantu's python interface" + EXTRA_PACKAGE_OPTIONS PREFIX PYTHON FOUND PYTHONLIBS_FOUND ARGS REQUIRED 2.7) + +package_declare_sources(Pythonlibs + python/python_functor.cc + python/python_functor.hh + python/python_functor_inline_impl.cc + model/boundary_condition_python_functor.hh + model/boundary_condition_python_functor.cc + model/solid_mechanics/materials/material_python/material_python.cc + model/solid_mechanics/materials/material_python/material_python.hh + ) \ No newline at end of file diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 9432b0094..54f86fe67 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,223 +1,252 @@ #=============================================================================== # @file CMakeLists.txt # # @author Nicolas Richart # # @date Wed Jul 9 17:22:12 2014 # # @brief CMake file for the python wrapping of 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 . # #=============================================================================== #=============================================================================== # Configuration #=============================================================================== package_get_all_definitions(AKANTU_DEFS) list(REMOVE_ITEM AKANTU_DEFS AKANTU_CORE_CXX11) #message(${AKANTU_DEFS}) set(AKA_DEFS "") foreach (def ${AKANTU_DEFS}) list(APPEND AKA_DEFS "-D${def}") endforeach() set(AKANTU_SWIG_FLAGS -w309,325,401,317,509,503 ${AKA_DEFS}) set(AKANTU_SWIG_OUTDIR ${CMAKE_CURRENT_SOURCE_DIR}) set(AKANTU_SWIG_MODULES swig/akantu.i) #=============================================================================== # Swig wrapper #=============================================================================== -find_package(SWIG 3.0 REQUIRED) +find_package(SWIG 3.0) find_package(PythonLibs) +find_package(PythonInterp) package_get_all_include_directories( AKANTU_LIBRARY_INCLUDE_DIRS ) package_get_all_external_informations( AKANTU_EXTERNAL_INCLUDE_DIR AKANTU_EXTERNAL_LIBRARIES ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/swig ${PYTHON_INCLUDE_PATH} ${AKANTU_LIBRARY_INCLUDE_DIRS} ${PROJECT_BINARY_DIR}/src ${AKANTU_EXTERNAL_INCLUDE_DIR} ) +#numpy includes +if(PYTHONINTERP_FOUND) + execute_process(COMMAND + ${PYTHON_EXECUTABLE} -c "import numpy; print(numpy.get_include())" + OUTPUT_VARIABLE NUMPY_INCLUDE_DIR) + + include_directories(${NUMPY_INCLUDE_DIR}) +endif() + include(CMakeParseArguments) + function(swig_generate_dependencies _module _depedencies) set(_dependencies_script "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/_swig_generate_dependencies.cmake") file(WRITE ${_dependencies_script} " set(_include_directories ${_include_directories}) list(APPEND _include_directories \"./\") set(_dep) set(_files_to_process \${_module}) while(_files_to_process) list(GET _files_to_process 0 _file) list(REMOVE_AT _files_to_process 0) file(STRINGS \${_file} _file_content REGEX \"^%include *\\\"(.*)\\\"\") set(_includes) foreach(_line \${_file_content}) string(REGEX REPLACE \"^%include *\\\"(.*)\\\"\" \"\\\\1\" _inc \${_line}) if(_inc) list(APPEND _includes \${_inc}) endif() endforeach() foreach(_include \${_includes}) unset(_found) foreach(_inc_dir \${_include_directories}) if(EXISTS \${_inc_dir}/\${_include}) set(_found \${_inc_dir}/\${_include}) break() endif() endforeach() if(_found) list(APPEND _files_to_process \${_found}) list(APPEND _dep \${_found}) endif() endforeach() endwhile() get_filename_component(_module_we \"\${_module}\" NAME_WE) set(_dependencies_file \${CMAKE_CURRENT_BINARY_DIR}\${CMAKE_FILES_DIRECTORY}/_swig_\${_module_we}_depends.cmake) file(WRITE \"\${_dependencies_file}\" \"set(_swig_\${_module_we}_depends\") foreach(_d \${_dep}) file(APPEND \"\${_dependencies_file}\" \" \${_d}\") endforeach() file(APPEND \"\${_dependencies_file}\" \" )\") ") get_directory_property(_include_directories INCLUDE_DIRECTORIES) get_filename_component(_module_absolute "${_module}" ABSOLUTE) get_filename_component(_module_we "${_module}" NAME_WE) set(_dependencies_file ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/_swig_${_module_we}_depends.cmake) if(EXISTS ${_dependencies_file}) include(${_dependencies_file}) else() execute_process(COMMAND ${CMAKE_COMMAND} -D_module=${_module_absolute} -P ${_dependencies_script} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) include(${_dependencies_file}) endif() add_custom_command(OUTPUT ${_dependencies_file} COMMAND ${CMAKE_COMMAND} -D_module=${_module_absolute} -P ${_dependencies_script} COMMENT "Scannong dependencies for swig module ${_module_we}" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} MAIN_DEPENDENCY ${_module_absolute} DEPENDS ${_swig_${_module_we}_depends} ) - set(${_depedencies} ${_dependencies_file} PARENT_SCOPE) endfunction() -function(swig_generate_wrappers project _wrappers) +function(swig_generate_wrappers project _wrappers_cpp _wrappers_py) cmake_parse_arguments(_swig_opt "" "OUTPUT_DIR" "EXTRA_FLAGS" ${ARGN}) if(_swig_opt_OUTPUT_DIR) set(_output_dir ${_swig_opt_OUTPUT_DIR}) else() set(_output_dir ${CMAKE_CURRENT_BINARY_DIR}) endif() set(_swig_wrappers) get_directory_property(_include_directories INCLUDE_DIRECTORIES) if(_include_directories) string(REPLACE ";" ";-I" _swig_include_directories "${_include_directories}") endif() foreach(_module ${_swig_opt_UNPARSED_ARGUMENTS}) swig_generate_dependencies(${_module} _module_dependencies) get_filename_component(_module_absolute "${_module}" ABSOLUTE) get_filename_component(_module_path "${_module_absolute}" PATH) get_filename_component(_module_name "${_module}" NAME) get_filename_component(_module_we "${_module}" NAME_WE) set(_wrapper "${_output_dir}/${_module_we}_wrapper.cc") set(_extra_wrapper "${_output_dir}/${_module_we}.py") set(_extra_wrapper_bin "${CMAKE_CURRENT_BINARY_DIR}/${_module_we}.py") - + message(${_extra_wrapper_bin}) if(SWIG_FOUND) set_source_files_properties("${_wrapper}" PROPERTIES GENERATED 1) set_source_files_properties("${_extra_wrapper}" PROPERTIES GENERATED 1) set(_dependencies_file ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/_swig_${_module_we}_depends.cmake) set(_ouput "${_wrapper}" "${_extra_wrapper}") add_custom_command( - OUTPUT ${_ouput} - COMMAND "${SWIG_EXECUTABLE}" - ARGS -python -c++ - ${_swig_opt_EXTRA_FLAGS} - -outdir ${_output_dir} - -I${_swig_include_directories} -I${_module_path} - -o "${_wrapper}" - "${_module_absolute}" - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_extra_wrapper} ${_extra_wrapper_bin} -# MAIN_DEPENDENCY "${_module_absolute}" + OUTPUT ${_ouput} + COMMAND "${SWIG_EXECUTABLE}" + ARGS -python -c++ + ${_swig_opt_EXTRA_FLAGS} + -outdir ${_output_dir} + -I${_swig_include_directories} -I${_module_path} + -o "${_wrapper}" + "${_module_absolute}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_extra_wrapper} ${_extra_wrapper_bin} + # MAIN_DEPENDENCY "${_module_absolute}" DEPENDS ${_module_dependencies} - COMMENT "Generating swig wrapper ${_module} -> ${_wrapper}" + COMMENT "Generating swig wrapper ${_module} -> ${_wrapper}" ) list(APPEND _swig_wrappers ${_wrapper}) + list(APPEND _swig_wrappers_py "${_extra_wrapper_bin}") else() if(NOT EXISTS ${_wrapper} OR NOT EXISTS "${_extra_wrapper}") - message(FATAL_ERROR "The file ${_wrapper} and/or ${_extra_wrapper} does not exists and they cannot be generated. Install swig in order to generate them") + message(FATAL_ERROR "The file ${_wrapper} and/or ${_extra_wrapper} does not exists and they cannot be generated. Install swig in order to generate them") else() - list(APPEND _swig_wrappers ${_wrapper}) + list(APPEND _swig_wrappers "${_wrapper}") + list(APPEND _swig_wrappers_py "${_extra_wrapper_bin}") endif() endif() endforeach() add_custom_target(${project}_generate_swig_wrappers DEPENDS ${_swig_wrappers}) - set(${_wrappers} ${_swig_wrappers} PARENT_SCOPE) + set(${_wrappers_cpp} ${_swig_wrappers} PARENT_SCOPE) + message(${_swig_wrappers_py}) + set(${_wrappers_py} ${_swig_wrappers_py} PARENT_SCOPE) endfunction() -swig_generate_wrappers(akantu AKANTU_SWIG_WRAPPERS +swig_generate_wrappers(akantu AKANTU_SWIG_WRAPPERS_CPP AKANTU_WRAPPERS_PYTHON ${AKANTU_SWIG_MODULES} EXTRA_FLAGS ${AKANTU_SWIG_FLAGS}) -if(AKANTU_SWIG_WRAPPERS) - add_library(_akantu MODULE ${AKANTU_SWIG_WRAPPERS}) +if(AKANTU_SWIG_WRAPPERS_CPP) + add_library(_akantu MODULE ${AKANTU_SWIG_WRAPPERS_CPP}) target_link_libraries(_akantu akantu ${PYTHON_LIBRARIES}) set_target_properties(_akantu PROPERTIES PREFIX "") + + list(APPEND AKANTU_EXPORT_LIST _akantu) + + install(TARGETS _akantu + EXPORT ${AKANTU_TARGETS_EXPORT} + LIBRARY DESTINATION lib COMPONENT python NAMELINK_SKIP # for real systems + ARCHIVE DESTINATION lib COMPONENT python + RUNTIME DESTINATION bin COMPONENT python # for windows ... + ) + + message(AKANTU_WRAPPERS_PYTHON ${AKANTU_WRAPPERS_PYTHON}) + install(FILES ${AKANTU_WRAPPERS_PYTHON} + DESTINATION lib COMPONENT python + ) + endif() diff --git a/python/swig/aka_array.i b/python/swig/aka_array.i index 6b06979c9..3f220cb6d 100644 --- a/python/swig/aka_array.i +++ b/python/swig/aka_array.i @@ -1,187 +1,187 @@ %{ #define SWIG_FILE_WITH_INIT #include "aka_array.hh" %} %include "typemaps.i" namespace akantu { %ignore Array::operator=; %ignore Array::operator[]; %ignore Array::operator(); %ignore Array::set; %ignore Array::begin; %ignore Array::end; %ignore Array::begin_reinterpret; %ignore Array::end_reinterpret; }; %include "aka_array.hh" namespace akantu { %template(RArray) Array; %template(UArray) Array; %template(BArray) Array; } %include "numpy.i" %init %{ import_array(); %} %inline %{ namespace akantu{ template class ArrayForPython : public Array{ public: ArrayForPython(T * wrapped_memory, UInt size = 0, UInt nb_component = 1, const ID & id = "") : Array(0,nb_component,id){ this->values = wrapped_memory; this->size = size; }; ~ArrayForPython(){ this->values = NULL; }; void resize(UInt new_size){ AKANTU_DEBUG_ASSERT(this->size == new_size,"cannot resize a temporary vector"); } }; } template int getPythonDataTypeCode(){ AKANTU_EXCEPTION("undefined type");} template <> int getPythonDataTypeCode(){ int data_typecode = NPY_NOTYPE; size_t s = sizeof(bool); switch(s) { case 1: data_typecode = NPY_BOOL; break; case 2: data_typecode = NPY_UINT16; break; case 4: data_typecode = NPY_UINT32; break; case 8: data_typecode = NPY_UINT64; break; } return data_typecode; } template <> int getPythonDataTypeCode(){return NPY_DOUBLE;} template <> int getPythonDataTypeCode(){return NPY_LONGDOUBLE;} template <> int getPythonDataTypeCode(){return NPY_FLOAT;} template <> int getPythonDataTypeCode(){ int data_typecode = NPY_NOTYPE; size_t s = sizeof(unsigned long); switch(s) { case 2: data_typecode = NPY_UINT16; break; case 4: data_typecode = NPY_UINT32; break; case 8: data_typecode = NPY_UINT64; break; } return data_typecode; } template <> int getPythonDataTypeCode(){ int data_typecode = NPY_NOTYPE; size_t s = sizeof(akantu::UInt); switch(s) { case 2: data_typecode = NPY_UINT16; break; case 4: data_typecode = NPY_UINT32; break; case 8: data_typecode = NPY_UINT64; break; } return data_typecode; } template <> int getPythonDataTypeCode(){ int data_typecode = NPY_NOTYPE; size_t s = sizeof(int); switch(s) { case 2: data_typecode = NPY_INT16; break; case 4: data_typecode = NPY_INT32; break; case 8: data_typecode = NPY_INT64; break; } return data_typecode; } int getSizeOfPythonType(int type_num){ switch (type_num){ case NPY_INT16 : return 2;break; case NPY_UINT16: return 2;break; case NPY_INT32 : return 4;break; case NPY_UINT32: return 4;break; case NPY_INT64 : return 8;break; case NPY_UINT64: return 8;break; case NPY_FLOAT: return sizeof(float);break; case NPY_DOUBLE: return sizeof(double);break; case NPY_LONGDOUBLE: return sizeof(long double);break; } return 0; } std::string getPythonTypeName(int type_num){ switch (type_num){ case NPY_INT16 : return "NPY_INT16" ;break; case NPY_UINT16: return "NPY_UINT16";break; case NPY_INT32 : return "NPY_INT32" ;break; case NPY_UINT32: return "NPY_UINT32";break; case NPY_INT64 : return "NPY_INT64" ;break; case NPY_UINT64: return "NPY_UINT64";break; case NPY_FLOAT: return "NPY_FLOAT" ;break; case NPY_DOUBLE: return "NPY_DOUBLE";break; case NPY_LONGDOUBLE: return "NPY_LONGDOUBLE";break; } return 0; } template void checkDataType(int type_num){ AKANTU_DEBUG_ASSERT(type_num == getPythonDataTypeCode(), "incompatible types between numpy and input function: " << type_num << " != " << getPythonDataTypeCode() << std::endl << getSizeOfPythonType(type_num) << " != " << sizeof(T) << std::endl << "The numpy array is of type " << getPythonTypeName(type_num)); } %} %define %akantu_array_typemaps(DATA_TYPE) %typemap(out, fragment="NumPy_Fragments") (akantu::Array< DATA_TYPE > &) { int data_typecode = getPythonDataTypeCode< DATA_TYPE >(); - npy_intp dims[2] = {$1->getSize(), $1->getNbComponent()}; + npy_intp dims[2] = {npy_intp($1->getSize()), npy_intp($1->getNbComponent())}; PyObject* obj = PyArray_SimpleNewFromData(2, dims, data_typecode, $1->storage()); PyArrayObject* array = (PyArrayObject*) obj; if (!array) SWIG_fail; $result = SWIG_Python_AppendOutput($result, obj); } %typemap(in) akantu::Array< DATA_TYPE > & { if (!PyArray_Check($input)) { AKANTU_EXCEPTION("incompatible input which is not a numpy"); } else { PyArray_Descr * numpy_type = (PyArray_Descr*)PyArray_DESCR((PyArrayObject*)$input); int type_num = numpy_type->type_num; checkDataType< DATA_TYPE >(type_num); UInt _n = PyArray_NDIM((PyArrayObject*)$input); if (_n != 2) AKANTU_EXCEPTION("incompatible numpy dimension " << _n); npy_intp * ndims = PyArray_DIMS((PyArrayObject*)$input); akantu::UInt sz = ndims[0]; akantu::UInt nb_components = ndims[1]; PyArrayIterObject *iter = (PyArrayIterObject *)PyArray_IterNew($input); if (iter == NULL) AKANTU_EXCEPTION("Python internal error"); $1 = new akantu::ArrayForPython< DATA_TYPE >((DATA_TYPE*)(iter->dataptr),sz,nb_components,"tmp_array_for_python"); } } %enddef %akantu_array_typemaps(double ) %akantu_array_typemaps(float ) %akantu_array_typemaps(unsigned int) %akantu_array_typemaps(unsigned long) %akantu_array_typemaps(int ) %akantu_array_typemaps(bool ) diff --git a/python/swig/solid_mechanics_model.i b/python/swig/solid_mechanics_model.i index 08d744527..e70b8d729 100644 --- a/python/swig/solid_mechanics_model.i +++ b/python/swig/solid_mechanics_model.i @@ -1,135 +1,137 @@ %{ #include "solid_mechanics_model.hh" #include "sparse_matrix.hh" #include "boundary_condition.hh" #include "boundary_condition_functor.hh" #include "boundary_condition_python_functor.hh" %} namespace akantu { %ignore SolidMechanicsModel::initFEEngineBoundary; %ignore SolidMechanicsModel::initParallel; %ignore SolidMechanicsModel::initArrays; - %ignore SolidMechanicsModel::initMaterials; %ignore SolidMechanicsModel::initModel; %ignore SolidMechanicsModel::initPBC; %ignore SolidMechanicsModel::initExplicit; %ignore SolidMechanicsModel::isExplicit; %ignore SolidMechanicsModel::updateCurrentPosition; %ignore SolidMechanicsModel::updateAcceleration; %ignore SolidMechanicsModel::updateIncrement; %ignore SolidMechanicsModel::updatePreviousDisplacement; %ignore SolidMechanicsModel::saveStressAndStrainBeforeDamage; %ignore SolidMechanicsModel::updateEnergiesAfterDamage; %ignore SolidMechanicsModel::solveLumped; %ignore SolidMechanicsModel::explicitPred; %ignore SolidMechanicsModel::explicitCorr; %ignore SolidMechanicsModel::initSolver; %ignore SolidMechanicsModel::initImplicit; %ignore SolidMechanicsModel::initialAcceleration; %ignore SolidMechanicsModel::testConvergence; %ignore SolidMechanicsModel::testConvergenceIncrement; %ignore SolidMechanicsModel::testConvergenceResidual; %ignore SolidMechanicsModel::initVelocityDampingMatrix; %ignore SolidMechanicsModel::getNbDataForElements; %ignore SolidMechanicsModel::packElementData; %ignore SolidMechanicsModel::unpackElementData; %ignore SolidMechanicsModel::getNbDataToPack; %ignore SolidMechanicsModel::getNbDataToUnpack; %ignore SolidMechanicsModel::packData; %ignore SolidMechanicsModel::unpackData; %ignore SolidMechanicsModel::setMaterialSelector; %ignore SolidMechanicsModel::getSolver; %ignore SolidMechanicsModel::getSynchronizer; %ignore Dumpable::registerExternalDumper; } %template(SolidMechanicsBoundaryCondition) akantu::BoundaryCondition; %include "dumpable.hh" print_self(SolidMechanicsModel) %include "solid_mechanics_model.hh" %extend akantu::SolidMechanicsModel { bool testConvergenceSccRes(Real tolerance) { - Real error = 0; - bool res = self->testConvergence(tolerance,error); + bool res = self->testConvergence(tolerance,error); return res; } void solveStaticDisplacement(Real tolerance, UInt max_iteration) { - - $self->solveStatic(tolerance, max_iteration); - + $self->solveStatic(tolerance, max_iteration); } - void applyBC(PyObject * func_obj, - const BC::Functor::Type & type, - const std::string & group_name) { + void applyDirichletBC(PyObject * func_obj, + const std::string & group_name) { akantu::BC::PythonFunctorDirichlet functor(func_obj); $self->applyBC(functor,group_name); } + void applyNeumannBC(PyObject * func_obj, + const std::string & group_name) { + + akantu::BC::PythonFunctorNeumann functor(func_obj); + $self->applyBC(functor,group_name); + } + void solveDisplCorr(bool need_factorize, bool has_profile_changed) { akantu::Array & increment = $self->getIncrement(); $self->solve(increment, 1., need_factorize, has_profile_changed); } void clearDispl() { akantu::Array & displ = $self->getDisplacement(); displ.clear(); } void solveStep_TgModifIncr(Real tolerance, UInt max_iteration) { - $self->solveStep(tolerance, max_iteration); + $self->solveStep(tolerance, max_iteration); } void clearDisplVeloAcc() { akantu::Array & displ = $self->getDisplacement(); akantu::Array & velo = $self->getVelocity(); akantu::Array & acc = $self->getAcceleration(); displ.clear(); velo.clear(); acc.clear(); } void applyUniformPressure(Real pressure, const std::string surface_name){ UInt spatial_dimension = $self->getSpatialDimension(); akantu::Matrix surface_stress(spatial_dimension, spatial_dimension, 0.0); for(UInt i = 0; i < spatial_dimension; ++i) { surface_stress(i,i) = -pressure; } $self->applyBC(akantu::BC::Neumann::FromStress(surface_stress), surface_name); } void blockDOF(const std::string surface_name, SpacialDirection direction){ $self->applyBC(akantu::BC::Dirichlet::FixedValue(0.0, direction), surface_name); } } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 293a8abde..79decb98c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,157 +1,159 @@ #=============================================================================== # @file CMakeLists.txt # # @author Guillaume Anciaux # @author Nicolas Richart # # @date creation: Mon Nov 28 2011 # @date last modification: Tue Sep 16 2014 # # @brief CMake file for the library # # @section LICENSE # # Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # #=============================================================================== #=============================================================================== # Package Management #=============================================================================== package_get_all_source_files( AKANTU_LIBRARY_SRCS AKANTU_LIBRARY_PUBLIC_HDRS AKANTU_LIBRARY_PRIVATE_HDRS ) package_get_all_include_directories( AKANTU_LIBRARY_INCLUDE_DIRS ) package_get_all_external_informations( AKANTU_EXTERNAL_INCLUDE_DIR AKANTU_EXTERNAL_LIBRARIES ) #=========================================================================== # header for blas/lapack (any other fortran libraries) #=========================================================================== package_is_activated(BLAS _blas_activated) package_is_activated(LAPACK _lapack_activated) if(_blas_activated OR _lapack_activated) if(CMAKE_Fortran_COMPILER) # ugly hack set(CMAKE_Fortran_COMPILER_LOADED TRUE) endif() include(FortranCInterface) FortranCInterface_HEADER( ${CMAKE_CURRENT_BINARY_DIR}/aka_fortran_mangling.hh MACRO_NAMESPACE "AKA_FC_") mark_as_advanced(CDEFS) list(APPEND AKANTU_LIBRARY_PUBLIC_HDRS ${CMAKE_CURRENT_BINARY_DIR}/aka_fortran_mangling.hh) endif() #=========================================================================== # configurations #=========================================================================== package_get_all_material_includes(AKANTU_MATERIAL_INCLUDES) package_get_all_material_lists(AKANTU_MATERIAL_LISTS) configure_file(model/solid_mechanics/material_list.hh.in "${CMAKE_CURRENT_BINARY_DIR}/material_list.hh" @ONLY) package_get_element_lists() configure_file(common/aka_element_classes_info.hh.in "${CMAKE_CURRENT_BINARY_DIR}/aka_element_classes_info.hh" @ONLY) configure_file(common/aka_config.hh.in "${CMAKE_CURRENT_BINARY_DIR}/aka_config.hh" @ONLY) list(APPEND AKANTU_LIBRARY_PUBLIC_HDRS ${CMAKE_CURRENT_BINARY_DIR}/aka_config.hh ${CMAKE_CURRENT_BINARY_DIR}/material_list.hh) list(APPEND AKANTU_LIBRARY_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}) add_extra_mpi_options() #=========================================================================== # header precompilation #=========================================================================== set(AKANTU_COMMON_HDR_TO_PRECOMPILE common/aka_vector.hh common/aka_math.hh common/aka_types.hh fem/element_class.hh ) set(AKANTU_PRECOMPILE_HDR_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/common/ ${CMAKE_CURRENT_BINARY_DIR}/fem/ ) set(AKANTU_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} ${AKANTU_LIBRARY_INCLUDE_DIRS} ${AKANTU_PRECOMPILE_HDR_INCLUDE_DIRS} CACHE INTERNAL "Internal include directories to link with Akantu as a subproject") include_directories(${AKANTU_INCLUDE_DIRS} ${AKANTU_EXTERNAL_INCLUDE_DIR}) generate_material_list() if(CMAKE_COMPILER_IS_GNUCXX) include(PCHgcc) foreach(_header ${AKANTU_COMMON_HDR_TO_PRECOMPILE}) add_pch_rule(${_header} AKANTU_LIBRARY_SRCS) endforeach() elseif(CMAKE_COMPILER_IS_GNUCXX) endif() #=============================================================================== # Library generation #=============================================================================== add_library(akantu ${AKANTU_LIBRARY_SRCS}) target_link_libraries(akantu ${AKANTU_EXTERNAL_LIBRARIES}) package_get_all_extra_dependencies(_extra_target_dependencies) if(_extra_target_dependencies) # This only adding todo: find a solution for when a dependency was add the is removed... add_dependencies(akantu ${_extra_target_dependencies}) endif() set_target_properties(akantu PROPERTIES ${AKANTU_LIBRARY_PROPERTIES}) set_target_properties(akantu PROPERTIES PUBLIC_HEADER "${AKANTU_LIBRARY_PUBLIC_HDRS}") list(APPEND AKANTU_EXPORT_LIST akantu) +# TODO separate public from private headers install(TARGETS akantu EXPORT ${AKANTU_TARGETS_EXPORT} LIBRARY DESTINATION lib COMPONENT lib ARCHIVE DESTINATION lib COMPONENT lib + RUNTIME DESTINATION bin COMPONENT bin PUBLIC_HEADER DESTINATION include/akantu/ COMPONENT dev ) if("${AKANTU_TARGETS_EXPORT}" STREQUAL "AkantuLibraryDepends") install(EXPORT AkantuLibraryDepends DESTINATION lib/akantu COMPONENT dev) endif() #Export for build tree export(TARGETS ${AKANTU_EXPORT_LIST} FILE "${CMAKE_BINARY_DIR}/AkantuLibraryDepends.cmake") export(PACKAGE Akantu) diff --git a/src/common/aka_common.cc b/src/common/aka_common.cc index 0734896b9..089584f08 100644 --- a/src/common/aka_common.cc +++ b/src/common/aka_common.cc @@ -1,147 +1,148 @@ /** * @file aka_common.cc * * @author Nicolas Richart * * @date creation: Mon Jun 14 2010 * @date last modification: Mon Sep 15 2014 * * @brief Initialization of global variables * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_static_memory.hh" #include "static_communicator.hh" #include "static_solver.hh" #include "aka_random_generator.hh" #include "parser.hh" #include "cppargparse.hh" - +/* -------------------------------------------------------------------------- */ +#include /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void initialize(int & argc, char ** & argv) { AKANTU_DEBUG_IN(); initialize("", argc, argv); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void initialize(const std::string & input_file, int & argc, char ** & argv) { AKANTU_DEBUG_IN(); StaticMemory::getStaticMemory(); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(argc, argv); debug::debugger.setParallelContext(comm.whoAmI(), comm.getNbProc()); debug::initSignalHandler(); static_argparser.setParallelContext(comm.whoAmI(), comm.getNbProc()); static_argparser.setExternalExitFunction(debug::exit); static_argparser.addArgument("--aka_input_file", "Akantu's input file", 1, cppargparse::_string, std::string()); static_argparser.addArgument("--aka_debug_level", std::string("Akantu's overall debug level") + std::string(" (0: error, 1: exceptions, 4: warnings, 5: info, ..., 100: dump,") + std::string(" more info on levels can be foind in aka_error.hh)"), 1, cppargparse::_integer, int(dblWarning)); static_argparser.addArgument("--aka_print_backtrace", "Should Akantu print a backtrace in case of error", 0, cppargparse::_boolean, false, true); static_argparser.parse(argc, argv, cppargparse::_remove_parsed); std::string infile = static_argparser["aka_input_file"]; if(infile == "") infile = input_file; debug::setDebugLevel(dblError); if ("" != infile) { static_parser.parse(infile); } long int seed; try { seed = static_parser.getParameter("seed", _ppsc_current_scope); } catch (debug::Exception &) { seed = time(NULL); } int dbl_level = static_argparser["aka_debug_level"]; debug::setDebugLevel(DebugLevel(dbl_level)); debug::debugger.printBacktrace(static_argparser["aka_print_backtrace"]); seed *= (comm.whoAmI() + 1); #if not defined(_WIN32) Rand48Generator::seed(seed); #endif RandGenerator::seed(seed); AKANTU_DEBUG_INFO("Random seed set to " << seed); /// initialize external solvers StaticSolver::getStaticSolver().initialize(argc,argv); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void finalize() { AKANTU_DEBUG_IN(); /// finalize external solvers StaticSolver::getStaticSolver().finalize(); if(StaticMemory::isInstantiated()) delete &(StaticMemory::getStaticMemory()); if(StaticCommunicator::isInstantiated()) { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); comm.barrier(); delete &comm; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ cppargparse::ArgumentParser & getStaticArgumentParser() { return static_argparser; } /* -------------------------------------------------------------------------- */ Parser & getStaticParser() { return static_parser; } /* -------------------------------------------------------------------------- */ const ParserSection & getUserParser() { return *(static_parser.getSubSections(_st_user).first); } __END_AKANTU__ diff --git a/src/common/aka_config.hh.in b/src/common/aka_config.hh.in index 07d4400b4..a5a1b7b28 100644 --- a/src/common/aka_config.hh.in +++ b/src/common/aka_config.hh.in @@ -1,124 +1,125 @@ /** * @file aka_config.hh.in * * @author Nicolas Richart * * @date Fri Jan 13 12:34:54 2012 * * @brief Compilation time configuration of Akantu * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_CONFIG_HH__ #define __AKANTU_AKA_CONFIG_HH__ #define AKANTU_VERSION_MAJOR @AKANTU_MAJOR_VERSION@ #define AKANTU_VERSION_MINOR @AKANTU_MINOR_VERSION@ #define AKANTU_VERSION_PATCH @AKANTU_PATCH_VERSION@ #define AKANTU_VERSION (AKANTU_VERSION_MAJOR * 100000 \ + AKANTU_VERSION_MINOR * 1000 \ + AKANTU_VERSION_PATCH) @AKANTU_TYPES_EXTRA_INCLUDES@ namespace akantu { typedef @AKANTU_FLOAT_TYPE@ Real; typedef @AKANTU_SIGNED_INTEGER_TYPE@ Int; typedef @AKANTU_UNSIGNED_INTEGER_TYPE@ UInt; template struct unordered_map { typedef typename @AKANTU_UNORDERED_MAP_TYPE@ type; }; template std::size_t hash(const T & t) { typedef @AKANTU_HASH_TYPE@ hash_type; return hash_type()(t); }; } #define AKANTU_INTEGER_SIZE @AKANTU_INTEGER_SIZE@ #define AKANTU_FLOAT_SIZE @AKANTU_FLOAT_SIZE@ #cmakedefine AKANTU_UNORDERED_MAP_IS_CXX11 #define __BEGIN_AKANTU_UNORDERED_MAP__ \ @AKANTU_UNORDERED_MAP_NAMESPACE_BEGIN@ #define __END_AKANTU_UNORDERED_MAP__ \ @AKANTU_UNORDERED_MAP_NAMESPACE_END@ #cmakedefine AKANTU_HAS_STRDUP #cmakedefine AKANTU_USE_BLAS #cmakedefine AKANTU_USE_LAPACK #cmakedefine AKANTU_PARALLEL #cmakedefine AKANTU_USE_MPI #cmakedefine AKANTU_USE_SCOTCH #cmakedefine AKANTU_USE_PTSCOTCH #cmakedefine AKANTU_SCOTCH_NO_EXTERN #cmakedefine AKANTU_USE_MUMPS #cmakedefine AKANTU_USE_PETSC #cmakedefine AKANTU_USE_IOHELPER #cmakedefine AKANTU_USE_QVIEW #cmakedefine AKANTU_USE_BLACKDYNAMITE #cmakedefine AKANTU_USE_NLOPT #cmakedefine AKANTU_USE_CPPARRAY #cmakedefine AKANTU_USE_OBSOLETE_GETTIMEOFDAY #cmakedefine AKANTU_EXTRA_MATERIALS #cmakedefine AKANTU_STUDENTS_EXTRA_PACKAGE #cmakedefine AKANTU_DAMAGE_NON_LOCAL #cmakedefine AKANTU_STRUCTURAL_MECHANICS #cmakedefine AKANTU_HEAT_TRANSFER +#cmakedefine AKANTU_PYTHON_INTERFACE #cmakedefine AKANTU_COHESIVE_ELEMENT #cmakedefine AKANTU_PARALLEL_COHESIVE_ELEMENT #cmakedefine AKANTU_IGFEM #cmakedefine AKANTU_USE_CGAL #cmakedefine AKANTU_EMBEDDED // BOOST Section #cmakedefine AKANTU_BOOST_CHRONO #cmakedefine AKANTU_BOOST_SYSTEM // Experimental part #cmakedefine AKANTU_CORE_CXX11 // Debug tools //#cmakedefine AKANTU_NDEBUG #cmakedefine AKANTU_DEBUG_TOOLS #cmakedefine READLINK_COMMAND @READLINK_COMMAND@ #cmakedefine ADDR2LINE_COMMAND @ADDR2LINE_COMMAND@ #define __aka_inline__ inline #endif /* __AKANTU_AKA_CONFIG_HH__ */ diff --git a/src/fe_engine/integration_point.hh b/src/fe_engine/integration_point.hh index 601d11a4f..c3c713bc1 100644 --- a/src/fe_engine/integration_point.hh +++ b/src/fe_engine/integration_point.hh @@ -1,153 +1,157 @@ /** * @file integration_point.hh * * @author * * @date creation: * @date last modification: Mon Oct 19 2015 * * @brief definition of the class IntegrationPoint * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #ifndef AKANTU_QUADRATURE_POINT_H #define AKANTU_QUADRATURE_POINT_H /* -------------------------------------------------------------------------- */ +#include "element.hh" +#include "aka_types.hh" +/* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ class IntegrationPoint; extern const IntegrationPoint IntegrationPointNull; +/* -------------------------------------------------------------------------- */ class IntegrationPoint : public Element { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: typedef Vector position_type; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: IntegrationPoint(const Element & element, UInt num_point = 0, UInt nb_quad_per_element = 0) : Element(element), num_point(num_point), global_num(element.element*nb_quad_per_element + num_point), position((Real *)NULL, 0) { }; IntegrationPoint(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) { }; IntegrationPoint(UInt element, UInt num_point, UInt global_num, const position_type & position, ElementType type, GhostType ghost_type = _not_ghost) : Element(type, element, ghost_type), num_point(num_point), global_num(global_num), position((Real *)NULL, 0) { this->position.shallowCopy(position); }; IntegrationPoint(const IntegrationPoint & quad) : Element(quad), num_point(quad.num_point), global_num(quad.global_num), position((Real *) NULL, 0) { position.shallowCopy(quad.position); }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ inline bool operator==(const IntegrationPoint & quad) const { return Element::operator==(quad) && this->num_point == quad.num_point; } inline bool operator!=(const IntegrationPoint & quad) const { return ((element != quad.element) || (type != quad.type) || (ghost_type != quad.ghost_type) || (kind != quad.kind) || (num_point != quad.num_point) || (global_num != quad.global_num)); } bool operator<(const IntegrationPoint& rhs) const { bool res = Element::operator<(rhs) || (Element::operator==(rhs) && this->num_point < rhs.num_point); return res; } inline IntegrationPoint & operator=(const IntegrationPoint & 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; } /// get the position of the integration point AKANTU_GET_MACRO(Position, position, const position_type &); /// set the position of the integration point void setPosition(const position_type & position) { this->position.shallowCopy(position); } /// deep copy of the position of the integration point void copyPosition(const position_type & position) { this->position.deepCopy(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 << "IntegrationPoint ["; Element::printself(stream, 0); stream << ", " << num_point << "(" << global_num << ")" << "]"; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: /// number of quadrature point in the element UInt num_point; /// global number of the quadrature point UInt global_num; // TODO might be temporary: however this class should be tought maybe... std::string material_id; private: /// position of the quadrature point position_type position; }; __END_AKANTU__ #endif /* AKANTU_QUADRATURE_POINT_H */ diff --git a/src/geometry/mesh_sphere_intersector_tmpl.hh b/src/geometry/mesh_sphere_intersector_tmpl.hh index 900ae984c..72ad9f6fa 100644 --- a/src/geometry/mesh_sphere_intersector_tmpl.hh +++ b/src/geometry/mesh_sphere_intersector_tmpl.hh @@ -1,195 +1,193 @@ /** * @file mesh_sphere_intersector_tmpl.hh * * @author Clément Roux-Langlois * * @date creation: Wed june 10 2015 * @date last modification: Wed June 17 2015 * * @brief Computation of mesh intersection with spheres * * @section LICENSE * * Copyright (©) 2010-2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_SPHERE_INTERSECTOR_TMPL_HH__ #define __AKANTU_MESH_SPHERE_INTERSECTOR_TMPL_HH__ #include "aka_common.hh" #include "mesh_geom_common.hh" #include "tree_type_helper.hh" #include "mesh_sphere_intersector.hh" #include "static_communicator.hh" __BEGIN_AKANTU__ template MeshSphereIntersector::MeshSphereIntersector(Mesh & mesh): parent_type(mesh), tol_intersection_on_node(1e-10) { #if defined(AKANTU_IGFEM) if( (type == _triangle_3) || (type == _igfem_triangle_4) || (type == _igfem_triangle_5) ){ const_cast(this->nb_seg_by_el) = 3; } else { AKANTU_DEBUG_ERROR("Not ready for mesh type " << type); } #else if( (type != _triangle_3) ) AKANTU_DEBUG_ERROR("Not ready for mesh type " << type); #endif // initialize the intersection pointsss array with the spatial dimension this->intersection_points = new Array(0,dim); // A maximum is set to the number of intersection nodes per element to limit the size of new_node_per_elem: 2 in 2D and 4 in 3D this->new_node_per_elem = new Array(0, 1 + 4 * (dim-1)); } template MeshSphereIntersector::~MeshSphereIntersector() { delete this->new_node_per_elem; delete this->intersection_points; } template void MeshSphereIntersector::constructData(GhostType ghost_type) { this->new_node_per_elem->resize(this->mesh.getNbElement(type, ghost_type)); this->new_node_per_elem->clear(); MeshGeomIntersector, SK::Sphere_3, SK>::constructData(ghost_type); } template void MeshSphereIntersector:: computeMeshQueryIntersectionPoint(const SK::Sphere_3 & query, UInt nb_old_nodes) { /// function to replace computeIntersectionQuery in a more generic geometry module version // The newNodeEvent is not send from this method who only compute the intersection points AKANTU_DEBUG_IN(); Array & nodes = this->mesh.getNodes(); UInt nb_node = nodes.getSize() + this->intersection_points->getSize(); // Tolerance for proximity checks should be defined by user Real global_tolerance = Math::getTolerance(); Math::setTolerance(tol_intersection_on_node); typedef boost::variant sk_inter_res; TreeTypeHelper, Spherical>::const_iterator it = this->factory.getPrimitiveList().begin(), end= this->factory.getPrimitiveList().end(); for (; it != end ; ++it) { // loop on the primitives (segments) std::list s_results; CGAL::intersection(*it, query, std::back_inserter(s_results)); if (s_results.size() == 1) { // just one point if (pair_type * pair = boost::get(&s_results.front())) { if (pair->second == 1) { // not a point tangent to the sphere // the intersection point written as a vector Vector new_node(dim, 0.0); Cartesian::Point_3 point(CGAL::to_double(pair->first.x()), CGAL::to_double(pair->first.y()), CGAL::to_double(pair->first.z())); for (UInt i = 0 ; i < dim ; i++) { new_node(i) = point[i]; } - bool is_on_mesh = false, is_new = true; + /// boolean to decide wheter intersection point is on a standard node of the mesh or not + bool is_on_mesh = false; + /// boolean to decide if this intersection point has been already computed for a neighbor element + bool is_new = true; + + /// check if intersection point has already been computed + UInt n = nb_old_nodes; + // check if we already compute this intersection and add it as a node for a neighboor element of another type Array::vector_iterator existing_node = nodes.begin(dim); - UInt n = nb_old_nodes; + for (; n < nodes.getSize() ; ++n) {// loop on the nodes from nb_old_nodes if (Math::are_vector_equal(dim, new_node.storage(), existing_node[n].storage())) { is_new = false; break; } } - // check if we already compute this intersection for a neighboor element of this type if(is_new){ Array::vector_iterator intersection_points_it = this->intersection_points->begin(dim); Array::vector_iterator intersection_points_end = this->intersection_points->end(dim); for (; intersection_points_it != intersection_points_end ; ++intersection_points_it, ++n) { if (Math::are_vector_equal(dim, new_node.storage(), intersection_points_it->storage())) { is_new = false; break; } } } // get the initial and final points of the primitive (segment) and write them as vectors Cartesian::Point_3 source_cgal(CGAL::to_double(it->source().x()), CGAL::to_double(it->source().y()), CGAL::to_double(it->source().z())); Cartesian::Point_3 target_cgal(CGAL::to_double(it->target().x()), CGAL::to_double(it->target().y()), CGAL::to_double(it->target().z())); Vector source(dim), target(dim); for (UInt i = 0 ; i < dim ; i++) { source(i) = source_cgal[i]; target(i) = target_cgal[i]; } // Check if we are close from a node of the primitive (segment) if (Math::are_vector_equal(dim, source.storage(), new_node.storage()) || Math::are_vector_equal(dim, target.storage(), new_node.storage())) { is_on_mesh = true; is_new = false; } if (is_new) {// if the intersection point is a new one add it to the list this->intersection_points->push_back(new_node); nb_node++; } // deduce the element id UInt element_id = it->id(); // fill the new_node_per_elem array if (!is_on_mesh) { // if the node is not on a mesh node UInt & nb_new_nodes_per_el = (*this->new_node_per_elem)(element_id, 0); nb_new_nodes_per_el += 1; + AKANTU_DEBUG_ASSERT(2 * nb_new_nodes_per_el < this->new_node_per_elem->getNbComponent(), + "You might have to interface crossing the same material"); (*this->new_node_per_elem)(element_id, (2 * nb_new_nodes_per_el) - 1) = n; (*this->new_node_per_elem)(element_id, 2 * nb_new_nodes_per_el) = it->segId(); - } else { // if intersection is at an existing node, write node number (in el) in pennultimate position - if (Math::are_vector_equal(dim, source.storage(), new_node.storage())) { - // 2D: if it is the initial node of the segment its number within the element is the segment ID - (*this->new_node_per_elem)(element_id, (this->new_node_per_elem->getNbComponent() - 2)) = it->segId(); - } else { - // 2D: otherwise (final node of the segment) its number within the element - // is the segment ID+1 modulo the number of segment per elements - (*this->new_node_per_elem)(element_id, (this->new_node_per_elem->getNbComponent() - 2)) = - (it->segId()+1) % this->nb_seg_by_el; - } - } + } } } } } Math::setTolerance(global_tolerance); AKANTU_DEBUG_OUT(); } __END_AKANTU__ #endif // __AKANTU_MESH_SPHERE_INTERSECTOR_TMPL_HH__ diff --git a/src/io/dumper/dumpable_inline_impl.hh b/src/io/dumper/dumpable_inline_impl.hh index 1c93bf84e..b58a7b53a 100644 --- a/src/io/dumper/dumpable_inline_impl.hh +++ b/src/io/dumper/dumpable_inline_impl.hh @@ -1,137 +1,147 @@ /** * @file dumpable_inline_impl.hh * * @author Guillaume Anciaux * @author David Simon Kammer * @author Nicolas Richart * * @date creation: Wed Nov 13 2013 * @date last modification: Mon Sep 15 2014 * * @brief Implementation of the Dumpable class * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #ifndef __AKANTU_DUMPABLE_INLINE_IMPL_HH__ #define __AKANTU_DUMPABLE_INLINE_IMPL_HH__ /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #include "dumper_elemental_field.hh" #include "dumper_nodal_field.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template inline void Dumpable::registerDumper(const std::string & dumper_name, const std::string & file_name, const bool is_default) { if (this->dumpers.find(dumper_name) != this->dumpers.end()){ AKANTU_DEBUG_INFO("Dumper " + dumper_name + "is already registered."); } std::string name = file_name; if (name == "") name = dumper_name; this->dumpers[dumper_name] = new T(name); if (is_default) this->default_dumper = dumper_name; } /* -------------------------------------------------------------------------- */ template inline void Dumpable::addDumpFieldExternal(const std::string & field_id, const Array & field) { this->addDumpFieldExternalToDumper(this->default_dumper, field_id, field); }; /* -------------------------------------------------------------------------- */ template inline void Dumpable::addDumpFieldExternalToDumper(const std::string & dumper_name, const std::string & field_id, const Array & field) { dumper::Field * field_cont = new dumper::NodalField(field); DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.registerField(field_id, field_cont); } /* -------------------------------------------------------------------------- */ template inline void Dumpable::addDumpFieldExternal(const std::string & field_id, const ElementTypeMapArray & field, UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & element_kind) { this->addDumpFieldExternalToDumper(this->default_dumper, field_id, field, spatial_dimension, ghost_type, element_kind); } /* -------------------------------------------------------------------------- */ template inline void Dumpable::addDumpFieldExternalToDumper(const std::string & dumper_name, const std::string & field_id, const ElementTypeMapArray & field, UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & element_kind) { - dumper::Field * field_cont = new dumper::ElementalField(field, - spatial_dimension, - ghost_type, - element_kind); + + dumper::Field * field_cont; +#if defined(AKANTU_IGFEM) + if (element_kind == _ek_igfem) { + field_cont = new dumper::IGFEMElementalField(field, + spatial_dimension, + ghost_type, + element_kind); + } else +#endif + field_cont = new dumper::ElementalField(field, + spatial_dimension, + ghost_type, + element_kind); DumperIOHelper & dumper = this->getDumper(dumper_name); dumper.registerField(field_id, field_cont); } /* -------------------------------------------------------------------------- */ template inline T & Dumpable::getDumper(const std::string & dumper_name) { DumperIOHelper & dumper = this->getDumper(dumper_name); try { T & templated_dumper = dynamic_cast(dumper); return templated_dumper; } catch (...) { AKANTU_EXCEPTION("Dumper " << dumper_name << " is not of type: " << debug::demangle(typeid(T).name())); } } /* -------------------------------------------------------------------------- */ __END_AKANTU__ #endif #endif /* __AKANTU_DUMPABLE_INLINE_IMPL_HH__ */ diff --git a/src/io/dumper/dumper_compute.hh b/src/io/dumper/dumper_compute.hh index 7f937ad14..13f1dc4e9 100644 --- a/src/io/dumper/dumper_compute.hh +++ b/src/io/dumper/dumper_compute.hh @@ -1,270 +1,272 @@ /** * @file dumper_compute.hh * * @author Guillaume Anciaux * * @date creation: Tue Sep 02 2014 * @date last modification: Fri Sep 05 2014 * * @brief Field that map a function to another field * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #ifndef __AKANTU_DUMPER_COMPUTE_HH__ #define __AKANTU_DUMPER_COMPUTE_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "dumper_iohelper.hh" #include "dumper_type_traits.hh" #include "dumper_field.hh" #include /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ __BEGIN_AKANTU_DUMPER__ class ComputeFunctorInterface { public: virtual ~ComputeFunctorInterface(){}; virtual UInt getDim() = 0; virtual UInt getNbComponent(UInt old_nb_comp) = 0; }; /* -------------------------------------------------------------------------- */ template class ComputeFunctorOutput : public ComputeFunctorInterface { public: ComputeFunctorOutput(){}; virtual ~ComputeFunctorOutput(){}; }; /* -------------------------------------------------------------------------- */ template class ComputeFunctor : public ComputeFunctorOutput { public: ComputeFunctor(){}; virtual ~ComputeFunctor(){}; virtual return_type func(const input_type & d, Element global_index) = 0; }; /* -------------------------------------------------------------------------- */ template class FieldCompute : public Field { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: typedef typename SubFieldCompute::iterator sub_iterator; typedef typename SubFieldCompute::types sub_types; typedef typename sub_types::return_type sub_return_type; typedef _return_type return_type; typedef typename sub_types::data_type data_type; typedef TypeTraits > types; class iterator { public: iterator(const sub_iterator & it, ComputeFunctor & func) : it(it), func(func) {} bool operator!=(const iterator & it)const { return it.it != this->it; } iterator operator++() { ++this->it; return *this; } UInt currentGlobalIndex(){ return this->it.currentGlobalIndex(); } return_type operator*() { return func.func(*it,it.getCurrentElement()); } Element getCurrentElement(){ return this->it.getCurrentElement(); } UInt element_type() { return this->it.element_type(); } protected: sub_iterator it; ComputeFunctor & func; }; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FieldCompute(SubFieldCompute & cont, ComputeFunctorInterface & func) :sub_field(cont),func(dynamic_cast &>(func)){ this->checkHomogeneity(); }; virtual void registerToDumper(const std::string & id, iohelper::Dumper & dumper) { dumper.addElemDataField(id, *this); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: iterator begin() { return iterator(sub_field.begin(), func); } iterator end () { return iterator(sub_field.end(), func); } UInt getDim() { return func.getDim(); } UInt size() { throw; // return Functor::size(); return 0; } virtual void checkHomogeneity(){this->homogeneous = true;}; iohelper::DataType getDataType() { return iohelper::getDataType(); } /// get the number of components of the hosted field virtual ElementTypeMap getNbComponents(UInt dim = _all_dimensions, GhostType ghost_type = _not_ghost, ElementKind kind = _ek_not_defined){ ElementTypeMap nb_components; const ElementTypeMap & old_nb_components = this->sub_field.getNbComponents(dim,ghost_type,kind); ElementTypeMap::type_iterator tit = old_nb_components.firstType(dim,ghost_type,kind); ElementTypeMap::type_iterator end = old_nb_components.lastType(dim,ghost_type,kind); while (tit != end){ UInt nb_comp = old_nb_components(*tit,ghost_type); nb_components(*tit,ghost_type) = func.getNbComponent(nb_comp); ++tit; } return nb_components; }; /// for connection to a FieldCompute inline virtual Field * connect(FieldComputeProxy & proxy); /// for connection to a FieldCompute virtual ComputeFunctorInterface * connect(HomogenizerProxy & proxy); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: SubFieldCompute & sub_field; ComputeFunctor & func; }; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ class FieldComputeProxy { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FieldComputeProxy(ComputeFunctorInterface & func):func(func){}; inline static Field * createFieldCompute(Field * field, ComputeFunctorInterface & func){ FieldComputeProxy compute_proxy(func); return field->connect(compute_proxy); } template Field * connectToField(T * ptr){ if (dynamic_cast > *>(&func)){ return this->connectToFunctor >(ptr); } else if (dynamic_cast > *>(&func)){ return this->connectToFunctor >(ptr); } else if (dynamic_cast > *>(&func)){ return this->connectToFunctor >(ptr); } else if (dynamic_cast > *>(&func)){ return this->connectToFunctor >(ptr); } else throw; } template Field * connectToFunctor(T * ptr){ - return new FieldCompute(*ptr,func); + FieldCompute * functor_ptr = new FieldCompute(*ptr,func); + return functor_ptr; } template Field * connectToFunctor(FieldCompute, return_type2> * ptr){ throw; // return new FieldCompute(*ptr,func); return NULL; } template Field * connectToFunctor(FieldCompute< FieldCompute< FieldCompute< FieldCompute, return_type2>, return_type3>, return_type4> * ptr){ throw; // return new FieldCompute(*ptr,func); return NULL; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: ComputeFunctorInterface & func; + }; /* -------------------------------------------------------------------------- */ /// for connection to a FieldCompute template inline Field * FieldCompute ::connect(FieldComputeProxy & proxy){ return proxy.connectToField(this); } /* -------------------------------------------------------------------------- */ __END_AKANTU_DUMPER__ __END_AKANTU__ #endif /* __AKANTU_DUMPER_COMPUTE_HH__ */ diff --git a/src/mesh/group_manager.hh b/src/mesh/group_manager.hh index 912ae8f18..c93556bf9 100644 --- a/src/mesh/group_manager.hh +++ b/src/mesh/group_manager.hh @@ -1,304 +1,304 @@ /** * @file group_manager.hh * * @author Guillaume Anciaux * @author Dana Christen * @author Nicolas Richart * @author David Simon Kammer * * @date creation: Fri May 03 2013 * @date last modification: Fri Sep 05 2014 * * @brief Stores information relevent to the notion of element and nodes groups. * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_GROUP_MANAGER_HH__ #define __AKANTU_GROUP_MANAGER_HH__ #include #include "aka_common.hh" #include "element_type_map.hh" //#include "dumpable.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ class FEM; class ElementGroup; class NodeGroup; class Mesh; class Element; class DistributedSynchronizer; template class CommunicationBufferTemplated; namespace dumper { class Field; } /* -------------------------------------------------------------------------- */ class GroupManager { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ private: typedef std::map ElementGroups; typedef std::map NodeGroups; public: typedef std::set GroupManagerTypeSet; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: GroupManager(const Mesh & mesh, const ID & id = "group_manager", const MemoryID & memory_id = 0); virtual ~GroupManager(); /* ------------------------------------------------------------------------ */ /* Groups iterators */ /* ------------------------------------------------------------------------ */ public: typedef NodeGroups::iterator node_group_iterator; typedef ElementGroups::iterator element_group_iterator; typedef NodeGroups::const_iterator const_node_group_iterator; typedef ElementGroups::const_iterator const_element_group_iterator; #ifndef SWIG #define AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(group_type, \ function, \ param_in, \ param_out) \ inline BOOST_PP_CAT(BOOST_PP_CAT(const_, group_type), _iterator) \ BOOST_PP_CAT(BOOST_PP_CAT(group_type, _), function)(param_in) const { \ return BOOST_PP_CAT(group_type, s).function(param_out); \ }; \ \ inline BOOST_PP_CAT(group_type, _iterator) \ BOOST_PP_CAT(BOOST_PP_CAT(group_type, _), function)(param_in) { \ return BOOST_PP_CAT(group_type, s).function(param_out); \ } #define AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(group_type, function) \ AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(group_type, function, BOOST_PP_EMPTY(), BOOST_PP_EMPTY()) AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(node_group, begin); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(node_group, end ); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(element_group, begin); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION_NP(element_group, end ); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(element_group, find, const std::string & name, name); AKANTU_GROUP_MANAGER_DEFINE_ITERATOR_FUNCTION(node_group, find, const std::string & name, name); #endif /* ------------------------------------------------------------------------ */ /* Clustering filter */ /* ------------------------------------------------------------------------ */ public: class ClusteringFilter { public: virtual bool operator() (const Element &) const { return true; } }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// create an empty node group NodeGroup & createNodeGroup(const std::string & group_name, bool replace_group = false); /// create a node group from another node group but filtered template NodeGroup & createFilteredNodeGroup(const std::string & group_name, const NodeGroup & node_group, T & filter); /// destroy a node group void destroyNodeGroup(const std::string & group_name); /// create an element group and the associated node group ElementGroup & createElementGroup(const std::string & group_name, UInt dimension = _all_dimensions, bool replace_group = false); /// create an element group from another element group but filtered template ElementGroup & createFilteredElementGroup(const std::string & group_name, UInt dimension, const NodeGroup & node_group, T & filter); /// destroy an element group and the associated node group void destroyElementGroup(const std::string & group_name, bool destroy_node_group = false); /// destroy all element groups and the associated node groups void destroyAllElementGroups(bool destroy_node_groups = false); /// create a element group using an existing node group ElementGroup & createElementGroup(const std::string & group_name, UInt dimension, NodeGroup & node_group); /// create groups based on values stored in a given mesh data template void createGroupsFromMeshData(const std::string & dataset_name); /// create boundaries group by a clustering algorithm \todo extend to parallel UInt createBoundaryGroupFromGeometry(); /// create element clusters for a given dimension UInt createClusters(UInt element_dimension, std::string cluster_name_prefix = "cluster", const ClusteringFilter & filter = ClusteringFilter(), DistributedSynchronizer * distributed_synchronizer = NULL, Mesh * mesh_facets = NULL); /// Create an ElementGroup based on a NodeGroup void createElementGroupFromNodeGroup(const std::string & name, const std::string & node_group, UInt dimension = _all_dimensions); virtual void printself(std::ostream & stream, int indent = 0) const; /// this function insure that the group names are present on all processors /// /!\ it is a SMP call void synchronizeGroupNames(); /// register an elemental field to the given group name (overloading for ElementalPartionField) #ifndef SWIG template class dump_type> inline dumper::Field * createElementalField(const ElementTypeMapArray & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap nb_data_per_elem = ElementTypeMap()); /// register an elemental field to the given group name (overloading for ElementalField) template class ret_type, template class,bool> class dump_type> inline dumper::Field * createElementalField(const ElementTypeMapArray & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap nb_data_per_elem = ElementTypeMap()); /// register an elemental field to the given group name (overloading for MaterialInternalField) template class dump_type> + template class dump_type> inline dumper::Field * createElementalField(const ElementTypeMapArray & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap nb_data_per_elem); template class ftype> inline dumper::Field * createNodalField(const ftype * field, const std::string & group_name, UInt padding_size = 0); template class ftype> inline dumper::Field * createStridedNodalField(const ftype * field, const std::string & group_name, UInt size, UInt stride, UInt padding_size); protected: /// fill a buffer with all the group names void fillBufferWithGroupNames(CommunicationBufferTemplated & comm_buffer) const; /// take a buffer and create the missing groups localy void checkAndAddGroups(CommunicationBufferTemplated & buffer); /// register an elemental field to the given group name template inline dumper::Field * createElementalField(const field_type & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap nb_data_per_elem); /// register an elemental field to the given group name template inline dumper::Field * createElementalFilteredField(const field_type & field, const std::string & group_name, UInt spatial_dimension, const ElementKind & kind, ElementTypeMap nb_data_per_elem); #endif /* ------------------------------------------------------------------------ */ /* Accessor */ /* ------------------------------------------------------------------------ */ public: const ElementGroup & getElementGroup(const std::string & name) const; const NodeGroup & getNodeGroup(const std::string & name) const; ElementGroup & getElementGroup(const std::string & name); NodeGroup & getNodeGroup(const std::string & name); UInt getNbElementGroups(UInt dimension = _all_dimensions) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id to create element and node groups ID id; /// memory_id to create element and node groups MemoryID memory_id; /// list of the node groups managed NodeGroups node_groups; /// list of the element groups managed ElementGroups element_groups; /// Mesh to which the element belongs const Mesh & mesh; }; /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const GroupManager & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_GROUP_MANAGER_HH__ */ diff --git a/src/mesh_utils/mesh_utils.cc b/src/mesh_utils/mesh_utils.cc index 3900669ec..9528921d7 100644 --- a/src/mesh_utils/mesh_utils.cc +++ b/src/mesh_utils/mesh_utils.cc @@ -1,2196 +1,2204 @@ /** * @file mesh_utils.cc * * @author Guillaume Anciaux * @author Leonardo Snozzi * @author Marco Vocialta * @author Dana Christen * @author David Simon Kammer * @author Nicolas Richart * * @date creation: Fri Aug 20 2010 * @date last modification: Mon Jun 09 2014 * * @brief All mesh utils necessary for various tasks * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "mesh_utils.hh" #include "aka_safe_enum.hh" #include "fe_engine.hh" /* -------------------------------------------------------------------------- */ #include #include #include #include /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2Elements(const Mesh & mesh, CSR & node_to_elem, UInt spatial_dimension) { AKANTU_DEBUG_IN(); if (spatial_dimension == _all_dimensions) spatial_dimension = mesh.getSpatialDimension(); /// count number of occurrence of each node UInt nb_nodes = mesh.getNbNodes(); /// array for the node-element list node_to_elem.resizeRows(nb_nodes); node_to_elem.clearRows(); AKANTU_DEBUG_ASSERT(mesh.firstType(spatial_dimension) != mesh.lastType(spatial_dimension), "Some elements must be found in right dimension to compute facets!"); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { Mesh::type_iterator first = mesh.firstType(spatial_dimension, *gt, _ek_not_defined); Mesh::type_iterator last = mesh.lastType(spatial_dimension, *gt, _ek_not_defined); for (; first != last; ++first) { ElementType type = *first; UInt nb_element = mesh.getNbElement(type, *gt); Array::const_iterator< Vector > conn_it = mesh.getConnectivity(type, *gt).begin(Mesh::getNbNodesPerElement(type)); for (UInt el = 0; el < nb_element; ++el, ++conn_it) for (UInt n = 0; n < conn_it->size(); ++n) ++node_to_elem.rowOffset((*conn_it)(n)); } } node_to_elem.countToCSR(); node_to_elem.resizeCols(); /// rearrange element to get the node-element list Element e; node_to_elem.beginInsertions(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { Mesh::type_iterator first = mesh.firstType(spatial_dimension, *gt, _ek_not_defined); Mesh::type_iterator last = mesh.lastType(spatial_dimension, *gt, _ek_not_defined); e.ghost_type = *gt; for (; first != last; ++first) { ElementType type = *first; e.type = type; e.kind = Mesh::getKind(type); UInt nb_element = mesh.getNbElement(type, *gt); Array::const_iterator< Vector > conn_it = mesh.getConnectivity(type, *gt).begin(Mesh::getNbNodesPerElement(type)); for (UInt el = 0; el < nb_element; ++el, ++conn_it) { e.element = el; for (UInt n = 0; n < conn_it->size(); ++n) node_to_elem.insertInRow((*conn_it)(n), e); } } } node_to_elem.endInsertions(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * This function should disappear in the future (used in mesh partitioning) */ void MeshUtils::buildNode2Elements(const Mesh & mesh, CSR & node_to_elem, UInt spatial_dimension) { AKANTU_DEBUG_IN(); if (spatial_dimension == _all_dimensions) spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes = mesh.getNbNodes(); const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt nb_types = type_list.size(); UInt nb_good_types = 0; UInt nb_nodes_per_element[nb_types]; UInt * conn_val[nb_types]; UInt nb_element[nb_types]; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; nb_nodes_per_element[nb_good_types] = Mesh::getNbNodesPerElement(type); conn_val[nb_good_types] = mesh.getConnectivity(type, _not_ghost).storage(); nb_element[nb_good_types] = mesh.getConnectivity(type, _not_ghost).getSize(); nb_good_types++; } AKANTU_DEBUG_ASSERT(nb_good_types != 0, "Some elements must be found in right dimension to compute facets!"); /// array for the node-element list node_to_elem.resizeRows(nb_nodes); node_to_elem.clearRows(); /// count number of occurrence of each node for (UInt t = 0; t < nb_good_types; ++t) { for (UInt el = 0; el < nb_element[t]; ++el) { UInt el_offset = el*nb_nodes_per_element[t]; for (UInt n = 0; n < nb_nodes_per_element[t]; ++n) { ++node_to_elem.rowOffset(conn_val[t][el_offset + n]); } } } node_to_elem.countToCSR(); node_to_elem.resizeCols(); node_to_elem.beginInsertions(); /// rearrange element to get the node-element list for (UInt t = 0, linearized_el = 0; t < nb_good_types; ++t) for (UInt el = 0; el < nb_element[t]; ++el, ++linearized_el) { UInt el_offset = el*nb_nodes_per_element[t]; for (UInt n = 0; n < nb_nodes_per_element[t]; ++n) node_to_elem.insertInRow(conn_val[t][el_offset + n], linearized_el); } node_to_elem.endInsertions(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2ElementsElementTypeMap(const Mesh & mesh, CSR & node_to_elem, const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_elements = mesh.getConnectivity(type, ghost_type).getSize(); UInt * conn_val = mesh.getConnectivity(type, ghost_type).storage(); /// array for the node-element list node_to_elem.resizeRows(nb_nodes); node_to_elem.clearRows(); /// count number of occurrence of each node for (UInt el = 0; el < nb_elements; ++el) { UInt el_offset = el*nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) ++node_to_elem.rowOffset(conn_val[el_offset + n]); } /// convert the occurrence array in a csr one node_to_elem.countToCSR(); node_to_elem.resizeCols(); node_to_elem.beginInsertions(); /// save the element index in the node-element list for (UInt el = 0; el < nb_elements; ++el) { UInt el_offset = el*nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { node_to_elem.insertInRow(conn_val[el_offset + n], el); } } node_to_elem.endInsertions(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildFacets(Mesh & mesh){ AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh.lastType(spatial_dimension - 1, gt_facet); for(; it != end; ++it) { mesh.getConnectivity(*it, *gt).resize(0); // \todo inform the mesh event handler } } buildFacetsDimension(mesh, mesh, true, spatial_dimension); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildAllFacets(const Mesh & mesh, Mesh & mesh_facets, UInt to_dimension, DistributedSynchronizer * synchronizer) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); buildAllFacets(mesh, mesh_facets, spatial_dimension, to_dimension, synchronizer); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildAllFacets(const Mesh & mesh, Mesh & mesh_facets, UInt from_dimension, UInt to_dimension, DistributedSynchronizer * synchronizer) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(mesh_facets.isMeshFacets(), "The mesh_facets should be initialized with initMeshFacets"); const ElementTypeMapArray * prank_to_element = NULL; if (synchronizer) { synchronizer->buildPrankToElement(); prank_to_element = &synchronizer->getPrankToElement(); } /// generate facets buildFacetsDimension(mesh, mesh_facets, false, from_dimension, prank_to_element); /// copy nodes type mesh_facets.nodes_type.resize(mesh.nodes_type.getSize()); mesh_facets.nodes_type.copy(mesh.nodes_type); /// sort facets and generate subfacets for (UInt i = from_dimension - 1; i > to_dimension; --i) { buildFacetsDimension(mesh_facets, mesh_facets, false, i, prank_to_element); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildFacetsDimension(const Mesh & mesh, Mesh & mesh_facets, bool boundary_only, UInt dimension, const ElementTypeMapArray * prank_to_element){ AKANTU_DEBUG_IN(); // save the current parent of mesh_facets and set it temporarly to mesh since // mesh is the one containing the elements for which mesh_facets has the subelements // example: if the function is called with mesh = mesh_facets const Mesh & mesh_facets_parent = mesh_facets.getMeshParent(); mesh_facets.defineMeshParent(mesh); UInt spatial_dimension = mesh.getSpatialDimension(); const Array & mesh_facets_nodes = mesh_facets.getNodes(); const Array::const_vector_iterator mesh_facets_nodes_it = mesh_facets_nodes.begin(spatial_dimension); CSR node_to_elem; buildNode2Elements(mesh, node_to_elem, dimension); Array counter; std::vector connected_elements; // init the SubelementToElement data to improve performance for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator first = mesh.firstType(dimension, ghost_type); Mesh::type_iterator last = mesh.lastType(dimension, ghost_type); for(; first != last; ++first) { ElementType type = *first; mesh_facets.getSubelementToElementPointer(type, ghost_type); Vector facet_types = mesh.getAllFacetTypes(type); for (UInt ft = 0; ft < facet_types.size(); ++ft) { ElementType facet_type = facet_types(ft); mesh_facets.getElementToSubelementPointer(facet_type, ghost_type); mesh_facets.getConnectivityPointer(facet_type, ghost_type); } } } Element current_element; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; GhostType facet_ghost_type = ghost_type; current_element.ghost_type = ghost_type; Mesh::type_iterator first = mesh.firstType(dimension, ghost_type); Mesh::type_iterator last = mesh.lastType(dimension, ghost_type); for(; first != last; ++first) { ElementType type = *first; Vector facet_types = mesh.getAllFacetTypes(type); current_element.type = type; for (UInt ft = 0; ft < facet_types.size(); ++ft) { ElementType facet_type = facet_types(ft); UInt nb_element = mesh.getNbElement(type, ghost_type); Array< std::vector > * element_to_subelement = &mesh_facets.getElementToSubelement(facet_type, ghost_type); Array * connectivity_facets = &mesh_facets.getConnectivity(facet_type, ghost_type); UInt nb_facet_per_element = mesh.getNbFacetsPerElement(type, ft); const Array & element_connectivity = mesh.getConnectivity(type, ghost_type); const Matrix facet_local_connectivity = mesh.getFacetLocalConnectivity(type, ft); UInt nb_nodes_per_facet = connectivity_facets->getNbComponent(); Vector facet(nb_nodes_per_facet); for (UInt el = 0; el < nb_element; ++el) { current_element.element = el; for (UInt f = 0; f < nb_facet_per_element; ++f) { for (UInt n = 0; n < nb_nodes_per_facet; ++n) facet(n) = element_connectivity(el, facet_local_connectivity(f, n)); UInt first_node_nb_elements = node_to_elem.getNbCols(facet(0)); counter.resize(first_node_nb_elements); counter.clear(); //loop over the other nodes to search intersecting elements, //which are the elements that share another node with the //starting element after first_node CSR::iterator first_node_elements = node_to_elem.begin(facet(0)); CSR::iterator first_node_elements_end = node_to_elem.end(facet(0)); UInt local_el = 0; for (; first_node_elements != first_node_elements_end; ++first_node_elements, ++local_el) { for (UInt n = 1; n < nb_nodes_per_facet; ++n) { CSR::iterator node_elements_begin = node_to_elem.begin(facet(n)); CSR::iterator node_elements_end = node_to_elem.end (facet(n)); counter(local_el) += std::count(node_elements_begin, node_elements_end, *first_node_elements); } } // counting the number of elements connected to the facets and // taking the minimum element number, because the facet should // be inserted just once UInt nb_element_connected_to_facet = 0; Element minimum_el = ElementNull; connected_elements.clear(); for (UInt el_f = 0; el_f < first_node_nb_elements; el_f++) { Element real_el = node_to_elem(facet(0), el_f); if (counter(el_f) == nb_nodes_per_facet - 1) { ++nb_element_connected_to_facet; minimum_el = std::min(minimum_el, real_el); connected_elements.push_back(real_el); } } if (minimum_el == current_element) { bool full_ghost_facet = false; UInt n = 0; while (n < nb_nodes_per_facet && mesh.isPureGhostNode(facet(n))) ++n; if (n == nb_nodes_per_facet) full_ghost_facet = true; if (!full_ghost_facet) { if (!boundary_only || (boundary_only && nb_element_connected_to_facet == 1)) { std::vector elements; // build elements_on_facets: linearized_el must come first // in order to store the facet in the correct direction // and avoid to invert the sign in the normal computation elements.push_back(current_element); /// boundary facet if (nb_element_connected_to_facet == 1) elements.push_back(ElementNull); /// internal facet else if (nb_element_connected_to_facet == 2) { elements.push_back(connected_elements[1]); /// check if facet is in between ghost and normal /// elements: if it's the case, the facet is either /// ghost or not ghost. The criterion to decide this /// is arbitrary. It was chosen to check the processor /// id (prank) of the two neighboring elements. If /// prank of the ghost element is lower than prank of /// the normal one, the facet is not ghost, otherwise /// it's ghost GhostType gt[2] = { _not_ghost, _not_ghost }; for (UInt el = 0; el < connected_elements.size(); ++el) gt[el] = connected_elements[el].ghost_type; if (gt[0] + gt[1] == 1) { if (prank_to_element) { UInt prank[2]; for (UInt el = 0; el < 2; ++el) { UInt current_el = connected_elements[el].element; ElementType current_type = connected_elements[el].type; GhostType current_gt = connected_elements[el].ghost_type; const Array & prank_to_el = (*prank_to_element)(current_type, current_gt); prank[el] = prank_to_el(current_el); } bool ghost_one = (gt[0] != _ghost); if (prank[ghost_one] > prank[!ghost_one]) facet_ghost_type = _not_ghost; else facet_ghost_type = _ghost; connectivity_facets = &mesh_facets.getConnectivity(facet_type, facet_ghost_type); element_to_subelement = &mesh_facets.getElementToSubelement(facet_type, facet_ghost_type); } } } /// facet of facet else { for (UInt i = 1; i < nb_element_connected_to_facet; ++i) { elements.push_back(connected_elements[i]); } } element_to_subelement->push_back(elements); connectivity_facets->push_back(facet); /// current facet index UInt current_facet = connectivity_facets->getSize() - 1; /// loop on every element connected to current facet and /// insert current facet in the first free spot of the /// subelement_to_element vector for (UInt elem = 0; elem < elements.size(); ++elem) { Element loc_el = elements[elem]; if (loc_el.type != _not_defined) { Array & subelement_to_element = mesh_facets.getSubelementToElement(loc_el.type, loc_el.ghost_type); UInt nb_facet_per_loc_element = subelement_to_element.getNbComponent(); for (UInt f_in = 0; f_in < nb_facet_per_loc_element; ++f_in) { if (subelement_to_element(loc_el.element, f_in).type == _not_defined) { subelement_to_element(loc_el.element, f_in).type = facet_type; subelement_to_element(loc_el.element, f_in).element = current_facet; subelement_to_element(loc_el.element, f_in).ghost_type = facet_ghost_type; break; } } } } /// reset connectivity in case a facet was found in /// between ghost and normal elements if (facet_ghost_type != ghost_type) { facet_ghost_type = ghost_type; connectivity_facets = mesh_facets.getConnectivityPointer(facet_type, facet_ghost_type); element_to_subelement = mesh_facets.getElementToSubelementPointer(facet_type, facet_ghost_type); } } } } } } } } } // restore the parent of mesh_facet mesh_facets.defineMeshParent(mesh_facets_parent); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::renumberMeshNodes(Mesh & mesh, UInt * local_connectivities, UInt nb_local_element, UInt nb_ghost_element, ElementType type, Array & old_nodes_numbers) { AKANTU_DEBUG_IN(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); std::map renumbering_map; for (UInt i = 0; i < old_nodes_numbers.getSize(); ++i) { renumbering_map[old_nodes_numbers(i)] = i; } /// renumber the nodes renumberNodesInConnectivity(local_connectivities, (nb_local_element + nb_ghost_element)*nb_nodes_per_element, renumbering_map); std::map::iterator it = renumbering_map.begin(); std::map::iterator end = renumbering_map.end(); old_nodes_numbers.resize(renumbering_map.size()); for (;it != end; ++it) { old_nodes_numbers(it->second) = it->first; } renumbering_map.clear(); /// copy the renumbered connectivity to the right place Array * local_conn = mesh.getConnectivityPointer(type); local_conn->resize(nb_local_element); memcpy(local_conn->storage(), local_connectivities, nb_local_element * nb_nodes_per_element * sizeof(UInt)); Array * ghost_conn = mesh.getConnectivityPointer(type, _ghost); ghost_conn->resize(nb_ghost_element); memcpy(ghost_conn->storage(), local_connectivities + nb_local_element * nb_nodes_per_element, nb_ghost_element * nb_nodes_per_element * sizeof(UInt)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::renumberNodesInConnectivity(UInt * list_nodes, UInt nb_nodes, std::map & renumbering_map) { AKANTU_DEBUG_IN(); UInt * connectivity = list_nodes; UInt new_node_num = renumbering_map.size(); for (UInt n = 0; n < nb_nodes; ++n, ++connectivity) { UInt & node = *connectivity; std::map::iterator it = renumbering_map.find(node); if(it == renumbering_map.end()) { UInt old_node = node; renumbering_map[old_node] = new_node_num; node = new_node_num; ++new_node_num; } else { node = it->second; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::purifyMesh(Mesh & mesh) { AKANTU_DEBUG_IN(); std::map renumbering_map; RemovedNodesEvent remove_nodes(mesh); Array & nodes_removed = remove_nodes.getList(); for (UInt gt = _not_ghost; gt <= _ghost; ++gt) { GhostType ghost_type = (GhostType) gt; Mesh::type_iterator it = mesh.firstType(_all_dimensions, ghost_type, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(_all_dimensions, ghost_type, _ek_not_defined); for(; it != end; ++it) { ElementType type(*it); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); const Array & connectivity_vect = mesh.getConnectivity(type, ghost_type); UInt nb_element(connectivity_vect.getSize()); UInt * connectivity = connectivity_vect.storage(); renumberNodesInConnectivity (connectivity, nb_element*nb_nodes_per_element, renumbering_map); } } Array & new_numbering = remove_nodes.getNewNumbering(); std::fill(new_numbering.begin(), new_numbering.end(), UInt(-1)); std::map::iterator it = renumbering_map.begin(); std::map::iterator end = renumbering_map.end(); for (; it != end; ++it) { new_numbering(it->first) = it->second; } for (UInt i = 0; i < new_numbering.getSize(); ++i) { if(new_numbering(i) == UInt(-1)) nodes_removed.push_back(i); } mesh.sendEvent(remove_nodes); AKANTU_DEBUG_OUT(); } #if defined(AKANTU_COHESIVE_ELEMENT) /* -------------------------------------------------------------------------- */ UInt MeshUtils::insertCohesiveElements(Mesh & mesh, Mesh & mesh_facets, const ElementTypeMapArray & facet_insertion, Array & doubled_nodes, Array & new_elements, bool only_double_facets) { UInt spatial_dimension = mesh.getSpatialDimension(); UInt elements_to_insert = updateFacetToDouble(mesh_facets, facet_insertion); if (elements_to_insert > 0) { if (spatial_dimension == 1) { doublePointFacet(mesh, mesh_facets, doubled_nodes); } else { doubleFacet(mesh, mesh_facets, spatial_dimension - 1, doubled_nodes, true); findSubfacetToDouble(mesh, mesh_facets); if (spatial_dimension == 2) { doubleSubfacet<2>(mesh, mesh_facets, doubled_nodes); } else if (spatial_dimension == 3) { doubleFacet(mesh, mesh_facets, 1, doubled_nodes, false); findSubfacetToDouble(mesh, mesh_facets); doubleSubfacet<3>(mesh, mesh_facets, doubled_nodes); } } if (!only_double_facets) updateCohesiveData(mesh, mesh_facets, new_elements); } return elements_to_insert; } #endif /* -------------------------------------------------------------------------- */ void MeshUtils::doubleNodes(Mesh & mesh, const std::vector & old_nodes, Array & doubled_nodes) { AKANTU_DEBUG_IN(); Array & position = mesh.getNodes(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt old_nb_nodes = position.getSize(); UInt new_nb_nodes = old_nb_nodes + old_nodes.size(); UInt old_nb_doubled_nodes = doubled_nodes.getSize(); UInt new_nb_doubled_nodes = old_nb_doubled_nodes + old_nodes.size(); position.resize(new_nb_nodes); doubled_nodes.resize(new_nb_doubled_nodes); Array::iterator > position_begin = position.begin(spatial_dimension); for (UInt n = 0; n < old_nodes.size(); ++n) { UInt new_node = old_nb_nodes + n; /// store doubled nodes doubled_nodes(old_nb_doubled_nodes + n, 0) = old_nodes[n]; doubled_nodes(old_nb_doubled_nodes + n, 1) = new_node; /// update position std::copy(position_begin + old_nodes[n], position_begin + old_nodes[n] + 1, position_begin + new_node); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::doubleFacet(Mesh & mesh, Mesh & mesh_facets, UInt facet_dimension, Array & doubled_nodes, bool facet_mode) { AKANTU_DEBUG_IN(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(facet_dimension, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(facet_dimension, gt_facet); for(; it != end; ++it) { ElementType type_facet = *it; Array & f_to_double = mesh_facets.getData("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); if (nb_facet_to_double == 0) continue; ElementType type_subfacet = Mesh::getFacetType(type_facet); const UInt nb_subfacet_per_facet = Mesh::getNbFacetsPerElement(type_facet); GhostType gt_subfacet = _casper; Array > * f_to_subfacet = NULL; Array & subfacet_to_facet = mesh_facets.getSubelementToElement(type_facet, gt_facet); Array & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); UInt nb_nodes_per_facet = conn_facet.getNbComponent(); UInt old_nb_facet = conn_facet.getSize(); UInt new_nb_facet = old_nb_facet + nb_facet_to_double; conn_facet.resize(new_nb_facet); subfacet_to_facet.resize(new_nb_facet); UInt new_facet = old_nb_facet - 1; Element new_facet_el(type_facet, 0, gt_facet); Array::iterator > subfacet_to_facet_begin = subfacet_to_facet.begin(nb_subfacet_per_facet); Array::iterator > conn_facet_begin = conn_facet.begin(nb_nodes_per_facet); for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { UInt old_facet = f_to_double(facet); ++new_facet; /// adding a new facet by copying original one /// copy connectivity in new facet std::copy(conn_facet_begin + old_facet, conn_facet_begin + old_facet + 1, conn_facet_begin + new_facet); /// update subfacet_to_facet std::copy(subfacet_to_facet_begin + old_facet, subfacet_to_facet_begin + old_facet + 1, subfacet_to_facet_begin + new_facet); new_facet_el.element = new_facet; /// loop on every subfacet for (UInt sf = 0; sf < nb_subfacet_per_facet; ++sf) { Element & subfacet = subfacet_to_facet(old_facet, sf); if (subfacet == ElementNull) continue; if (gt_subfacet != subfacet.ghost_type) { gt_subfacet = subfacet.ghost_type; f_to_subfacet = & mesh_facets.getElementToSubelement(type_subfacet, subfacet.ghost_type); } /// update facet_to_subfacet array (*f_to_subfacet)(subfacet.element).push_back(new_facet_el); } } /// update facet_to_subfacet and _segment_3 facets if any if (!facet_mode) { updateSubfacetToFacet(mesh_facets, type_facet, gt_facet, true); updateFacetToSubfacet(mesh_facets, type_facet, gt_facet, true); updateQuadraticSegments(mesh, mesh_facets, type_facet, gt_facet, doubled_nodes); } else updateQuadraticSegments(mesh, mesh_facets, type_facet, gt_facet, doubled_nodes); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ UInt MeshUtils::updateFacetToDouble(Mesh & mesh_facets, const ElementTypeMapArray & facet_insertion) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh_facets.getSpatialDimension(); UInt nb_facets_to_double = 0.; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); for(; it != end; ++it) { ElementType type_facet = *it; const Array & f_insertion = facet_insertion(type_facet, gt_facet); Array & f_to_double = mesh_facets.getData("facet_to_double", type_facet, gt_facet); Array< std::vector > & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); ElementType el_type = _not_defined; GhostType el_gt = _casper; UInt nb_facet_per_element = 0; Element old_facet_el(type_facet, 0, gt_facet); Array * facet_to_element = NULL; for (UInt f = 0; f < f_insertion.getSize(); ++f) { if (f_insertion(f) == false) continue; ++nb_facets_to_double; if (element_to_facet(f)[1].type == _not_defined #if defined(AKANTU_COHESIVE_ELEMENT) || element_to_facet(f)[1].kind == _ek_cohesive #endif ) { AKANTU_DEBUG_WARNING("attempt to double a facet on the boundary"); continue; } f_to_double.push_back(f); UInt new_facet = mesh_facets.getNbElement(type_facet, gt_facet) + f_to_double.getSize() - 1; old_facet_el.element = f; /// update facet_to_element vector Element & elem_to_update = element_to_facet(f)[1]; UInt el = elem_to_update.element; if (elem_to_update.ghost_type != el_gt || elem_to_update.type != el_type) { el_type = elem_to_update.type; el_gt = elem_to_update.ghost_type; facet_to_element = & mesh_facets.getSubelementToElement(el_type, el_gt); nb_facet_per_element = facet_to_element->getNbComponent(); } Element * f_update = std::find(facet_to_element->storage() + el * nb_facet_per_element, facet_to_element->storage() + el * nb_facet_per_element + nb_facet_per_element, old_facet_el); AKANTU_DEBUG_ASSERT(facet_to_element->storage() + el * nb_facet_per_element != facet_to_element->storage() + el * nb_facet_per_element + nb_facet_per_element, "Facet not found"); f_update->element = new_facet; /// update elements connected to facet std::vector first_facet_list = element_to_facet(f); element_to_facet.push_back(first_facet_list); /// set new and original facets as boundary facets element_to_facet(new_facet)[0] = element_to_facet(new_facet)[1]; element_to_facet(f)[1] = ElementNull; element_to_facet(new_facet)[1] = ElementNull; } } } AKANTU_DEBUG_OUT(); return nb_facets_to_double; } /* -------------------------------------------------------------------------- */ void MeshUtils::resetFacetToDouble(Mesh & mesh_facets) { AKANTU_DEBUG_IN(); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; Mesh::type_iterator it = mesh_facets.firstType(_all_dimensions, gt); Mesh::type_iterator end = mesh_facets.lastType(_all_dimensions, gt); for(; it != end; ++it) { ElementType type = *it; mesh_facets.getDataPointer("facet_to_double", type, gt, 1, false); mesh_facets.getDataPointer > ("facets_to_subfacet_double", type, gt, 1, false); mesh_facets.getDataPointer > ("elements_to_subfacet_double", type, gt, 1, false); mesh_facets.getDataPointer > ("subfacets_to_subsubfacet_double", type, gt, 1, false); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MeshUtils::findSubfacetToDouble(Mesh & mesh, Mesh & mesh_facets) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh_facets.getSpatialDimension(); if (spatial_dimension == 1) return; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); for(; it != end; ++it) { ElementType type_facet = *it; Array & f_to_double = mesh_facets.getData("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); if (nb_facet_to_double == 0) continue; ElementType type_subfacet = Mesh::getFacetType(type_facet); GhostType gt_subfacet = _casper; ElementType type_subsubfacet = Mesh::getFacetType(type_subfacet); GhostType gt_subsubfacet = _casper; Array * conn_subfacet = NULL; Array * sf_to_double = NULL; Array > * sf_to_subfacet_double = NULL; Array > * f_to_subfacet_double = NULL; Array > * el_to_subfacet_double = NULL; UInt nb_subfacet = Mesh::getNbFacetsPerElement(type_facet); UInt nb_subsubfacet; UInt nb_nodes_per_sf_el; if (subsubfacet_mode) { nb_nodes_per_sf_el = Mesh::getNbNodesPerElement(type_subsubfacet); nb_subsubfacet = Mesh::getNbFacetsPerElement(type_subfacet); } else nb_nodes_per_sf_el = Mesh::getNbNodesPerElement(type_subfacet); Array & subfacet_to_facet = mesh_facets.getSubelementToElement(type_facet, gt_facet); Array< std::vector > & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); Array * subsubfacet_to_subfacet = NULL; UInt old_nb_facet = subfacet_to_facet.getSize() - nb_facet_to_double; Element current_facet(type_facet, 0, gt_facet); std::vector element_list; std::vector facet_list; std::vector * subfacet_list; if (subsubfacet_mode) subfacet_list = new std::vector; /// map to filter subfacets Array< std::vector > * facet_to_subfacet = NULL; /// this is used to make sure that both new and old facets are /// checked UInt facets[2]; /// loop on every facet for (UInt f_index = 0; f_index < 2; ++f_index) { for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { facets[bool(f_index)] = f_to_double(facet); facets[!bool(f_index)] = old_nb_facet + facet; UInt old_facet = facets[0]; UInt new_facet = facets[1]; Element & starting_element = element_to_facet(new_facet)[0]; current_facet.element = old_facet; /// loop on every subfacet for (UInt sf = 0; sf < nb_subfacet; ++sf) { Element & subfacet = subfacet_to_facet(old_facet, sf); if (subfacet == ElementNull) continue; if (gt_subfacet != subfacet.ghost_type) { gt_subfacet = subfacet.ghost_type; if (subsubfacet_mode) { subsubfacet_to_subfacet = & mesh_facets.getSubelementToElement(type_subfacet, gt_subfacet); } else { conn_subfacet = & mesh_facets.getConnectivity(type_subfacet, gt_subfacet); sf_to_double = & mesh_facets.getData("facet_to_double", type_subfacet, gt_subfacet); f_to_subfacet_double = & mesh_facets.getData >("facets_to_subfacet_double", type_subfacet, gt_subfacet); el_to_subfacet_double = & mesh_facets.getData >("elements_to_subfacet_double", type_subfacet, gt_subfacet); facet_to_subfacet = & mesh_facets.getElementToSubelement(type_subfacet, gt_subfacet); } } if (subsubfacet_mode) { /// loop on every subsubfacet for (UInt ssf = 0; ssf < nb_subsubfacet; ++ssf) { Element & subsubfacet = (*subsubfacet_to_subfacet)(subfacet.element, ssf); if (subsubfacet == ElementNull) continue; if (gt_subsubfacet != subsubfacet.ghost_type) { gt_subsubfacet = subsubfacet.ghost_type; conn_subfacet = & mesh_facets.getConnectivity(type_subsubfacet, gt_subsubfacet); sf_to_double = & mesh_facets.getData("facet_to_double", type_subsubfacet, gt_subsubfacet); sf_to_subfacet_double = & mesh_facets.getData >("subfacets_to_subsubfacet_double", type_subsubfacet, gt_subsubfacet); f_to_subfacet_double = & mesh_facets.getData >("facets_to_subfacet_double", type_subsubfacet, gt_subsubfacet); el_to_subfacet_double = & mesh_facets.getData >("elements_to_subfacet_double", type_subsubfacet, gt_subsubfacet); facet_to_subfacet = & mesh_facets.getElementToSubelement(type_subsubfacet, gt_subsubfacet); } UInt global_ssf = subsubfacet.element; Vector subsubfacet_connectivity(conn_subfacet->storage() + global_ssf * nb_nodes_per_sf_el, nb_nodes_per_sf_el); /// check if subsubfacet is to be doubled if (findElementsAroundSubfacet(mesh, mesh_facets, starting_element, current_facet, subsubfacet_connectivity, element_list, facet_list, subfacet_list) == false && removeElementsInVector(*subfacet_list, (*facet_to_subfacet)(global_ssf)) == false) { sf_to_double->push_back(global_ssf); sf_to_subfacet_double->push_back(*subfacet_list); f_to_subfacet_double->push_back(facet_list); el_to_subfacet_double->push_back(element_list); } } } else { const UInt global_sf = subfacet.element; Vector subfacet_connectivity(conn_subfacet->storage() + global_sf * nb_nodes_per_sf_el, nb_nodes_per_sf_el); /// check if subfacet is to be doubled if (findElementsAroundSubfacet(mesh, mesh_facets, starting_element, current_facet, subfacet_connectivity, element_list, facet_list) == false && removeElementsInVector(facet_list, (*facet_to_subfacet)(global_sf)) == false) { sf_to_double->push_back(global_sf); f_to_subfacet_double->push_back(facet_list); el_to_subfacet_double->push_back(element_list); } } } } } if (subsubfacet_mode) delete subfacet_list; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ #if defined(AKANTU_COHESIVE_ELEMENT) void MeshUtils::updateCohesiveData(Mesh & mesh, Mesh & mesh_facets, Array & new_elements) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); bool third_dimension = spatial_dimension == 3; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); for(; it != end; ++it) { ElementType type_facet = *it; Array & f_to_double = mesh_facets.getData("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); if (nb_facet_to_double == 0) continue; ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet); Array * facet_to_coh_element = mesh_facets.getSubelementToElementPointer(type_cohesive, gt_facet); Array & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); Array * conn_cohesive = mesh.getConnectivityPointer(type_cohesive, gt_facet); UInt nb_nodes_per_facet = Mesh::getNbNodesPerElement(type_facet); Array< std::vector > & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); UInt old_nb_cohesive_elements = conn_cohesive->getSize(); UInt new_nb_cohesive_elements = conn_cohesive->getSize() + nb_facet_to_double; UInt old_nb_facet = element_to_facet.getSize() - nb_facet_to_double; facet_to_coh_element->resize(new_nb_cohesive_elements); conn_cohesive->resize(new_nb_cohesive_elements); UInt new_elements_old_size = new_elements.getSize(); new_elements.resize(new_elements_old_size + nb_facet_to_double); Element c_element(type_cohesive, 0, gt_facet, _ek_cohesive); Element f_element(type_facet, 0, gt_facet); UInt facets[2]; for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { /// (in 3D cohesive elements connectivity is inverted) facets[third_dimension] = f_to_double(facet); facets[!third_dimension] = old_nb_facet + facet; UInt cohesive_element = old_nb_cohesive_elements + facet; /// store doubled facets f_element.element = facets[0]; (*facet_to_coh_element)(cohesive_element, 0) = f_element; f_element.element = facets[1]; (*facet_to_coh_element)(cohesive_element, 1) = f_element; /// modify cohesive elements' connectivity for (UInt n = 0; n < nb_nodes_per_facet; ++n) { (*conn_cohesive)(cohesive_element, n) = conn_facet(facets[0], n); (*conn_cohesive)(cohesive_element, n + nb_nodes_per_facet) = conn_facet(facets[1], n); } /// update element_to_facet vectors c_element.element = cohesive_element; element_to_facet(facets[0])[1] = c_element; element_to_facet(facets[1])[1] = c_element; /// add cohesive element to the element event list new_elements(new_elements_old_size + facet) = c_element; } } } AKANTU_DEBUG_OUT(); } #endif /* -------------------------------------------------------------------------- */ void MeshUtils::doublePointFacet(Mesh & mesh, Mesh & mesh_facets, Array & doubled_nodes) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); if (spatial_dimension != 1) return; Array & position = mesh.getNodes(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_facet = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); for(; it != end; ++it) { ElementType type_facet = *it; Array & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); Array< std::vector > & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); const Array & f_to_double = mesh_facets.getData("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); UInt old_nb_facet = element_to_facet.getSize() - nb_facet_to_double; UInt new_nb_facet = element_to_facet.getSize(); UInt old_nb_nodes = position.getSize(); UInt new_nb_nodes = old_nb_nodes + nb_facet_to_double; position.resize(new_nb_nodes); conn_facet.resize(new_nb_facet); UInt old_nb_doubled_nodes = doubled_nodes.getSize(); doubled_nodes.resize(old_nb_doubled_nodes + nb_facet_to_double); for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { UInt old_facet = f_to_double(facet); UInt new_facet = old_nb_facet + facet; ElementType type = element_to_facet(new_facet)[0].type; UInt el = element_to_facet(new_facet)[0].element; GhostType gt = element_to_facet(new_facet)[0].ghost_type; UInt old_node = conn_facet(old_facet); UInt new_node = old_nb_nodes + facet; /// update position position(new_node) = position(old_node); conn_facet(new_facet) = new_node; Array & conn_segment = mesh.getConnectivity(type, gt); UInt nb_nodes_per_segment = conn_segment.getNbComponent(); /// update facet connectivity UInt i; for (i = 0; conn_segment(el, i) != old_node && i <= nb_nodes_per_segment; ++i); conn_segment(el, i) = new_node; doubled_nodes(old_nb_doubled_nodes + facet, 0) = old_node; doubled_nodes(old_nb_doubled_nodes + facet, 1) = new_node; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MeshUtils::updateQuadraticSegments(Mesh & mesh, Mesh & mesh_facets, ElementType type_facet, GhostType gt_facet, Array & doubled_nodes) { AKANTU_DEBUG_IN(); if (type_facet != _segment_3) return; Array & f_to_double = mesh_facets.getData("facet_to_double", type_facet, gt_facet); UInt nb_facet_to_double = f_to_double.getSize(); UInt old_nb_facet = mesh_facets.getNbElement(type_facet, gt_facet) - nb_facet_to_double; Array & conn_facet = mesh_facets.getConnectivity(type_facet, gt_facet); Array< std::vector > & element_to_facet = mesh_facets.getElementToSubelement(type_facet, gt_facet); /// this ones matter only for segments in 3D Array< std::vector > * el_to_subfacet_double = NULL; Array< std::vector > * f_to_subfacet_double = NULL; if (third_dim_segments) { el_to_subfacet_double = & mesh_facets.getData >("elements_to_subfacet_double", type_facet, gt_facet); f_to_subfacet_double = & mesh_facets.getData >("facets_to_subfacet_double", type_facet, gt_facet); } std::vector middle_nodes; for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { UInt old_facet = f_to_double(facet); UInt node = conn_facet(old_facet, 2); if (!mesh.isPureGhostNode(node)) middle_nodes.push_back(node); } UInt n = doubled_nodes.getSize(); doubleNodes(mesh, middle_nodes, doubled_nodes); for (UInt facet = 0; facet < nb_facet_to_double; ++facet) { UInt old_facet = f_to_double(facet); UInt old_node = conn_facet(old_facet, 2); if (mesh.isPureGhostNode(old_node)) continue; UInt new_node = doubled_nodes(n, 1); UInt new_facet = old_nb_facet + facet; conn_facet(new_facet, 2) = new_node; if (third_dim_segments) { updateElementalConnectivity(mesh_facets, old_node, new_node, element_to_facet(new_facet)); updateElementalConnectivity(mesh, old_node, new_node, (*el_to_subfacet_double)(facet), &(*f_to_subfacet_double)(facet)); } else { updateElementalConnectivity(mesh, old_node, new_node, element_to_facet(new_facet)); } ++n; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::updateSubfacetToFacet(Mesh & mesh_facets, ElementType type_subfacet, GhostType gt_subfacet, bool facet_mode) { AKANTU_DEBUG_IN(); Array & sf_to_double = mesh_facets.getData("facet_to_double", type_subfacet, gt_subfacet); UInt nb_subfacet_to_double = sf_to_double.getSize(); /// update subfacet_to_facet vector ElementType type_facet = _not_defined; GhostType gt_facet = _casper; Array * subfacet_to_facet = NULL; UInt nb_subfacet_per_facet = 0; UInt old_nb_subfacet = mesh_facets.getNbElement(type_subfacet, gt_subfacet) - nb_subfacet_to_double; Array > * facet_list = NULL; if (facet_mode) facet_list = & mesh_facets.getData >("facets_to_subfacet_double", type_subfacet, gt_subfacet); else facet_list = & mesh_facets.getData >("subfacets_to_subsubfacet_double", type_subfacet, gt_subfacet); Element old_subfacet_el(type_subfacet, 0, gt_subfacet); Element new_subfacet_el(type_subfacet, 0, gt_subfacet); for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) { old_subfacet_el.element = sf_to_double(sf); new_subfacet_el.element = old_nb_subfacet + sf; for (UInt f = 0; f < (*facet_list)(sf).size(); ++f) { Element & facet = (*facet_list)(sf)[f]; if (facet.type != type_facet || facet.ghost_type != gt_facet) { type_facet = facet.type; gt_facet = facet.ghost_type; subfacet_to_facet = & mesh_facets.getSubelementToElement(type_facet, gt_facet); nb_subfacet_per_facet = subfacet_to_facet->getNbComponent(); } Element * sf_update = std::find(subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet, subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet + nb_subfacet_per_facet, old_subfacet_el); AKANTU_DEBUG_ASSERT(subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet != subfacet_to_facet->storage() + facet.element * nb_subfacet_per_facet + nb_subfacet_per_facet, "Subfacet not found"); *sf_update = new_subfacet_el; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::updateFacetToSubfacet(Mesh & mesh_facets, ElementType type_subfacet, GhostType gt_subfacet, bool facet_mode) { AKANTU_DEBUG_IN(); Array & sf_to_double = mesh_facets.getData("facet_to_double", type_subfacet, gt_subfacet); UInt nb_subfacet_to_double = sf_to_double.getSize(); Array< std::vector > & facet_to_subfacet = mesh_facets.getElementToSubelement(type_subfacet, gt_subfacet); Array< std::vector > * facet_to_subfacet_double = NULL; if (facet_mode) { facet_to_subfacet_double = & mesh_facets.getData >("facets_to_subfacet_double", type_subfacet, gt_subfacet); } else { facet_to_subfacet_double = & mesh_facets.getData >("subfacets_to_subsubfacet_double", type_subfacet, gt_subfacet); } UInt old_nb_subfacet = facet_to_subfacet.getSize(); facet_to_subfacet.resize(old_nb_subfacet + nb_subfacet_to_double); for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) facet_to_subfacet(old_nb_subfacet + sf) = (*facet_to_subfacet_double)(sf); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MeshUtils::doubleSubfacet(Mesh & mesh, Mesh & mesh_facets, Array & doubled_nodes) { AKANTU_DEBUG_IN(); if (spatial_dimension == 1) return; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType gt_subfacet = *gt; Mesh::type_iterator it = mesh_facets.firstType(0, gt_subfacet); Mesh::type_iterator end = mesh_facets.lastType(0, gt_subfacet); for(; it != end; ++it) { ElementType type_subfacet = *it; Array & sf_to_double = mesh_facets.getData("facet_to_double", type_subfacet, gt_subfacet); UInt nb_subfacet_to_double = sf_to_double.getSize(); if (nb_subfacet_to_double == 0) continue; AKANTU_DEBUG_ASSERT(type_subfacet == _point_1, "Only _point_1 subfacet doubling is supported at the moment"); Array & conn_subfacet = mesh_facets.getConnectivity(type_subfacet, gt_subfacet); UInt old_nb_subfacet = conn_subfacet.getSize(); UInt new_nb_subfacet = old_nb_subfacet + nb_subfacet_to_double; conn_subfacet.resize(new_nb_subfacet); std::vector nodes_to_double; UInt old_nb_doubled_nodes = doubled_nodes.getSize(); /// double nodes for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) { UInt old_subfacet = sf_to_double(sf); nodes_to_double.push_back(conn_subfacet(old_subfacet)); } doubleNodes(mesh, nodes_to_double, doubled_nodes); /// add new nodes in connectivity for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) { UInt new_subfacet = old_nb_subfacet + sf; UInt new_node = doubled_nodes(old_nb_doubled_nodes + sf, 1); conn_subfacet(new_subfacet) = new_node; } /// update facet and element connectivity Array > & f_to_subfacet_double = mesh_facets.getData >("facets_to_subfacet_double", type_subfacet, gt_subfacet); Array > & el_to_subfacet_double = mesh_facets.getData >("elements_to_subfacet_double", type_subfacet, gt_subfacet); Array > * sf_to_subfacet_double = NULL; if (spatial_dimension == 3) sf_to_subfacet_double = & mesh_facets.getData >("subfacets_to_subsubfacet_double", type_subfacet, gt_subfacet); for (UInt sf = 0; sf < nb_subfacet_to_double; ++sf) { UInt old_node = doubled_nodes(old_nb_doubled_nodes + sf, 0); UInt new_node = doubled_nodes(old_nb_doubled_nodes + sf, 1); updateElementalConnectivity(mesh, old_node, new_node, el_to_subfacet_double(sf), &f_to_subfacet_double(sf)); updateElementalConnectivity(mesh_facets, old_node, new_node, f_to_subfacet_double(sf)); if (spatial_dimension == 3) updateElementalConnectivity(mesh_facets, old_node, new_node, (*sf_to_subfacet_double)(sf)); } if (spatial_dimension == 2) { updateSubfacetToFacet(mesh_facets, type_subfacet, gt_subfacet, true); updateFacetToSubfacet(mesh_facets, type_subfacet, gt_subfacet, true); } else if (spatial_dimension == 3) { updateSubfacetToFacet(mesh_facets, type_subfacet, gt_subfacet, false); updateFacetToSubfacet(mesh_facets, type_subfacet, gt_subfacet, false); } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::flipFacets(Mesh & mesh_facets, const ElementTypeMapArray & global_connectivity, GhostType gt_facet) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh_facets.getSpatialDimension(); /// get global connectivity for local mesh ElementTypeMapArray global_connectivity_tmp; mesh_facets.initElementTypeMapArray(global_connectivity_tmp, 1, spatial_dimension - 1, gt_facet, true, _ek_regular, true); mesh_facets.getGlobalConnectivity(global_connectivity_tmp, spatial_dimension - 1, gt_facet); Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, gt_facet); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, gt_facet); /// loop on every facet for(; it != end; ++it) { ElementType type_facet = *it; Array & connectivity = mesh_facets.getConnectivity(type_facet, gt_facet); const Array & g_connectivity = global_connectivity(type_facet, gt_facet); Array > & el_to_f = mesh_facets.getElementToSubelement(type_facet, gt_facet); Array & subfacet_to_facet = mesh_facets.getSubelementToElement(type_facet, gt_facet); UInt nb_subfacet_per_facet = subfacet_to_facet.getNbComponent(); UInt nb_nodes_per_facet = connectivity.getNbComponent(); UInt nb_facet = connectivity.getSize(); UInt nb_nodes_per_P1_facet = Mesh::getNbNodesPerElement(Mesh::getP1ElementType(type_facet)); Array & global_conn_tmp = global_connectivity_tmp(type_facet, gt_facet); Array::iterator > conn_it = connectivity.begin(nb_nodes_per_facet); Array::iterator > gconn_tmp_it = global_conn_tmp.begin(nb_nodes_per_facet); Array::const_iterator > conn_glob_it = g_connectivity.begin(nb_nodes_per_facet); Array::iterator > subf_to_f = subfacet_to_facet.begin(nb_subfacet_per_facet); UInt * conn_tmp_pointer = new UInt[nb_nodes_per_facet]; Vector conn_tmp(conn_tmp_pointer, nb_nodes_per_facet); Element el_tmp; Element * subf_tmp_pointer = new Element[nb_subfacet_per_facet]; Vector subf_tmp(subf_tmp_pointer, nb_subfacet_per_facet); for (UInt f = 0; f < nb_facet; ++f, ++conn_it, ++gconn_tmp_it, ++subf_to_f, ++conn_glob_it) { Vector & gconn_tmp = *gconn_tmp_it; const Vector & conn_glob = *conn_glob_it; Vector & conn_local = *conn_it; /// skip facet if connectivities are the same if (gconn_tmp == conn_glob) continue; /// re-arrange connectivity conn_tmp = conn_local; UInt * begin = conn_glob.storage(); UInt * end = conn_glob.storage() + nb_nodes_per_facet; for (UInt n = 0; n < nb_nodes_per_facet; ++n) { UInt * new_node = std::find(begin, end, gconn_tmp(n)); AKANTU_DEBUG_ASSERT(new_node != end, "Node not found"); UInt new_position = new_node - begin; conn_local(new_position) = conn_tmp(n); } /// if 3D, check if facets are just rotated if (spatial_dimension == 3) { /// find first node UInt * new_node = std::find(begin, end, gconn_tmp(0)); AKANTU_DEBUG_ASSERT(new_node != end, "Node not found"); UInt new_position = new_node - begin; UInt n = 1; /// count how many nodes in the received connectivity follow /// the same order of those in the local connectivity for (; n < nb_nodes_per_P1_facet && gconn_tmp(n) == conn_glob((new_position + n) % nb_nodes_per_P1_facet); ++n); /// skip the facet inversion if facet is just rotated if (n == nb_nodes_per_P1_facet) continue; } /// update data to invert facet el_tmp = el_to_f(f)[0]; el_to_f(f)[0] = el_to_f(f)[1]; el_to_f(f)[1] = el_tmp; subf_tmp = (*subf_to_f); (*subf_to_f)(0) = subf_tmp(1); (*subf_to_f)(1) = subf_tmp(0); } delete [] subf_tmp_pointer; delete [] conn_tmp_pointer; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::fillElementToSubElementsData(Mesh & mesh) { AKANTU_DEBUG_IN(); if(mesh.getNbElement(mesh.getSpatialDimension() - 1) == 0) { AKANTU_DEBUG_INFO("There are not facets, add them in the mesh file or call the buildFacet method."); return; } UInt spatial_dimension = mesh.getSpatialDimension(); ElementTypeMapArray barycenters("barycenter_tmp", mesh.getID()); mesh.initElementTypeMapArray(barycenters, spatial_dimension, _all_dimensions); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { Mesh::type_iterator it = mesh.firstType(_all_dimensions, *gt); Mesh::type_iterator end = mesh.lastType(_all_dimensions, *gt); for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, *gt); Array & barycenters_arr = barycenters(*it, *gt); barycenters_arr.resize(nb_element); Array::vector_iterator bary = barycenters_arr.begin(spatial_dimension); Array::vector_iterator bary_end = barycenters_arr.end(spatial_dimension); for (UInt el = 0; bary != bary_end; ++bary, ++el) { mesh.getBarycenter(el, *it, bary->storage(), *gt); } } } for(Int sp(spatial_dimension); sp >= 1; --sp) { if(mesh.getNbElement(sp) == 0) continue; for (ghost_type_t::iterator git = ghost_type_t::begin(); git != ghost_type_t::end(); ++git) { Mesh::type_iterator tit = mesh.firstType(sp, *git); Mesh::type_iterator tend = mesh.lastType(sp, *git); for (;tit != tend; ++tit) { mesh.getSubelementToElementPointer(*tit, *git)->resize(mesh.getNbElement(*tit, *git)); mesh.getSubelementToElement(*tit, *git).clear(); } tit = mesh.firstType(sp - 1, *git); tend = mesh.lastType(sp - 1, *git); for (;tit != tend; ++tit) { mesh.getElementToSubelementPointer(*tit, *git)->resize(mesh.getNbElement(*tit, *git)); mesh.getElementToSubelement(*tit, *git).clear(); } } CSR nodes_to_elements; buildNode2Elements(mesh, nodes_to_elements, sp); Element facet_element; for (ghost_type_t::iterator git = ghost_type_t::begin(); git != ghost_type_t::end(); ++git) { Mesh::type_iterator tit = mesh.firstType(sp - 1, *git); Mesh::type_iterator tend = mesh.lastType(sp - 1, *git); facet_element.ghost_type = *git; for (;tit != tend; ++tit) { facet_element.type = *tit; Array< std::vector > & element_to_subelement = mesh.getElementToSubelement(*tit, *git); const Array & connectivity = mesh.getConnectivity(*tit, *git); Array::const_iterator< Vector > fit = connectivity.begin(mesh.getNbNodesPerElement(*tit)); Array::const_iterator< Vector > fend = connectivity.end(mesh.getNbNodesPerElement(*tit)); UInt fid = 0; for (;fit != fend; ++fit, ++fid) { const Vector & facet = *fit; facet_element.element = fid; std::map element_seen_counter; UInt nb_nodes_per_facet = mesh.getNbNodesPerElement(Mesh::getP1ElementType(*tit)); for (UInt n(0); n < nb_nodes_per_facet; ++n) { CSR::iterator eit = nodes_to_elements.begin(facet(n)); CSR::iterator eend = nodes_to_elements.end(facet(n)); for(;eit != eend; ++eit) { Element & elem = *eit; std::map::iterator cit = element_seen_counter.find(elem); if(cit != element_seen_counter.end()) { cit->second++; } else { element_seen_counter[elem] = 1; } } } std::vector connected_elements; std::map::iterator cit = element_seen_counter.begin(); std::map::iterator cend = element_seen_counter.end(); for(;cit != cend; ++cit) { if(cit->second == nb_nodes_per_facet) connected_elements.push_back(cit->first); } std::vector::iterator ceit = connected_elements.begin(); std::vector::iterator ceend = connected_elements.end(); for(;ceit != ceend; ++ceit) element_to_subelement(fid).push_back(*ceit); for (UInt ce = 0; ce < connected_elements.size(); ++ce) { Element & elem = connected_elements[ce]; Array & subelement_to_element = *(mesh.getSubelementToElementPointer(elem.type, elem.ghost_type)); UInt f(0); for(; f < mesh.getNbFacetsPerElement(elem.type) && subelement_to_element(elem.element, f) != ElementNull; ++f); AKANTU_DEBUG_ASSERT(f < mesh.getNbFacetsPerElement(elem.type), "The element " << elem << " seems to have too many facets!! (" << f << " < " << mesh.getNbFacetsPerElement(elem.type) << ")"); subelement_to_element(elem.element, f) = facet_element; } } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template bool MeshUtils::findElementsAroundSubfacet(const Mesh & mesh, const Mesh & mesh_facets, const Element & starting_element, const Element & end_facet, const Vector & subfacet_connectivity, std::vector & elem_list, std::vector & facet_list, std::vector * subfacet_list) { AKANTU_DEBUG_IN(); /// preallocated stuff before starting bool facet_matched = false; elem_list.clear(); facet_list.clear(); if (third_dim_points) subfacet_list->clear(); elem_list.push_back(starting_element); const Array * facet_connectivity = NULL; const Array * sf_connectivity = NULL; const Array * facet_to_element = NULL; const Array * subfacet_to_facet = NULL; ElementType current_type = _not_defined; GhostType current_ghost_type = _casper; ElementType current_facet_type = _not_defined; GhostType current_facet_ghost_type = _casper; ElementType current_subfacet_type = _not_defined; GhostType current_subfacet_ghost_type = _casper; const Array< std::vector > * element_to_facet = NULL; const Element * opposing_el = NULL; std::queue elements_to_check; elements_to_check.push(starting_element); /// keep going until there are elements to check while (!elements_to_check.empty()) { /// check current element Element & current_el = elements_to_check.front(); if (current_el.type != current_type || current_el.ghost_type != current_ghost_type) { current_type = current_el.type; current_ghost_type = current_el.ghost_type; facet_to_element = & mesh_facets.getSubelementToElement(current_type, current_ghost_type); } /// loop over each facet of the element for (UInt f = 0; f < facet_to_element->getNbComponent(); ++f) { const Element & current_facet = (*facet_to_element)(current_el.element, f); if (current_facet == ElementNull) continue; if (current_facet_type != current_facet.type || current_facet_ghost_type != current_facet.ghost_type) { current_facet_type = current_facet.type; current_facet_ghost_type = current_facet.ghost_type; element_to_facet = & mesh_facets.getElementToSubelement(current_facet_type, current_facet_ghost_type); facet_connectivity = & mesh_facets.getConnectivity(current_facet_type, current_facet_ghost_type); if (third_dim_points) subfacet_to_facet = & mesh_facets.getSubelementToElement(current_facet_type, current_facet_ghost_type); } /// check if end facet is reached if (current_facet == end_facet) facet_matched = true; /// add this facet if not already passed if (std::find(facet_list.begin(), facet_list.end(), current_facet) == facet_list.end() && hasElement(*facet_connectivity, current_facet, subfacet_connectivity)) { facet_list.push_back(current_facet); if (third_dim_points) { /// check subfacets for (UInt sf = 0; sf < subfacet_to_facet->getNbComponent(); ++sf) { const Element & current_subfacet = (*subfacet_to_facet)(current_facet.element, sf); if (current_subfacet == ElementNull) continue; if (current_subfacet_type != current_subfacet.type || current_subfacet_ghost_type != current_subfacet.ghost_type) { current_subfacet_type = current_subfacet.type; current_subfacet_ghost_type = current_subfacet.ghost_type; sf_connectivity = & mesh_facets.getConnectivity(current_subfacet_type, current_subfacet_ghost_type); } if (std::find(subfacet_list->begin(), subfacet_list->end(), current_subfacet) == subfacet_list->end() && hasElement(*sf_connectivity, current_subfacet, subfacet_connectivity)) subfacet_list->push_back(current_subfacet); } } } else continue; /// consider opposing element if ( (*element_to_facet)(current_facet.element)[0] == current_el) opposing_el = & (*element_to_facet)(current_facet.element)[1]; else opposing_el = & (*element_to_facet)(current_facet.element)[0]; /// skip null elements since they are on a boundary if (*opposing_el == ElementNull) continue; /// skip this element if already added if ( std::find(elem_list.begin(), elem_list.end(), *opposing_el) != elem_list.end() ) continue; /// only regular elements have to be checked if (opposing_el->kind == _ek_regular) elements_to_check.push(*opposing_el); elem_list.push_back(*opposing_el); #ifndef AKANTU_NDEBUG const Array & conn_elem = mesh.getConnectivity(opposing_el->type, opposing_el->ghost_type); AKANTU_DEBUG_ASSERT(hasElement(conn_elem, *opposing_el, subfacet_connectivity), "Subfacet doesn't belong to this element"); #endif } /// erased checked element from the list elements_to_check.pop(); } AKANTU_DEBUG_OUT(); return facet_matched; } /* -------------------------------------------------------------------------- */ void MeshUtils::buildSegmentToNodeType(const Mesh & mesh, Mesh & mesh_facets, DistributedSynchronizer * synchronizer) { buildAllFacets(mesh, mesh_facets, 1, synchronizer); UInt spatial_dimension = mesh.getSpatialDimension(); const ElementTypeMapArray & element_to_rank = synchronizer->getPrankToElement(); Int local_rank = StaticCommunicator::getStaticCommunicator().whoAmI(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator it = mesh_facets.firstType(1, ghost_type); Mesh::type_iterator end = mesh_facets.lastType(1, ghost_type); for(; it != end; ++it) { ElementType type = *it; UInt nb_segments = mesh_facets.getNbElement(type, ghost_type); // allocate the data Array & segment_to_nodetype = *(mesh_facets.getDataPointer("segment_to_nodetype", type, ghost_type)); std::set connected_elements; const Array< std::vector > & segment_to_2Delement = mesh_facets.getElementToSubelement(type, ghost_type); // loop over segments for (UInt s = 0; s < nb_segments; ++s) { // determine the elements connected to the segment connected_elements.clear(); const std::vector & twoD_elements = segment_to_2Delement(s); if (spatial_dimension == 2) { // if 2D just take the elements connected to the segments connected_elements.insert(twoD_elements.begin(), twoD_elements.end()); } else if (spatial_dimension == 3) { // if 3D a second loop is needed to get to the 3D elements std::vector::const_iterator facet = twoD_elements.begin(); for (; facet != twoD_elements.end(); ++facet) { const std::vector & threeD_elements = mesh_facets.getElementToSubelement(facet->type, facet->ghost_type)(facet->element); connected_elements.insert(threeD_elements.begin(), threeD_elements.end()); } } // get the minimum processor rank associated to the connected // elements and verify if ghost and not ghost elements are // found Int minimum_rank = std::numeric_limits::max(); // two booleans saying if not ghost and ghost elements are found in the loop bool ghost_found[2]; ghost_found[0] = false; ghost_found[1] = false; std::set::iterator connected_elements_it = connected_elements.begin(); for (; connected_elements_it != connected_elements.end(); ++connected_elements_it) { if (*connected_elements_it == ElementNull) continue; ghost_found[connected_elements_it->ghost_type] = true; const Array & el_to_rank_array = element_to_rank(connected_elements_it->type, connected_elements_it->ghost_type); minimum_rank = std::min(minimum_rank, Int(el_to_rank_array(connected_elements_it->element))); } // if no ghost elements are found the segment is local if (!ghost_found[1]) segment_to_nodetype(s) = -1; // if no not ghost elements are found the segment is pure ghost else if (!ghost_found[0]) segment_to_nodetype(s) = -3; // if the minimum rank is equal to the local rank, the segment is master else if (local_rank == minimum_rank) segment_to_nodetype(s) = -2; // if the minimum rank is less than the local rank, the segment is slave else if (local_rank > minimum_rank) segment_to_nodetype(s) = minimum_rank; else AKANTU_DEBUG_ERROR("The local rank cannot be smaller than the minimum rank if both ghost and not ghost elements are found"); } } } } /* -------------------------------------------------------------------------- */ UInt MeshUtils::updateLocalMasterGlobalConnectivity(Mesh & mesh, UInt local_nb_new_nodes) { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int rank = comm.whoAmI(); Int nb_proc = comm.getNbProc(); if (nb_proc == 1) return local_nb_new_nodes; /// resize global ids array Array & nodes_global_ids = mesh.getGlobalNodesIds(); UInt old_nb_nodes = mesh.getNbNodes() - local_nb_new_nodes; nodes_global_ids.resize(mesh.getNbNodes()); + /// compute the number of global nodes based on the number of old nodes + Vector old_local_master_nodes(nb_proc); + for (UInt n = 0; n < old_nb_nodes; ++n) + if (mesh.isLocalOrMasterNode(n)) ++old_local_master_nodes(rank); + comm.allGather(old_local_master_nodes.storage(), 1); + UInt old_global_nodes = std::accumulate(old_local_master_nodes.storage(), + old_local_master_nodes.storage() + nb_proc, + 0); + /// compute amount of local or master doubled nodes Vector local_master_nodes(nb_proc); - for (UInt n = old_nb_nodes; n < mesh.getNbNodes(); ++n) if (mesh.isLocalOrMasterNode(n)) ++local_master_nodes(rank); comm.allGather(local_master_nodes.storage(), 1); /// update global number of nodes UInt total_nb_new_nodes = std::accumulate(local_master_nodes.storage(), local_master_nodes.storage() + nb_proc, 0); if (total_nb_new_nodes == 0) return 0; /// set global ids of local and master nodes UInt starting_index = std::accumulate(local_master_nodes.storage(), local_master_nodes.storage() + rank, - mesh.getNbGlobalNodes()); + old_global_nodes); for (UInt n = old_nb_nodes; n < mesh.getNbNodes(); ++n) { if (mesh.isLocalOrMasterNode(n)) { nodes_global_ids(n) = starting_index; ++starting_index; } } - mesh.nb_global_nodes += total_nb_new_nodes; + mesh.nb_global_nodes = old_global_nodes + total_nb_new_nodes; return total_nb_new_nodes; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ // LocalWords: ElementType diff --git a/src/model/boundary_condition_python_functor.cc b/src/model/boundary_condition_python_functor.cc index 477356b2c..4ee348fbf 100644 --- a/src/model/boundary_condition_python_functor.cc +++ b/src/model/boundary_condition_python_functor.cc @@ -1,48 +1,62 @@ /** * @file boundary_condition_python_functor.cc * * @author Guillaume Anciaux * * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ - #include "boundary_condition_python_functor.hh" +/* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ namespace BC { + + void PythonFunctorDirichlet::operator ()(UInt node, Vector & flags, Vector & primal, const Vector & coord) const{ - throw; + + this->callFunctor("operator",node,flags,primal,coord); } - + + + + void PythonFunctorNeumann::operator()(const IntegrationPoint & quad_point, + Vector & dual, + const Vector & coord, + const Vector & normals) const{ + + this->callFunctor("operator",quad_point,dual,coord,normals); + } + + }//end namespace BC __END_AKANTU__ diff --git a/src/model/boundary_condition_python_functor.hh b/src/model/boundary_condition_python_functor.hh index fc7d4bf64..e871574ac 100644 --- a/src/model/boundary_condition_python_functor.hh +++ b/src/model/boundary_condition_python_functor.hh @@ -1,79 +1,113 @@ /** * @file boundary_condition_python_functor.hh * * @author Guillaume Anciaux * * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ - - +#include "aka_common.hh" +#include "boundary_condition_functor.hh" +/* -------------------------------------------------------------------------- */ #ifndef __AKANTU_BOUNDARY_CONDITION_PYTHON_FUNCTOR_HH__ #define __AKANTU_BOUNDARY_CONDITION_PYTHON_FUNCTOR_HH__ /* -------------------------------------------------------------------------- */ -#include -#include "aka_common.hh" #include "boundary_condition_functor.hh" +#include "python_functor.hh" /* -------------------------------------------------------------------------- */ - __BEGIN_AKANTU__ namespace BC { -class PythonFunctor : public Functor { -public: - PythonFunctor(PyObject * obj) : python_obj(obj) {} + class PythonFunctorDirichlet : public PythonFunctor, public Functor { + + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ -private: - PyObject * python_obj; + public: + PythonFunctorDirichlet(PyObject * obj) : PythonFunctor(obj) {} -}; + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ -class PythonFunctorDirichlet : public PythonFunctor { + public: + void operator()(UInt node, + Vector & flags, + Vector & primal, + const Vector & coord) const; -public: - PythonFunctorDirichlet(PyObject * obj) : PythonFunctor(obj) {} + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ -public: - void operator()(UInt node, - Vector & flags, - Vector & primal, - const Vector & coord) const; + public: + static const Type type = _dirichlet; + + + }; + +/* -------------------------------------------------------------------------- */ + + + class PythonFunctorNeumann : public PythonFunctor, public Functor{ + + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ + + public: + PythonFunctorNeumann(PyObject * obj) : PythonFunctor(obj) {} + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ + + public: + + void operator()(const IntegrationPoint & quad_point, + Vector & dual, + const Vector & coord, + const Vector & normals) const; -public: - static const Type type = _dirichlet; + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ + public: + static const Type type = _neumann; -}; + }; }//end namespace BC __END_AKANTU__ #endif /* __AKANTU_BOUNDARY_CONDITION_PYTHON_FUNCTOR_HH__ */ diff --git a/src/model/common/non_local_toolbox/non_local_manager.cc b/src/model/common/non_local_toolbox/non_local_manager.cc index 6b3f66e4b..6359b9fbb 100644 --- a/src/model/common/non_local_toolbox/non_local_manager.cc +++ b/src/model/common/non_local_toolbox/non_local_manager.cc @@ -1,634 +1,634 @@ /** * @file non_local_manager.cc * @author Aurelia Isabel Cuba Ramos * @date Mon Sep 21 15:32:10 2015 * * @brief Implementation of non-local manager * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "non_local_manager.hh" #include "non_local_neighborhood.hh" #include "material_non_local.hh" #include "base_weight_function.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ NonLocalManager::NonLocalManager(SolidMechanicsModel & model, const ID & id, const MemoryID & memory_id) : Memory(id, memory_id), Parsable(_st_neighborhoods, id), model(model), quad_positions("quad_positions", id), volumes("volumes", id), spatial_dimension(this->model.getSpatialDimension()), compute_stress_calls(0), dummy_registry(NULL), dummy_grid(NULL) { Mesh & mesh = this->model.getMesh(); mesh.registerEventHandler(*this); /// initialize the element type map array /// it will be resized to nb_quad * nb_element during the computation of coords mesh.initElementTypeMapArray(quad_positions, spatial_dimension, spatial_dimension, false, _ek_regular, true); /// parse the neighborhood information from the input file const Parser & parser = getStaticParser(); /// iterate over all the non-local sections and store them in a map std::pair weight_sect = parser.getSubSections(_st_non_local); Parser::const_section_iterator it = weight_sect.first; for (; it != weight_sect.second; ++it) { const ParserSection & section = *it; ID name = section.getName(); this->weight_function_types[name] = section; } this->dummy_registry = new SynchronizerRegistry(this->dummy_accessor); } /* -------------------------------------------------------------------------- */ NonLocalManager::~NonLocalManager() { /// delete neighborhoods NeighborhoodMap::iterator it; for (it = neighborhoods.begin(); it != neighborhoods.end(); ++it) { if(it->second) delete it->second; } /// delete non-local variables std::map::iterator it_variables; for (it_variables = non_local_variables.begin(); it_variables != non_local_variables.end(); ++it_variables) { if(it_variables->second) delete it_variables->second; } std::map::iterator it_internals; for (it_internals = weight_function_internals.begin(); it_internals != weight_function_internals.end(); ++it_internals) { if(it_internals->second) delete it_internals->second; } std::map::iterator grid_synch_it; for (grid_synch_it = dummy_synchronizers.begin(); grid_synch_it != dummy_synchronizers.end(); ++grid_synch_it) { if(grid_synch_it->second) delete grid_synch_it->second; } /// delete all objects related to the dummy synchronizers delete dummy_registry; delete dummy_grid; } /* -------------------------------------------------------------------------- */ void NonLocalManager::setJacobians(const FEEngine & fe_engine, const ElementKind & kind) { Mesh & mesh = this->model.getMesh(); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt, kind); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, gt, kind); for(; it != last_type; ++it) { jacobians(*it, gt) = &fe_engine.getIntegratorInterface().getJacobians(*it, gt); } } } /* -------------------------------------------------------------------------- */ void NonLocalManager::createNeighborhood(const ID & weight_func, const ID & neighborhood_id) { AKANTU_DEBUG_IN(); const ParserSection & section = this->weight_function_types[weight_func]; const ID weight_func_type = section.getOption(); /// create new neighborhood for given ID std::stringstream sstr; sstr << id << ":neighborhood:" << neighborhood_id; if (weight_func_type == "base_wf") neighborhoods[neighborhood_id] = new NonLocalNeighborhood(*this, this->quad_positions, sstr.str()); else if (weight_func_type == "remove_wf") neighborhoods[neighborhood_id] = new NonLocalNeighborhood(*this, this->quad_positions, sstr.str()); else if (weight_func_type == "stress_wf") neighborhoods[neighborhood_id] = new NonLocalNeighborhood(*this, this->quad_positions, sstr.str()); else if (weight_func_type == "damage_wf") neighborhoods[neighborhood_id] = new NonLocalNeighborhood(*this, this->quad_positions, sstr.str()); else AKANTU_EXCEPTION("error in weight function type provided in material file"); neighborhoods[neighborhood_id]->parseSection(section); neighborhoods[neighborhood_id]->initNeighborhood(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NonLocalManager::createNeighborhoodSynchronizers() { /// exchange all the neighborhood IDs, so that every proc knows how many neighborhoods exist globally /// First: Compute locally the maximum ID size UInt max_id_size = 0; UInt current_size = 0; NeighborhoodMap::const_iterator it; for (it = neighborhoods.begin(); it != neighborhoods.end(); ++it) { current_size = it->first.size(); if (current_size > max_id_size) max_id_size = current_size; } /// get the global maximum ID size on each proc StaticCommunicator & static_communicator = akantu::StaticCommunicator::getStaticCommunicator(); static_communicator.allReduce(&max_id_size, 1, _so_max); /// get the rank for this proc and the total nb proc UInt prank = static_communicator.whoAmI(); UInt psize = static_communicator.getNbProc(); /// exchange the number of neighborhoods on each proc Array nb_neighborhoods_per_proc(psize); nb_neighborhoods_per_proc(prank) = neighborhoods.size(); static_communicator.allGather(nb_neighborhoods_per_proc.storage(), 1); /// compute the total number of neighborhoods UInt nb_neighborhoods_global = std::accumulate(nb_neighborhoods_per_proc.begin(), nb_neighborhoods_per_proc.end(), 0); /// allocate an array of chars to store the names of all neighborhoods Array buffer(nb_neighborhoods_global, max_id_size); /// starting index on this proc UInt starting_index = std::accumulate(nb_neighborhoods_per_proc.begin(), nb_neighborhoods_per_proc.begin() + prank, 0); it = neighborhoods.begin(); /// store the names of local neighborhoods in the buffer for (UInt i = 0; i < neighborhoods.size(); ++i, ++it) { UInt c = 0; for (; c < it->first.size(); ++c) buffer(i + starting_index, c) = it->first[c]; for (; c < max_id_size; ++c) buffer(i + starting_index, c) = char( 0 ); } /// store the nb of data to send in the all gather Array buffer_size(nb_neighborhoods_per_proc); buffer_size *= max_id_size; /// exchange the names of all the neighborhoods with all procs static_communicator.allGatherV(buffer.storage(), buffer_size.storage()); for (UInt i = 0; i < nb_neighborhoods_global; ++i) { std::stringstream neighborhood_id; for(UInt c = 0; c < max_id_size; ++c) { if (buffer(i,c) == char( 0 )) break; neighborhood_id << buffer(i,c); } global_neighborhoods.insert(neighborhood_id.str()); } /// this proc does not know all the neighborhoods -> create dummy /// grid so that this proc can participate in the all gather for /// detecting the overlap of neighborhoods this proc doesn't know Vector grid_center(this->spatial_dimension); for(UInt s = 0; s < this->spatial_dimension; ++s) grid_center(s) = std::numeric_limits::max(); dummy_grid = new SpatialGrid(spatial_dimension, 0., grid_center); std::set tags; tags.insert(_gst_mnl_for_average); tags.insert(_gst_mnl_weight); std::set::const_iterator global_neighborhoods_it = global_neighborhoods.begin(); for (; global_neighborhoods_it != global_neighborhoods.end(); ++global_neighborhoods_it) { it = neighborhoods.find(*global_neighborhoods_it); if (it != neighborhoods.end()) { it->second->createGridSynchronizer(); } else { ID neighborhood_name = *global_neighborhoods_it; std::stringstream sstr; sstr << getID() << ":" << neighborhood_name << ":grid_synchronizer"; dummy_synchronizers[neighborhood_name] = GridSynchronizer::createGridSynchronizer(this->model.getMesh(), *dummy_grid, sstr.str(), dummy_registry, tags, 0, false); } } } /* -------------------------------------------------------------------------- */ void NonLocalManager::flattenInternal(ElementTypeMapReal & internal_flat, const GhostType & ghost_type, const ElementKind & kind) { const ID field_name = internal_flat.getName(); for (UInt m = 0; m < this->non_local_materials.size(); ++m) { Material & material = *(this->non_local_materials[m]); if (material.isInternal(field_name, kind)) material.flattenInternal(field_name, internal_flat, ghost_type, kind); } } /* -------------------------------------------------------------------------- */ void NonLocalManager::averageInternals(const GhostType & ghost_type) { /// update the weights of the weight function if (ghost_type == _not_ghost) this->computeWeights(); /// loop over all neighborhoods and compute the non-local variables NeighborhoodMap::iterator neighborhood_it = neighborhoods.begin(); NeighborhoodMap::iterator neighborhood_end = neighborhoods.end(); for (; neighborhood_it != neighborhood_end; ++neighborhood_it) { /// loop over all the non-local variables of the given neighborhood std::map::iterator non_local_variable_it = non_local_variables.begin(); std::map::iterator non_local_variable_end = non_local_variables.end(); for(; non_local_variable_it != non_local_variable_end; ++non_local_variable_it) { NonLocalVariable * non_local_var = non_local_variable_it->second; neighborhood_it->second->weightedAverageOnNeighbours(non_local_var->local, non_local_var->non_local, non_local_var->nb_component, ghost_type); } } if (ghost_type == _ghost) { /// compute the non-local stresses in the materials for(UInt m = 0; m < this->non_local_materials.size(); ++m) { switch (spatial_dimension) { case 1: - dynamic_cast &>(*(this->non_local_materials[m])).computeNonLocalStresses(ghost_type); + dynamic_cast &>(*(this->non_local_materials[m])).computeNonLocalStresses(_not_ghost); break; case 2: - dynamic_cast &>(*(this->non_local_materials[m])).computeNonLocalStresses(ghost_type); + dynamic_cast &>(*(this->non_local_materials[m])).computeNonLocalStresses(_not_ghost); break; case 3: - dynamic_cast &>(*(this->non_local_materials[m])).computeNonLocalStresses(ghost_type); + dynamic_cast &>(*(this->non_local_materials[m])).computeNonLocalStresses(_not_ghost); break; } } } } /* -------------------------------------------------------------------------- */ void NonLocalManager::init(){ /// store the number of current ghost elements for each type in the mesh ElementTypeMap nb_ghost_protected; Mesh & mesh = this->model.getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _ghost); for(; it != last_type; ++it) nb_ghost_protected(mesh.getNbElement(*it, _ghost), *it, _ghost); /// exchange the missing ghosts for the non-local neighborhoods this->createNeighborhoodSynchronizers(); /// insert the ghost quadrature points of the non-local materials into the non-local neighborhoods for(UInt m = 0; m < this->non_local_materials.size(); ++m) { switch (spatial_dimension) { case 1: dynamic_cast &>(*(this->non_local_materials[m])).insertQuadsInNeighborhoods(_ghost); break; case 2: dynamic_cast &>(*(this->non_local_materials[m])).insertQuadsInNeighborhoods(_ghost); break; case 3: dynamic_cast &>(*(this->non_local_materials[m])).insertQuadsInNeighborhoods(_ghost); break; } } FEEngine & fee = this->model.getFEEngine(); this->updatePairLists(); /// cleanup the unneccessary ghost elements this->cleanupExtraGhostElements(nb_ghost_protected); this->initElementTypeMap(1, volumes, fee); this->setJacobians(fee, _ek_regular); this->initNonLocalVariables(); this->computeWeights(); } /* -------------------------------------------------------------------------- */ void NonLocalManager::initNonLocalVariables(){ /// loop over all the non-local variables std::map::iterator non_local_variable_it = non_local_variables.begin(); std::map::iterator non_local_variable_end = non_local_variables.end(); for(; non_local_variable_it != non_local_variable_end; ++non_local_variable_it) { NonLocalVariable & variable = *(non_local_variable_it->second); this->initElementTypeMap(variable.nb_component, variable.non_local, this->model.getFEEngine()); } } /* -------------------------------------------------------------------------- */ void NonLocalManager::initElementTypeMap(UInt nb_component, ElementTypeMapReal & element_map, const FEEngine & fee, const ElementKind el_kind) { Mesh & mesh = this->model.getMesh(); /// need to resize the arrays for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt, el_kind); Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt, el_kind); for(; it != end; ++it) { ElementType el_type = *it; UInt nb_element = mesh.getNbElement(*it, gt); UInt nb_quads = fee.getNbIntegrationPoints(*it, gt); if (!element_map.exists(el_type, gt)) { element_map.alloc(nb_element * nb_quads, nb_component, el_type, gt); } } } } /* -------------------------------------------------------------------------- */ void NonLocalManager::distributeInternals(ElementKind kind) { /// loop over all the non-local variables and copy back their values into the materials std::map::iterator non_local_variable_it = non_local_variables.begin(); std::map::iterator non_local_variable_end = non_local_variables.end(); for(; non_local_variable_it != non_local_variable_end; ++non_local_variable_it) { NonLocalVariable * non_local_var = non_local_variable_it->second; const ID field_name = non_local_var->non_local.getName(); /// loop over all the materials for (UInt m = 0; m < this->non_local_materials.size(); ++m) { if (this->non_local_materials[m]->isInternal(field_name, kind)) switch (spatial_dimension) { case 1: dynamic_cast &>(*(this->non_local_materials[m])).updateNonLocalInternals(non_local_var->non_local, field_name, non_local_var->nb_component); break; case 2: dynamic_cast &>(*(this->non_local_materials[m])).updateNonLocalInternals(non_local_var->non_local, field_name, non_local_var->nb_component); break; case 3: dynamic_cast &>(*(this->non_local_materials[m])).updateNonLocalInternals(non_local_var->non_local, field_name, non_local_var->nb_component); break; } } } } /* -------------------------------------------------------------------------- */ void NonLocalManager::computeAllNonLocalStresses() { /// update the flattened version of the internals std::map::iterator non_local_variable_it = non_local_variables.begin(); std::map::iterator non_local_variable_end = non_local_variables.end(); for(; non_local_variable_it != non_local_variable_end; ++non_local_variable_it) { non_local_variable_it->second->local.clear(); non_local_variable_it->second->non_local.clear(); for(UInt gt = _not_ghost; gt <= _ghost; ++gt) { GhostType ghost_type = (GhostType) gt; this->flattenInternal(non_local_variable_it->second->local, ghost_type, _ek_regular); } } this->volumes.clear(); ///loop over all the neighborhoods and compute intiate the /// exchange of the non-local_variables // std::set::const_iterator global_neighborhood_it = global_neighborhoods.begin(); // NeighborhoodMap::iterator it; // for(; global_neighborhood_it != global_neighborhoods.end(); ++global_neighborhood_it) { // it = neighborhoods.find(*global_neighborhood_it); // if (it != neighborhoods.end()) // it->second->getSynchronizerRegistry().asynchronousSynchronize(_gst_mnl_for_average); // else // dummy_synchronizers[*global_neighborhood_it]->asynchronousSynchronize(dummy_accessor, _gst_mnl_for_average); // } NeighborhoodMap::iterator neighborhood_it = neighborhoods.begin(); NeighborhoodMap::iterator neighborhood_end = neighborhoods.end(); for(; neighborhood_it != neighborhoods.end(); ++neighborhood_it) { neighborhood_it->second->getSynchronizerRegistry().asynchronousSynchronize(_gst_mnl_for_average); } this->averageInternals(_not_ghost); AKANTU_DEBUG_INFO("Wait distant non local stresses"); /// loop over all the neighborhoods and block until all non-local /// variables have been exchanged // global_neighborhood_it = global_neighborhoods.begin(); // for(; global_neighborhood_it != global_neighborhoods.end(); ++global_neighborhood_it) { // it = neighborhoods.find(*global_neighborhood_it); // if (it != neighborhoods.end()) // it->second->getSynchronizerRegistry().waitEndSynchronize(_gst_mnl_for_average); // else // dummy_synchronizers[*global_neighborhood_it]->waitEndSynchronize(dummy_accessor, _gst_mnl_for_average); // } neighborhood_it = neighborhoods.begin(); for(; neighborhood_it != neighborhoods.end(); ++neighborhood_it) { neighborhood_it->second->getSynchronizerRegistry().waitEndSynchronize(_gst_mnl_for_average); } this->averageInternals(_ghost); /// copy the results in the materials this->distributeInternals(_ek_regular); /// loop over all the materials and update the weights for (UInt m = 0; m < this->non_local_materials.size(); ++m) { switch (spatial_dimension) { case 1: dynamic_cast &>(*(this->non_local_materials[m])).computeNonLocalStresses(_not_ghost); break; case 2: dynamic_cast &>(*(this->non_local_materials[m])).computeNonLocalStresses(_not_ghost); break; case 3: dynamic_cast &>(*(this->non_local_materials[m])).computeNonLocalStresses(_not_ghost); break; } } ++this->compute_stress_calls; } /* -------------------------------------------------------------------------- */ void NonLocalManager::cleanupExtraGhostElements(ElementTypeMap & nb_ghost_protected) { typedef std::set ElementSet; ElementSet relevant_ghost_elements; ElementSet to_keep_per_neighborhood; /// loop over all the neighborhoods and get their protected ghosts NeighborhoodMap::iterator neighborhood_it = neighborhoods.begin(); NeighborhoodMap::iterator neighborhood_end = neighborhoods.end(); for (; neighborhood_it != neighborhood_end; ++neighborhood_it) { neighborhood_it->second->cleanupExtraGhostElements(to_keep_per_neighborhood); ElementSet::const_iterator it = to_keep_per_neighborhood.begin(); for(; it != to_keep_per_neighborhood.end(); ++it) relevant_ghost_elements.insert(*it); to_keep_per_neighborhood.clear(); } /// remove all unneccessary ghosts from the mesh /// Create list of element to remove and new numbering for element to keep Mesh & mesh = this->model.getMesh(); ElementSet ghost_to_erase; Mesh::type_iterator it = mesh.firstType(spatial_dimension, _ghost); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, _ghost); RemovedElementsEvent remove_elem(mesh); Element element; element.ghost_type = _ghost; for(; it != last_type; ++it) { element.type = *it; UInt nb_ghost_elem = mesh.getNbElement(*it, _ghost); UInt nb_ghost_elem_protected = 0; try { nb_ghost_elem_protected = nb_ghost_protected(*it, _ghost); } catch (...) {} if(!remove_elem.getNewNumbering().exists(*it, _ghost)) remove_elem.getNewNumbering().alloc(nb_ghost_elem, 1, *it, _ghost); else remove_elem.getNewNumbering(*it, _ghost).resize(nb_ghost_elem); Array & new_numbering = remove_elem.getNewNumbering(*it, _ghost); for (UInt g = 0; g < nb_ghost_elem; ++g) { element.element = g; if (element.element >= nb_ghost_elem_protected && relevant_ghost_elements.find(element) == relevant_ghost_elements.end()) { remove_elem.getList().push_back(element); new_numbering(element.element) = UInt(-1); } } /// renumber remaining ghosts UInt ng = 0; for (UInt g = 0; g < nb_ghost_elem; ++g) { if (new_numbering(g) != UInt(-1)) { new_numbering(g) = ng; ++ng; } } } it = mesh.firstType(spatial_dimension, _not_ghost); last_type = mesh.lastType(spatial_dimension, _not_ghost); for(; it != last_type; ++it) { UInt nb_elem = mesh.getNbElement(*it, _not_ghost); if(!remove_elem.getNewNumbering().exists(*it, _not_ghost)) remove_elem.getNewNumbering().alloc(nb_elem, 1, *it, _not_ghost); Array & new_numbering = remove_elem.getNewNumbering(*it, _not_ghost); for (UInt e = 0; e < nb_elem; ++e) { new_numbering(e) = e; } } mesh.sendEvent(remove_elem); } /* -------------------------------------------------------------------------- */ void NonLocalManager::onElementsRemoved(const Array & element_list, const ElementTypeMapArray & new_numbering, __attribute__((unused)) const RemovedElementsEvent & event) { FEEngine & fee = this->model.getFEEngine(); this->removeIntegrationPointsFromMap(event.getNewNumbering(), spatial_dimension, quad_positions, fee, _ek_regular); this->removeIntegrationPointsFromMap(event.getNewNumbering(), 1, volumes, fee, _ek_regular); /// loop over all the neighborhoods and call onElementsRemoved std::set::const_iterator global_neighborhood_it = global_neighborhoods.begin(); NeighborhoodMap::iterator it; for(; global_neighborhood_it != global_neighborhoods.end(); ++global_neighborhood_it) { it = neighborhoods.find(*global_neighborhood_it); if (it != neighborhoods.end()) it->second->onElementsRemoved(element_list, new_numbering, event); else dummy_synchronizers[*global_neighborhood_it]->onElementsRemoved(element_list, new_numbering, event); } } /* -------------------------------------------------------------------------- */ void NonLocalManager::onElementsAdded(__attribute__((unused)) const Array & element_list, __attribute__((unused)) const NewElementsEvent & event) { this->resizeElementTypeMap(1, volumes); this->resizeElementTypeMap(spatial_dimension, quad_positions); } /* -------------------------------------------------------------------------- */ void NonLocalManager::resizeElementTypeMap(UInt nb_component, ElementTypeMapReal & element_map, const ElementKind el_kind) { Mesh & mesh = this->model.getMesh(); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt, el_kind); Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt, el_kind); for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, gt); if(!element_map.exists(*it, gt)) element_map.alloc(nb_element, nb_component, *it, gt); else element_map(*it, gt).resize(nb_element); } } } /* -------------------------------------------------------------------------- */ void NonLocalManager::removeIntegrationPointsFromMap(const ElementTypeMapArray & new_numbering, UInt nb_component, ElementTypeMapReal & element_map, const FEEngine & fee, const ElementKind el_kind) { for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; ElementTypeMapArray::type_iterator it = new_numbering.firstType(_all_dimensions, gt, el_kind); ElementTypeMapArray::type_iterator end = new_numbering.lastType(_all_dimensions, gt, el_kind); for (; it != end; ++it) { ElementType type = *it; if(element_map.exists(type, gt)){ const Array & renumbering = new_numbering(type, gt); Array & vect = element_map(type, gt); UInt nb_quad_per_elem = fee.getNbIntegrationPoints(type, gt); Array tmp(renumbering.getSize()*nb_quad_per_elem, nb_component); AKANTU_DEBUG_ASSERT(tmp.getSize() == vect.getSize(), "Something strange append some mater was created from nowhere!!"); AKANTU_DEBUG_ASSERT(tmp.getSize() == vect.getSize(), "Something strange append some mater was created or disappeared in "<< vect.getID() << "("<< vect.getSize() <<"!=" << tmp.getSize() <<") ""!!"); UInt new_size = 0; for (UInt i = 0; i < renumbering.getSize(); ++i) { UInt new_i = renumbering(i); if(new_i != UInt(-1)) { memcpy(tmp.storage() + new_i * nb_component * nb_quad_per_elem, vect.storage() + i * nb_component * nb_quad_per_elem, nb_component * nb_quad_per_elem * sizeof(Real)); ++new_size; } } tmp.resize(new_size * nb_quad_per_elem); vect.copy(tmp); } } } } __END_AKANTU__ diff --git a/src/model/solid_mechanics/material.cc b/src/model/solid_mechanics/material.cc index 6326dbb9c..ca9d82255 100644 --- a/src/model/solid_mechanics/material.cc +++ b/src/model/solid_mechanics/material.cc @@ -1,1634 +1,1690 @@ /** * @file material.cc * * @author Aurelia Isabel Cuba Ramos * @author Marco Vocialta * @author Nicolas Richart * @author Daniel Pino Muñoz * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Sep 16 2014 * * @brief Implementation of the common part of the material class * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "material.hh" #include "solid_mechanics_model.hh" #include "sparse_matrix.hh" #include "dof_synchronizer.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Material::Material(SolidMechanicsModel & model, const ID & id) : Memory(id, model.getMemoryID()), Parsable(_st_material, id), is_init(false), fem(&(model.getFEEngine())), finite_deformation(false), name(""), model(&model), spatial_dimension(this->model->getSpatialDimension()), element_filter("element_filter", id, this->memory_id), stress("stress", *this), eigengradu("eigen_grad_u", *this), gradu("grad_u", *this), green_strain("green_strain",*this), piola_kirchhoff_2("piola_kirchhoff_2", *this), // potential_energy_vector(false), potential_energy("potential_energy", *this), is_non_local(false), use_previous_stress(false), use_previous_gradu(false), interpolation_inverse_coordinates("interpolation inverse coordinates", *this), interpolation_points_matrices("interpolation points matrices", *this) { AKANTU_DEBUG_IN(); /// for each connectivity types allocate the element filer array of the material model.getMesh().initElementTypeMapArray(element_filter, 1, spatial_dimension, false, _ek_regular); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Material::Material(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id) : Memory(id, model.getMemoryID()), Parsable(_st_material, id), is_init(false), fem(&(model.getFEEngine())), finite_deformation(false), name(""), model(&model), spatial_dimension(dim), element_filter("element_filter", id, this->memory_id), stress("stress", *this, dim, fe_engine, this->element_filter), eigengradu("eigen_grad_u", *this, dim, fe_engine, this->element_filter), gradu("gradu", *this, dim, fe_engine, this->element_filter), green_strain("green_strain", *this, dim, fe_engine, this->element_filter), piola_kirchhoff_2("poila_kirchhoff_2", *this, dim, fe_engine, this->element_filter), potential_energy("potential_energy", *this, dim, fe_engine, this->element_filter), is_non_local(false), use_previous_stress(false), use_previous_gradu(false), interpolation_inverse_coordinates("interpolation inverse_coordinates", *this, dim, fe_engine, this->element_filter), interpolation_points_matrices("interpolation points matrices", *this, dim, fe_engine, this->element_filter) { AKANTU_DEBUG_IN(); mesh.initElementTypeMapArray(element_filter, 1, spatial_dimension, false, _ek_regular); this->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Material::~Material() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::initialize() { registerParam("rho" , rho , Real(0.) , _pat_parsable | _pat_modifiable, "Density"); registerParam("name" , name , std::string(), _pat_parsable | _pat_readable); registerParam("finite_deformation" , finite_deformation , false , _pat_parsable | _pat_readable, "Is finite deformation"); registerParam("inelastic_deformation", inelastic_deformation, false , _pat_internal, "Is inelastic deformation"); /// allocate gradu stress for local elements eigengradu.initialize(spatial_dimension * spatial_dimension); gradu.initialize(spatial_dimension * spatial_dimension); stress.initialize(spatial_dimension * spatial_dimension); this->model->registerEventHandler(*this); } /* -------------------------------------------------------------------------- */ void Material::initMaterial() { AKANTU_DEBUG_IN(); if(finite_deformation) { this->piola_kirchhoff_2.initialize(spatial_dimension * spatial_dimension); if(use_previous_stress) this->piola_kirchhoff_2.initializeHistory(); this->green_strain.initialize(spatial_dimension * spatial_dimension); } if(use_previous_stress) this->stress.initializeHistory(); if(use_previous_gradu) this->gradu.initializeHistory(); for (std::map *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->resize(); for (std::map *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->resize(); for (std::map *>::iterator it = internal_vectors_bool.begin(); it != internal_vectors_bool.end(); ++it) it->second->resize(); is_init = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::savePreviousState() { AKANTU_DEBUG_IN(); for (std::map *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) { if(it->second->hasHistory()) it->second->saveCurrentValues(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the residual by assembling @f$\int_{e} \sigma_e \frac{\partial * \varphi}{\partial X} dX @f$ * * @param[in] displacements nodes displacements * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ void Material::updateResidual(GhostType ghost_type) { AKANTU_DEBUG_IN(); computeAllStresses(ghost_type); assembleResidual(ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::assembleResidual(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); if(!finite_deformation){ Array & residual = const_cast &>(model->getResidual()); Mesh & mesh = fem->getMesh(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { Array & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element) { const Array & shapes_derivatives = fem->getShapesDerivatives(*it, ghost_type); UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); UInt nb_quadrature_points = fem->getNbIntegrationPoints(*it, ghost_type); /// compute @f$\sigma \frac{\partial \varphi}{\partial X}@f$ by @f$\mathbf{B}^t \mathbf{\sigma}_q@f$ Array * sigma_dphi_dx = new Array(nb_element*nb_quadrature_points, size_of_shapes_derivatives, "sigma_x_dphi_/_dX"); Array * shapesd_filtered = new Array(0, size_of_shapes_derivatives, "filtered shapesd"); FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered, *it, ghost_type, elem_filter); Array & stress_vect = this->stress(*it, ghost_type); Array::matrix_iterator sigma = stress_vect.begin(spatial_dimension, spatial_dimension); Array::matrix_iterator B = shapesd_filtered->begin(spatial_dimension, nb_nodes_per_element); Array::matrix_iterator Bt_sigma_it = sigma_dphi_dx->begin(spatial_dimension, nb_nodes_per_element); for (UInt q = 0; q < nb_element*nb_quadrature_points; ++q, ++sigma, ++B, ++Bt_sigma_it) Bt_sigma_it->mul(*sigma, *B); delete shapesd_filtered; /** * compute @f$\int \sigma * \frac{\partial \varphi}{\partial X}dX@f$ by @f$ \sum_q \mathbf{B}^t * \mathbf{\sigma}_q \overline w_q J_q@f$ */ Array * int_sigma_dphi_dx = new Array(nb_element, nb_nodes_per_element * spatial_dimension, "int_sigma_x_dphi_/_dX"); fem->integrate(*sigma_dphi_dx, *int_sigma_dphi_dx, size_of_shapes_derivatives, *it, ghost_type, elem_filter); delete sigma_dphi_dx; /// assemble fem->assembleArray(*int_sigma_dphi_dx, residual, model->getDOFSynchronizer().getLocalDOFEquationNumbers(), residual.getNbComponent(), *it, ghost_type, elem_filter, -1); delete int_sigma_dphi_dx; } } } else{ switch (spatial_dimension){ case 1: this->assembleResidual<1>(ghost_type); break; case 2: this->assembleResidual<2>(ghost_type); break; case 3: this->assembleResidual<3>(ghost_type); break; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the stress from the gradu * * @param[in] current_position nodes postition + displacements * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ void Material::computeAllStresses(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); Mesh::type_iterator it = fem->getMesh().firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = fem->getMesh().lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { Array & elem_filter = element_filter(*it, ghost_type); if (elem_filter.getSize() == 0) continue; Array & gradu_vect = gradu(*it, ghost_type); /// compute @f$\nabla u@f$ fem->gradientOnIntegrationPoints(model->getDisplacement(), gradu_vect, spatial_dimension, *it, ghost_type, elem_filter); gradu_vect -= eigengradu(*it, ghost_type); /// compute @f$\mathbf{\sigma}_q@f$ from @f$\nabla u@f$ computeStress(*it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computeAllCauchyStresses(GhostType ghost_type) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(finite_deformation,"The Cauchy stress can only be computed if you are working in finite deformation."); //resizeInternalArray(stress); Mesh::type_iterator it = fem->getMesh().firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = fem->getMesh().lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) switch (spatial_dimension){ case 1: this->computeCauchyStress<1>(*it, ghost_type); break; case 2: this->computeCauchyStress<2>(*it, ghost_type); break; case 3: this->computeCauchyStress<3>(*it, ghost_type); break; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::computeCauchyStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array::matrix_iterator gradu_it = this->gradu(el_type, ghost_type).begin(dim, dim); Array::matrix_iterator gradu_end = this->gradu(el_type, ghost_type).end(dim, dim); Array::matrix_iterator piola_it = this->piola_kirchhoff_2(el_type, ghost_type).begin(dim, dim); Array::matrix_iterator stress_it = this->stress(el_type, ghost_type).begin(dim, dim); Matrix F_tensor(dim, dim); for (; gradu_it != gradu_end; ++gradu_it, ++piola_it, ++stress_it) { Matrix & grad_u = *gradu_it; Matrix & piola = *piola_it; Matrix & sigma = *stress_it; gradUToF (grad_u, F_tensor); this->computeCauchyStressOnQuad(F_tensor, piola, sigma); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::setToSteadyState(GhostType ghost_type) { AKANTU_DEBUG_IN(); const Array & displacement = model->getDisplacement(); //resizeInternalArray(gradu); UInt spatial_dimension = model->getSpatialDimension(); Mesh::type_iterator it = fem->getMesh().firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = fem->getMesh().lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { Array & elem_filter = element_filter(*it, ghost_type); Array & gradu_vect = gradu(*it, ghost_type); /// compute @f$\nabla u@f$ fem->gradientOnIntegrationPoints(displacement, gradu_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(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { if(finite_deformation){ switch (spatial_dimension) { case 1: { assembleStiffnessMatrixNL < 1 > (*it, ghost_type); assembleStiffnessMatrixL2 < 1 > (*it, ghost_type); break; } case 2: { assembleStiffnessMatrixNL < 2 > (*it, ghost_type); assembleStiffnessMatrixL2 < 2 > (*it, ghost_type); break; } case 3: { assembleStiffnessMatrixNL < 3 > (*it, ghost_type); assembleStiffnessMatrixL2 < 3 > (*it, ghost_type); break; } } } else { switch(spatial_dimension) { case 1: { assembleStiffnessMatrix<1>(*it, ghost_type); break; } case 2: { assembleStiffnessMatrix<2>(*it, ghost_type); break; } case 3: { assembleStiffnessMatrix<3>(*it, ghost_type); break; } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array & elem_filter = element_filter(type, ghost_type); if (elem_filter.getSize()) { SparseMatrix & K = const_cast(model->getStiffnessMatrix()); const Array & shapes_derivatives = fem->getShapesDerivatives(type, ghost_type); Array & gradu_vect = gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = fem->getNbIntegrationPoints(type, ghost_type); gradu_vect.resize(nb_quadrature_points * nb_element); fem->gradientOnIntegrationPoints(model->getDisplacement(), gradu_vect, dim, type, ghost_type, elem_filter); UInt tangent_size = getTangentStiffnessVoigtSize(dim); Array * tangent_stiffness_matrix = new Array(nb_element*nb_quadrature_points, tangent_size * tangent_size, "tangent_stiffness_matrix"); tangent_stiffness_matrix->clear(); computeTangentModuli(type, *tangent_stiffness_matrix, ghost_type); Array * shapesd_filtered = new Array(0, dim * nb_nodes_per_element, "filtered shapesd"); FEEngine::filterElementalData(fem->getMesh(), shapes_derivatives, *shapesd_filtered, type, ghost_type, elem_filter); /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_d_b_size = dim * nb_nodes_per_element; Array * bt_d_b = new Array(nb_element * nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B"); Matrix B(tangent_size, dim * nb_nodes_per_element); Matrix Bt_D(dim * nb_nodes_per_element, tangent_size); Array::matrix_iterator shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element); Array::matrix_iterator Bt_D_B_it = bt_d_b->begin(dim*nb_nodes_per_element, dim*nb_nodes_per_element); Array::matrix_iterator D_it = tangent_stiffness_matrix->begin(tangent_size, tangent_size); Array::matrix_iterator D_end = tangent_stiffness_matrix->end (tangent_size, tangent_size); for(; D_it != D_end; ++D_it, ++Bt_D_B_it, ++shapes_derivatives_filtered_it) { Matrix & D = *D_it; Matrix & Bt_D_B = *Bt_D_B_it; VoigtHelper::transferBMatrixToSymVoigtBMatrix( *shapes_derivatives_filtered_it, B, nb_nodes_per_element); Bt_D.mul(B, D); Bt_D_B.mul(Bt_D, B); } delete tangent_stiffness_matrix; delete shapesd_filtered; /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array * K_e = new Array(nb_element, bt_d_b_size * bt_d_b_size, "K_e"); fem->integrate(*bt_d_b, *K_e, bt_d_b_size * bt_d_b_size, type, ghost_type, elem_filter); delete bt_d_b; fem->assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, elem_filter); delete K_e; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::assembleStiffnessMatrixNL(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); SparseMatrix & K = const_cast (model->getStiffnessMatrix()); const Array & shapes_derivatives = fem->getShapesDerivatives(type, ghost_type); Array & elem_filter = element_filter(type, ghost_type); //Array & gradu_vect = delta_gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = fem->getNbIntegrationPoints(type, ghost_type); //gradu_vect.resize(nb_quadrature_points * nb_element); // fem->gradientOnIntegrationPoints(model->getIncrement(), gradu_vect, // dim, type, ghost_type, &elem_filter); Array * shapes_derivatives_filtered = new Array (nb_element * nb_quadrature_points, dim * nb_nodes_per_element, "shapes derivatives filtered"); Array::const_matrix_iterator shapes_derivatives_it = shapes_derivatives.begin(spatial_dimension, nb_nodes_per_element); Array::matrix_iterator shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, nb_nodes_per_element); UInt * elem_filter_val = elem_filter.storage(); for (UInt e = 0; e < nb_element; ++e, ++elem_filter_val) for (UInt q = 0; q < nb_quadrature_points; ++q, ++shapes_derivatives_filtered_it) *shapes_derivatives_filtered_it = shapes_derivatives_it[*elem_filter_val * nb_quadrature_points + q]; /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_s_b_size = dim * nb_nodes_per_element; Array * bt_s_b = new Array (nb_element * nb_quadrature_points, bt_s_b_size * bt_s_b_size, "B^t*D*B"); UInt piola_matrix_size = getCauchyStressMatrixSize(dim); Matrix B(piola_matrix_size, bt_s_b_size); Matrix Bt_S(bt_s_b_size, piola_matrix_size); Matrix S(piola_matrix_size, piola_matrix_size); shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, nb_nodes_per_element); Array::matrix_iterator Bt_S_B_it = bt_s_b->begin(bt_s_b_size, bt_s_b_size); Array::matrix_iterator Bt_S_B_end = bt_s_b->end(bt_s_b_size, bt_s_b_size); Array::matrix_iterator piola_it = piola_kirchhoff_2(type, ghost_type).begin(dim, dim); for (; Bt_S_B_it != Bt_S_B_end; ++Bt_S_B_it, ++shapes_derivatives_filtered_it, ++piola_it) { Matrix & Bt_S_B = *Bt_S_B_it; Matrix & Piola_kirchhoff_matrix = *piola_it; setCauchyStressMatrix< dim >(Piola_kirchhoff_matrix, S); VoigtHelper::transferBMatrixToBNL(*shapes_derivatives_filtered_it, B, nb_nodes_per_element); Bt_S.mul < true, false > (B, S); Bt_S_B.mul < false, false > (Bt_S, B); } delete shapes_derivatives_filtered; /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array * K_e = new Array (nb_element, bt_s_b_size * bt_s_b_size, "K_e"); fem->integrate(*bt_s_b, *K_e, bt_s_b_size * bt_s_b_size, type, ghost_type, elem_filter); delete bt_s_b; fem->assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, elem_filter); delete K_e; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::assembleStiffnessMatrixL2(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); SparseMatrix & K = const_cast (model->getStiffnessMatrix()); const Array & shapes_derivatives = fem->getShapesDerivatives(type, ghost_type); Array & elem_filter = element_filter(type, ghost_type); Array & gradu_vect = gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = fem->getNbIntegrationPoints(type, ghost_type); gradu_vect.resize(nb_quadrature_points * nb_element); fem->gradientOnIntegrationPoints(model->getDisplacement(), gradu_vect, dim, type, ghost_type, elem_filter); UInt tangent_size = getTangentStiffnessVoigtSize(dim); Array * tangent_stiffness_matrix = new Array (nb_element*nb_quadrature_points, tangent_size * tangent_size, "tangent_stiffness_matrix"); tangent_stiffness_matrix->clear(); computeTangentModuli(type, *tangent_stiffness_matrix, ghost_type); Array * shapes_derivatives_filtered = new Array (nb_element * nb_quadrature_points, dim * nb_nodes_per_element, "shapes derivatives filtered"); Array::const_matrix_iterator shapes_derivatives_it = shapes_derivatives.begin(spatial_dimension, nb_nodes_per_element); Array::matrix_iterator shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, nb_nodes_per_element); UInt * elem_filter_val = elem_filter.storage(); for (UInt e = 0; e < nb_element; ++e, ++elem_filter_val) for (UInt q = 0; q < nb_quadrature_points; ++q, ++shapes_derivatives_filtered_it) *shapes_derivatives_filtered_it = shapes_derivatives_it[*elem_filter_val * nb_quadrature_points + q]; /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_d_b_size = dim * nb_nodes_per_element; Array * bt_d_b = new Array (nb_element * nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B"); Matrix B(tangent_size, dim * nb_nodes_per_element); Matrix B2(tangent_size, dim * nb_nodes_per_element); Matrix Bt_D(dim * nb_nodes_per_element, tangent_size); shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, nb_nodes_per_element); Array::matrix_iterator Bt_D_B_it = bt_d_b->begin(dim*nb_nodes_per_element, dim * nb_nodes_per_element); Array::matrix_iterator grad_u_it = gradu_vect.begin(dim, dim); Array::matrix_iterator D_it = tangent_stiffness_matrix->begin(tangent_size, tangent_size); Array::matrix_iterator D_end = tangent_stiffness_matrix->end(tangent_size, tangent_size); for (; D_it != D_end; ++D_it, ++Bt_D_B_it, ++shapes_derivatives_filtered_it, ++grad_u_it) { Matrix & grad_u = *grad_u_it; Matrix & D = *D_it; Matrix & Bt_D_B = *Bt_D_B_it; //transferBMatrixToBL1 (*shapes_derivatives_filtered_it, B, nb_nodes_per_element); VoigtHelper::transferBMatrixToSymVoigtBMatrix(*shapes_derivatives_filtered_it, B, nb_nodes_per_element); VoigtHelper::transferBMatrixToBL2(*shapes_derivatives_filtered_it, grad_u, B2, nb_nodes_per_element); B += B2; Bt_D.mul < true, false > (B, D); Bt_D_B.mul < false, false > (Bt_D, B); } delete tangent_stiffness_matrix; delete shapes_derivatives_filtered; /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array * K_e = new Array (nb_element, bt_d_b_size * bt_d_b_size, "K_e"); fem->integrate(*bt_d_b, *K_e, bt_d_b_size * bt_d_b_size, type, ghost_type, elem_filter); delete bt_d_b; fem->assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, elem_filter); delete K_e; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::assembleResidual(GhostType ghost_type){ AKANTU_DEBUG_IN(); Array & residual = const_cast &> (model->getResidual()); Mesh & mesh = fem->getMesh(); Mesh::type_iterator it = element_filter.firstType(dim, ghost_type); Mesh::type_iterator last_type = element_filter.lastType(dim, ghost_type); for (; it != last_type; ++it) { const Array & shapes_derivatives = fem->getShapesDerivatives(*it, ghost_type); Array & elem_filter = element_filter(*it, ghost_type); if (elem_filter.getSize() == 0) continue; UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent(); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); UInt nb_quadrature_points = fem->getNbIntegrationPoints(*it, ghost_type); Array * shapesd_filtered = new Array(0, size_of_shapes_derivatives, "filtered shapesd"); FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered, *it, ghost_type, elem_filter); Array::matrix_iterator shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element); //Set stress vectors UInt stress_size = getTangentStiffnessVoigtSize(dim); //Set matrices B and BNL* UInt bt_s_size = dim * nb_nodes_per_element; Array * bt_s = new Array (nb_element * nb_quadrature_points, bt_s_size, "B^t*S"); Array::matrix_iterator grad_u_it = this->gradu(*it, ghost_type).begin(dim, dim); Array::matrix_iterator grad_u_end = this->gradu(*it, ghost_type).end(dim, dim); Array::matrix_iterator stress_it = this->piola_kirchhoff_2(*it, ghost_type).begin(dim, dim); shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element); Array::matrix_iterator bt_s_it = bt_s->begin(bt_s_size, 1); Matrix S_vect(stress_size, 1); Matrix B_tensor(stress_size, bt_s_size); Matrix B2_tensor(stress_size, bt_s_size); for (; grad_u_it != grad_u_end; ++grad_u_it, ++stress_it, ++shapes_derivatives_filtered_it, ++bt_s_it) { Matrix & grad_u = *grad_u_it; Matrix & r_it = *bt_s_it; Matrix & S_it = *stress_it; setCauchyStressArray (S_it, S_vect); VoigtHelper::transferBMatrixToSymVoigtBMatrix(*shapes_derivatives_filtered_it, B_tensor, nb_nodes_per_element); VoigtHelper::transferBMatrixToBL2(*shapes_derivatives_filtered_it, grad_u, B2_tensor, nb_nodes_per_element); B_tensor += B2_tensor; r_it.mul < true, false > (B_tensor, S_vect); } delete shapesd_filtered; /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array * r_e = new Array (nb_element, bt_s_size, "r_e"); fem->integrate(*bt_s, *r_e, bt_s_size, *it, ghost_type, elem_filter); delete bt_s; fem->assembleArray(*r_e, residual, model->getDOFSynchronizer().getLocalDOFEquationNumbers(), residual.getNbComponent(), *it, ghost_type, elem_filter, -1); delete r_e; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computeAllStressesFromTangentModuli(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { switch(spatial_dimension) { case 1: { computeAllStressesFromTangentModuli<1>(*it, ghost_type); break; } case 2: { computeAllStressesFromTangentModuli<2>(*it, ghost_type); break; } case 3: { computeAllStressesFromTangentModuli<3>(*it, ghost_type); break; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::computeAllStressesFromTangentModuli(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); const Array & shapes_derivatives = fem->getShapesDerivatives(type, ghost_type); Array & elem_filter = element_filter(type, ghost_type); Array & gradu_vect = gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = fem->getNbIntegrationPoints(type, ghost_type); gradu_vect.resize(nb_quadrature_points * nb_element); Array & disp = model->getDisplacement(); fem->gradientOnIntegrationPoints(disp, gradu_vect, dim, type, ghost_type, elem_filter); UInt tangent_moduli_size = getTangentStiffnessVoigtSize(dim); Array * tangent_moduli_tensors = new Array(nb_element*nb_quadrature_points, tangent_moduli_size * tangent_moduli_size, "tangent_moduli_tensors"); tangent_moduli_tensors->clear(); computeTangentModuli(type, *tangent_moduli_tensors, ghost_type); Array * shapesd_filtered = new Array(0, dim* nb_nodes_per_element, "filtered shapesd"); FEEngine::filterElementalData(fem->getMesh(), shapes_derivatives, *shapesd_filtered, type, ghost_type, elem_filter); Array filtered_u(nb_element, nb_nodes_per_element * spatial_dimension); FEEngine::extractNodalToElementField(fem->getMesh(), disp, filtered_u, type, ghost_type, elem_filter); /// compute @f$\mathbf{D} \mathbf{B} \mathbf{u}@f$ Array::matrix_iterator shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element); Array::matrix_iterator D_it = tangent_moduli_tensors->begin(tangent_moduli_size, tangent_moduli_size); Array::matrix_iterator sigma_it = stress(type, ghost_type).begin(spatial_dimension, spatial_dimension); Array::vector_iterator u_it = filtered_u.begin(spatial_dimension * nb_nodes_per_element); Matrix B(tangent_moduli_size, spatial_dimension * nb_nodes_per_element); Vector Bu(tangent_moduli_size); Vector DBu(tangent_moduli_size); for (UInt e = 0; e < nb_element; ++e, ++u_it) { for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_it, ++shapes_derivatives_filtered_it, ++sigma_it) { Vector & u = *u_it; Matrix & sigma = *sigma_it; Matrix & D = *D_it; VoigtHelper::transferBMatrixToSymVoigtBMatrix(*shapes_derivatives_filtered_it, B, nb_nodes_per_element); Bu.mul(B, u); DBu.mul(D, Bu); // Voigt notation to full symmetric tensor for (UInt i = 0; i < dim; ++i) sigma(i, i) = DBu(i); if(dim == 2) { sigma(0,1) = sigma(1,0) = DBu(2); } else if(dim == 3) { sigma(1,2) = sigma(2,1) = DBu(3); sigma(0,2) = sigma(2,0) = DBu(4); sigma(0,1) = sigma(1,0) = DBu(5); } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computePotentialEnergyByElements() { AKANTU_DEBUG_IN(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension); Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension); for(; it != last_type; ++it) { computePotentialEnergy(*it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if(!potential_energy.exists(el_type, ghost_type)) { UInt nb_element = element_filter(el_type, ghost_type).getSize(); UInt nb_quadrature_points = fem->getNbIntegrationPoints(el_type, _not_ghost); potential_energy.alloc(nb_element * nb_quadrature_points, 1, el_type, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real Material::getPotentialEnergy() { AKANTU_DEBUG_IN(); Real epot = 0.; computePotentialEnergyByElements(); /// integrate the potential energy for each type of elements Mesh::type_iterator it = element_filter.firstType(spatial_dimension); Mesh::type_iterator last_type = element_filter.lastType(spatial_dimension); for(; it != last_type; ++it) { epot += fem->integrate(potential_energy(*it, _not_ghost), *it, _not_ghost, element_filter(*it, _not_ghost)); } AKANTU_DEBUG_OUT(); return epot; } /* -------------------------------------------------------------------------- */ Real Material::getPotentialEnergy(ElementType & type, UInt index) { AKANTU_DEBUG_IN(); Real epot = 0.; Vector epot_on_quad_points(fem->getNbIntegrationPoints(type)); computePotentialEnergyByElement(type, index, epot_on_quad_points); epot = fem->integrate(epot_on_quad_points, type, element_filter(type)(index)); AKANTU_DEBUG_OUT(); return epot; } /* -------------------------------------------------------------------------- */ Real Material::getEnergy(std::string type) { AKANTU_DEBUG_IN(); if(type == "potential") return getPotentialEnergy(); AKANTU_DEBUG_OUT(); return 0.; } /* -------------------------------------------------------------------------- */ Real Material::getEnergy(std::string energy_id, ElementType type, UInt index) { AKANTU_DEBUG_IN(); if(energy_id == "potential") return getPotentialEnergy(type, index); AKANTU_DEBUG_OUT(); return 0.; } /* -------------------------------------------------------------------------- */ void Material::initElementalFieldInterpolation(const ElementTypeMapArray & interpolation_points_coordinates) { AKANTU_DEBUG_IN(); this->fem->initElementalFieldInterpolationFromIntegrationPoints(interpolation_points_coordinates, this->interpolation_points_matrices, this->interpolation_inverse_coordinates, &(this->element_filter)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::interpolateStress(ElementTypeMapArray & result, const GhostType ghost_type) { this->fem->interpolateElementalFieldFromIntegrationPoints(this->stress, this->interpolation_points_matrices, this->interpolation_inverse_coordinates, result, ghost_type, &(this->element_filter)); } /* -------------------------------------------------------------------------- */ void Material::interpolateStressOnFacets(ElementTypeMapArray & result, ElementTypeMapArray & by_elem_result, const GhostType ghost_type) { interpolateStress(by_elem_result, ghost_type); UInt stress_size = this->stress.getNbComponent(); const Mesh & mesh = this->model->getMesh(); const Mesh & mesh_facets = mesh.getMeshFacets(); Mesh::type_iterator it = this->element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last = this->element_filter.lastType(spatial_dimension, ghost_type); for (; it != last; ++it) { ElementType type = *it; Array & elem_fil = element_filter(type, ghost_type); Array & by_elem_res = by_elem_result(type, ghost_type); UInt nb_element = elem_fil.getSize(); UInt nb_element_full = this->model->getMesh().getNbElement(type, ghost_type); UInt nb_interpolation_points_per_elem = by_elem_res.getSize() / nb_element_full; const Array & facet_to_element = mesh_facets.getSubelementToElement(type, ghost_type); ElementType type_facet = Mesh::getFacetType(type); UInt nb_facet_per_elem = facet_to_element.getNbComponent(); UInt nb_quad_per_facet = nb_interpolation_points_per_elem / nb_facet_per_elem; Element element_for_comparison(type, 0, ghost_type); const Array< std::vector > * element_to_facet = NULL; GhostType current_ghost_type = _casper; Array * result_vec = NULL; Array::const_matrix_iterator result_it = by_elem_res.begin_reinterpret(stress_size, nb_interpolation_points_per_elem, nb_element_full); for (UInt el = 0; el < nb_element; ++el){ UInt global_el = elem_fil(el); element_for_comparison.element = global_el; for (UInt f = 0; f < nb_facet_per_elem; ++f) { Element facet_elem = facet_to_element(global_el, f); UInt global_facet = facet_elem.element; if (facet_elem.ghost_type != current_ghost_type) { current_ghost_type = facet_elem.ghost_type; element_to_facet = &mesh_facets.getElementToSubelement(type_facet, current_ghost_type); result_vec = &result(type_facet, current_ghost_type); } bool is_second_element = (*element_to_facet)(global_facet)[0] != element_for_comparison; for (UInt q = 0; q < nb_quad_per_facet; ++q) { Vector result_local(result_vec->storage() + (global_facet * nb_quad_per_facet + q) * result_vec->getNbComponent() + is_second_element * stress_size, stress_size); const Matrix & result_tmp(result_it[global_el]); result_local = result_tmp(f * nb_quad_per_facet + q); } } } } } /* -------------------------------------------------------------------------- */ template const Array & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); return NULL; } /* -------------------------------------------------------------------------- */ template Array & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); return NULL; } /* -------------------------------------------------------------------------- */ template<> const Array & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) const { std::stringstream sstr; std::string ghost_id = ""; if (ghost_type == _ghost) ghost_id = ":ghost"; sstr << getID() << ":" << vect_id << ":" << type << ghost_id; ID fvect_id = sstr.str(); try { return Memory::getArray(fvect_id); } catch(debug::Exception & e) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" < Array & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) { std::stringstream sstr; std::string ghost_id = ""; if (ghost_type == _ghost) ghost_id = ":ghost"; sstr << getID() << ":" << vect_id << ":" << type << ghost_id; ID fvect_id = sstr.str(); try { return Memory::getArray(fvect_id); } catch(debug::Exception & e) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain a vector " << vect_id << "(" << fvect_id << ") [" << e << "]"); } } +/* -------------------------------------------------------------------------- */ +template<> +const Array & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) const { + std::stringstream sstr; + std::string ghost_id = ""; + if (ghost_type == _ghost) ghost_id = ":ghost"; + sstr << getID() << ":" << vect_id << ":" << type << ghost_id; + + ID fvect_id = sstr.str(); + try { + return Memory::getArray(fvect_id); + } catch(debug::Exception & e) { + AKANTU_SILENT_EXCEPTION("The material " << name << "(" < +Array & Material::getArray(const ID & vect_id, const ElementType & type, const GhostType & ghost_type) { + std::stringstream sstr; + std::string ghost_id = ""; + if (ghost_type == _ghost) ghost_id = ":ghost"; + sstr << getID() << ":" << vect_id << ":" << type << ghost_id; + + ID fvect_id = sstr.str(); + try { + return Memory::getArray(fvect_id); + } catch(debug::Exception & e) { + AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain a vector " << vect_id << "(" << fvect_id << ") [" << e << "]"); + } +} + /* -------------------------------------------------------------------------- */ template const InternalField & Material::getInternal(const ID & int_id) const { AKANTU_DEBUG_TO_IMPLEMENT(); return NULL; } /* -------------------------------------------------------------------------- */ template InternalField & Material::getInternal(const ID & int_id) { AKANTU_DEBUG_TO_IMPLEMENT(); return NULL; } /* -------------------------------------------------------------------------- */ template<> const InternalField & Material::getInternal(const ID & int_id) const { std::map *>::const_iterator it = internal_vectors_real.find(getID() + ":" + int_id); if(it == internal_vectors_real.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ template<> InternalField & Material::getInternal(const ID & int_id) { std::map *>::iterator it = internal_vectors_real.find(getID() + ":" + int_id); if(it == internal_vectors_real.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ template<> const InternalField & Material::getInternal(const ID & int_id) const { std::map *>::const_iterator it = internal_vectors_uint.find(getID() + ":" + int_id); if(it == internal_vectors_uint.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ template<> InternalField & Material::getInternal(const ID & int_id) { std::map *>::iterator it = internal_vectors_uint.find(getID() + ":" + int_id); if(it == internal_vectors_uint.end()) { AKANTU_SILENT_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ void Material::addElements(const Array & elements_to_add) { AKANTU_DEBUG_IN(); UInt mat_id = model->getInternalIndexFromID(getID()); Array::const_iterator el_begin = elements_to_add.begin(); Array::const_iterator el_end = elements_to_add.end(); for(;el_begin != el_end; ++el_begin) { const Element & element = *el_begin; Array & mat_indexes = model->getMaterialByElement (element.type, element.ghost_type); Array & mat_loc_num = model->getMaterialLocalNumbering(element.type, element.ghost_type); UInt index = this->addElement(element.type, element.element, element.ghost_type); mat_indexes(element.element) = mat_id; mat_loc_num(element.element) = index; } this->resizeInternals(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::removeElements(const Array & elements_to_remove) { AKANTU_DEBUG_IN(); Array::const_iterator el_begin = elements_to_remove.begin(); Array::const_iterator el_end = elements_to_remove.end(); if(el_begin==el_end) return; ElementTypeMapArray material_local_new_numbering("remove mat filter elem", getID()); Element element; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; element.ghost_type = ghost_type; ElementTypeMapArray::type_iterator it = element_filter.firstType(_all_dimensions, ghost_type, _ek_not_defined); ElementTypeMapArray::type_iterator end = element_filter.lastType(_all_dimensions, ghost_type, _ek_not_defined); for(; it != end; ++it) { ElementType type = *it; element.type = type; Array & elem_filter = this->element_filter(type, ghost_type); Array & mat_loc_num = this->model->getMaterialLocalNumbering(type, ghost_type); if(!material_local_new_numbering.exists(type, ghost_type)) material_local_new_numbering.alloc(elem_filter.getSize(), 1, type, ghost_type); Array & mat_renumbering = material_local_new_numbering(type, ghost_type); UInt nb_element = elem_filter.getSize(); element.kind=(*el_begin).kind; Array elem_filter_tmp; UInt new_id = 0; for (UInt el = 0; el < nb_element; ++el) { element.element = elem_filter(el); if(std::find(el_begin, el_end, element) == el_end) { elem_filter_tmp.push_back(element.element); mat_renumbering(el) = new_id; mat_loc_num(element.element) = new_id; ++new_id; } else { mat_renumbering(el) = UInt(-1); } } elem_filter.resize(elem_filter_tmp.getSize()); elem_filter.copy(elem_filter_tmp); } } for (std::map *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->removeIntegrationPoints(material_local_new_numbering); for (std::map *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->removeIntegrationPoints(material_local_new_numbering); for (std::map *>::iterator it = internal_vectors_bool.begin(); it != internal_vectors_bool.end(); ++it) it->second->removeIntegrationPoints(material_local_new_numbering); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::resizeInternals() { AKANTU_DEBUG_IN(); for (std::map *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->resize(); for (std::map *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->resize(); for (std::map *>::iterator it = internal_vectors_bool.begin(); it != internal_vectors_bool.end(); ++it) it->second->resize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::onElementsAdded(__attribute__((unused)) const Array & element_list, __attribute__((unused)) const NewElementsEvent & event) { this->resizeInternals(); } /* -------------------------------------------------------------------------- */ void Material::onElementsRemoved(const Array & element_list, const ElementTypeMapArray & new_numbering, __attribute__((unused)) const RemovedElementsEvent & event) { UInt my_num = model->getInternalIndexFromID(getID()); ElementTypeMapArray material_local_new_numbering("remove mat filter elem", getID()); Array::const_iterator el_begin = element_list.begin(); Array::const_iterator el_end = element_list.end(); for (ghost_type_t::iterator g = ghost_type_t::begin(); g != ghost_type_t::end(); ++g) { GhostType gt = *g; ElementTypeMapArray::type_iterator it = new_numbering.firstType(_all_dimensions, gt, _ek_not_defined); ElementTypeMapArray::type_iterator end = new_numbering.lastType (_all_dimensions, gt, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; if(element_filter.exists(type, gt) && element_filter(type, gt).getSize()){ Array & elem_filter = element_filter(type, gt); Array & mat_indexes = this->model->getMaterialByElement (*it, gt); Array & mat_loc_num = this->model->getMaterialLocalNumbering(*it, gt); UInt nb_element = this->model->getMesh().getNbElement(type, gt); // all materials will resize of the same size... mat_indexes.resize(nb_element); mat_loc_num.resize(nb_element); if(!material_local_new_numbering.exists(type, gt)) material_local_new_numbering.alloc(elem_filter.getSize(), 1, type, gt); Array & mat_renumbering = material_local_new_numbering(type, gt); const Array & renumbering = new_numbering(type, gt); Array elem_filter_tmp; UInt ni = 0; Element el; el.type = type; el.ghost_type = gt; el.kind = Mesh::getKind(type); for (UInt i = 0; i < elem_filter.getSize(); ++i) { el.element = elem_filter(i); if(std::find(el_begin, el_end, el) == el_end) { UInt new_el = renumbering(el.element); AKANTU_DEBUG_ASSERT(new_el != UInt(-1), "A not removed element as been badly renumbered"); elem_filter_tmp.push_back(new_el); mat_renumbering(i) = ni; mat_indexes(new_el) = my_num; mat_loc_num(new_el) = ni; ++ni; } else { mat_renumbering(i) = UInt(-1); } } elem_filter.resize(elem_filter_tmp.getSize()); elem_filter.copy(elem_filter_tmp); } } } for (std::map *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->removeIntegrationPoints(material_local_new_numbering); for (std::map *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->removeIntegrationPoints(material_local_new_numbering); for (std::map *>::iterator it = internal_vectors_bool.begin(); it != internal_vectors_bool.end(); ++it) it->second->removeIntegrationPoints(material_local_new_numbering); } /* -------------------------------------------------------------------------- */ void Material::onBeginningSolveStep(const AnalysisMethod & method) { this->savePreviousState(); } /* -------------------------------------------------------------------------- */ void Material::onEndSolveStep(const AnalysisMethod & method) { ElementTypeMapArray::type_iterator it = this->element_filter.firstType(_all_dimensions, _not_ghost, _ek_not_defined); ElementTypeMapArray::type_iterator end = element_filter.lastType(_all_dimensions, _not_ghost, _ek_not_defined); for(; it != end; ++it) { this->updateEnergies(*it, _not_ghost); } } /* -------------------------------------------------------------------------- */ void Material::onDamageIteration() { this->savePreviousState(); } /* -------------------------------------------------------------------------- */ void Material::onDamageUpdate() { ElementTypeMapArray::type_iterator it = this->element_filter.firstType(_all_dimensions, _not_ghost, _ek_not_defined); ElementTypeMapArray::type_iterator end = element_filter.lastType(_all_dimensions, _not_ghost, _ek_not_defined); for(; it != end; ++it) { if(!this->potential_energy.exists(*it, _not_ghost)) { UInt nb_element = this->element_filter(*it, _not_ghost).getSize(); UInt nb_quadrature_points = this->fem->getNbIntegrationPoints(*it, _not_ghost); this->potential_energy.alloc(nb_element * nb_quadrature_points, 1, *it, _not_ghost); } this->updateEnergiesAfterDamage(*it, _not_ghost); } } /* -------------------------------------------------------------------------- */ void Material::onDump(){ if(this->isFiniteDeformation()) this->computeAllCauchyStresses(_not_ghost); } /* -------------------------------------------------------------------------- */ void Material::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); std::string type = getID().substr(getID().find_last_of(":") + 1); stream << space << "Material " << type << " [" << std::endl; Parsable::printself(stream, indent); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ inline ElementTypeMap Material::getInternalDataPerElem(const ID & id, const ElementKind & element_kind, const ID & fe_engine_id) const { std::map *>::const_iterator internal_array = internal_vectors_real.find(this->getID()+":"+id); if (internal_array == internal_vectors_real.end() || internal_array->second->getElementKind() != element_kind) AKANTU_EXCEPTION("Cannot find internal field " << id << " in material " << this->name); InternalField & internal = *internal_array->second; InternalField::type_iterator it = internal.firstType(internal.getSpatialDimension(), _not_ghost, element_kind); InternalField::type_iterator last_type = internal.lastType(internal.getSpatialDimension(), _not_ghost, element_kind); ElementTypeMap res; for(; it != last_type; ++it) { UInt nb_quadrature_points = 0; nb_quadrature_points = model->getFEEngine(fe_engine_id).getNbIntegrationPoints(*it); res(*it) = internal.getNbComponent() * nb_quadrature_points; } return res; } /* -------------------------------------------------------------------------- */ void Material::flattenInternal(const std::string & field_id, ElementTypeMapArray & internal_flat, const GhostType ghost_type, ElementKind element_kind) const { this->flattenInternalIntern(field_id, internal_flat, this->spatial_dimension, ghost_type, element_kind); } /* -------------------------------------------------------------------------- */ void Material::flattenInternalIntern(const std::string & field_id, ElementTypeMapArray & internal_flat, UInt spatial_dimension, const GhostType ghost_type, ElementKind element_kind, const ElementTypeMapArray * element_filter, const Mesh * mesh) const { typedef ElementTypeMapArray::type_iterator iterator; if(element_filter == NULL) element_filter = &(this->element_filter); if(mesh == NULL) mesh = &(this->model->mesh); iterator tit = element_filter->firstType(spatial_dimension, ghost_type, element_kind); iterator end = element_filter->lastType(spatial_dimension, ghost_type, element_kind); for (; tit != end; ++tit) { ElementType type = *tit; try { __attribute__((unused)) const Array & src_vect = this->getArray(field_id, type, ghost_type); } catch(debug::Exception & e) { continue; } const Array & src_vect = this->getArray(field_id, type, ghost_type); const Array & filter = (*element_filter)(type, ghost_type); // total number of elements for a given type UInt nb_element = mesh->getNbElement(type,ghost_type); // number of filtered elements UInt nb_element_src = filter.getSize(); // number of quadrature points per elem UInt nb_quad_per_elem = 0; // number of data per quadrature point UInt nb_data_per_quad = src_vect.getNbComponent(); if (!internal_flat.exists(type,ghost_type)) { internal_flat.alloc(nb_element * nb_quad_per_elem, nb_data_per_quad, type, ghost_type); } if (nb_element_src == 0) continue; nb_quad_per_elem = (src_vect.getSize() / nb_element_src); // number of data per element UInt nb_data = nb_quad_per_elem * src_vect.getNbComponent(); Array & dst_vect = internal_flat(type,ghost_type); dst_vect.resize(nb_element*nb_quad_per_elem); Array::const_scalar_iterator it = filter.begin(); Array::const_scalar_iterator end = filter.end(); Array::const_vector_iterator it_src = src_vect.begin_reinterpret(nb_data, nb_element_src); Array::vector_iterator it_dst = dst_vect.begin_reinterpret(nb_data, nb_element); for (; it != end ; ++it,++it_src) { it_dst[*it] = *it_src; } } }; /* -------------------------------------------------------------------------- */ /// extrapolate internal values void Material::extrapolateInternal(const ID & id, const Element & element, const Matrix & point, Matrix & extrapolated) { if (this->isInternal(id, element.kind)) { UInt nb_element = this->element_filter(element.type, element.ghost_type).getSize(); const ID name = this->getID() + ":" + id; UInt nb_quads = this->internal_vectors_real[name]->getFEEngine().getNbIntegrationPoints(element.type, element.ghost_type); const Array & internal = this->getArray(id, element.type, element.ghost_type); UInt nb_component = internal.getNbComponent(); Array::const_matrix_iterator internal_it = internal.begin_reinterpret(nb_component, nb_quads, nb_element); Element local_element = this->convertToLocalElement(element); /// instead of really extrapolating, here the value of the first GP /// is copied into the result vector. This works only for linear /// elements /// @todo extrapolate!!!! + AKANTU_DEBUG_WARNING("This is a fix, values are not truly extrapolated"); const Matrix & values = internal_it[local_element.element]; UInt index = 0; Vector tmp(nb_component); for (UInt j = 0; j < values.cols(); ++j) { tmp = values(j); if (tmp.norm() > 0) { index = j; - continue; + break; } } for (UInt i = 0; i < extrapolated.size(); ++i) { extrapolated(i) = values(index); } } else { Matrix default_values(extrapolated.rows(), extrapolated.cols(), 0.); extrapolated = default_values; } } +/* -------------------------------------------------------------------------- */ +void Material::applyEigenGradU(const Matrix & prescribed_eigen_grad_u, const GhostType ghost_type) { + + ElementTypeMapArray::type_iterator it + = this->element_filter.firstType(_all_dimensions, _not_ghost, _ek_not_defined); + ElementTypeMapArray::type_iterator end + = element_filter.lastType(_all_dimensions, _not_ghost, _ek_not_defined); + + for(; it != end; ++it) { + ElementType type = *it; + if (!element_filter(type, ghost_type).getSize()) + continue; + Array::matrix_iterator eigen_it = this->eigengradu(type, ghost_type).begin(spatial_dimension, + spatial_dimension); + Array::matrix_iterator eigen_end = this->eigengradu(type, ghost_type).end(spatial_dimension, + spatial_dimension); + for(; eigen_it != eigen_end; ++eigen_it) { + Matrix & current_eigengradu = *eigen_it; + current_eigengradu = prescribed_eigen_grad_u; + } + } +} + __END_AKANTU__ diff --git a/src/model/solid_mechanics/material.hh b/src/model/solid_mechanics/material.hh index fa8ad6361..2a6a4a0cd 100644 --- a/src/model/solid_mechanics/material.hh +++ b/src/model/solid_mechanics/material.hh @@ -1,633 +1,636 @@ /** * @file material.hh * * @author Marco Vocialta * @author Nicolas Richart * @author Daniel Pino Muñoz * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Sep 16 2014 * * @brief Mother class for all materials * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "aka_voigthelper.hh" #include "parser.hh" #include "parsable.hh" #include "data_accessor.hh" #include "internal_field.hh" #include "random_internal_field.hh" #include "solid_mechanics_model_event_handler.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_HH__ #define __AKANTU_MATERIAL_HH__ /* -------------------------------------------------------------------------- */ namespace akantu { class Model; class SolidMechanicsModel; } __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, * Array & tangent_matrix, * GhostType ghost_type = _not_ghost); * \endcode * */ class Material : public Memory, public DataAccessor, public Parsable, public MeshEventHandler, protected SolidMechanicsModelEventHandler { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: #if __cplusplus > 199711L Material(const Material & mat) = delete; Material & operator=(const Material & mat) = delete; #endif /// Initialize material with defaults Material(SolidMechanicsModel & model, const ID & id = ""); /// Initialize material with custom mesh & fe_engine Material(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id = ""); /// Destructor virtual ~Material(); protected: void initialize(); /* ------------------------------------------------------------------------ */ /* Function that materials can/should reimplement */ /* ------------------------------------------------------------------------ */ protected: /// constitutive law virtual void computeStress(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the tangent stiffness matrix virtual void computeTangentModuli(__attribute__((unused)) const ElementType & el_type, __attribute__((unused)) Array & tangent_matrix, __attribute__((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the potential energy virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the potential energy for an element virtual void computePotentialEnergyByElement(__attribute__((unused)) ElementType type, __attribute__((unused)) UInt index, __attribute__((unused)) Vector & epot_on_quad_points) { AKANTU_DEBUG_TO_IMPLEMENT(); } virtual void updateEnergies(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) { } virtual void updateEnergiesAfterDamage(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) {} /// set the material to steady state (to be implemented for materials that need it) virtual void setToSteadyState(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) { } /// function called to update the internal parameters when the modifiable /// parameters are modified virtual void updateInternalParameters() {} public: /// extrapolate internal values virtual void extrapolateInternal(const ID & id, const Element & element, const Matrix & points, Matrix & extrapolated); /// compute the p-wave speed in the material virtual Real getPushWaveSpeed(const Element & element) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the s-wave speed in the material virtual Real getShearWaveSpeed(const Element & element) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// get a material celerity to compute the stable time step (default: is the push wave speed) virtual Real getCelerity(const Element & element) const { return getPushWaveSpeed(element); } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: template void registerInternal(__attribute__((unused)) InternalField & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); } template void unregisterInternal(__attribute__((unused)) InternalField & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// initialize the material computed parameter virtual void initMaterial(); /// compute the residual for this material virtual void updateResidual(GhostType ghost_type = _not_ghost); /// assemble the residual for this material virtual void assembleResidual(GhostType ghost_type); /// Operations before and after solveStep in implicit virtual void beforeSolveStep() {} virtual void afterSolveStep() {} /// save the stress in the previous_stress if needed virtual void savePreviousState(); /// compute the stresses for this material virtual void computeAllStresses(GhostType ghost_type = _not_ghost); - virtual void computeAllNonLocalStresses(__attribute__((unused)) GhostType ghost_type = _not_ghost) {}; virtual void computeAllStressesFromTangentModuli(GhostType ghost_type = _not_ghost); virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost); /// set material to steady state void setToSteadyState(GhostType ghost_type = _not_ghost); /// compute the stiffness matrix virtual void assembleStiffnessMatrix(GhostType ghost_type); /// add an element to the local mesh filter inline UInt addElement(const ElementType & type, UInt element, const GhostType & ghost_type); /// add many elements at once void addElements(const Array & elements_to_add); /// remove many element at once void removeElements(const Array & elements_to_remove); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /** * interpolate stress on given positions for each element by means * of a geometrical interpolation on quadrature points */ void interpolateStress(ElementTypeMapArray & result, const GhostType ghost_type = _not_ghost); /** * interpolate stress on given positions for each element by means * of a geometrical interpolation on quadrature points and store the * results per facet */ void interpolateStressOnFacets(ElementTypeMapArray & result, ElementTypeMapArray & by_elem_result, const GhostType ghost_type = _not_ghost); /** * function to initialize the elemental field interpolation * function by inverting the quadrature points' coordinates */ void initElementalFieldInterpolation(const ElementTypeMapArray & interpolation_points_coordinates); /* ------------------------------------------------------------------------ */ /* Common part */ /* ------------------------------------------------------------------------ */ protected: /* ------------------------------------------------------------------------ */ inline UInt getTangentStiffnessVoigtSize(UInt spatial_dimension) const; /// compute the potential energy by element void computePotentialEnergyByElements(); /// resize the intenals arrays virtual void resizeInternals(); /* ------------------------------------------------------------------------ */ /* Finite deformation functions */ /* This functions area implementing what is described in the paper of Bathe */ /* et al, in IJNME, Finite Element Formulations For Large Deformation */ /* Dynamic Analysis, Vol 9, 353-386, 1975 */ /* ------------------------------------------------------------------------ */ protected: /// assemble the residual template void assembleResidual(GhostType ghost_type); /// Computation of Cauchy stress tensor in the case of finite deformation from /// the 2nd Piola-Kirchhoff for a given element type template void computeCauchyStress(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost); /// Computation the Cauchy stress the 2nd Piola-Kirchhoff and the deformation /// gradient template inline void computeCauchyStressOnQuad(const Matrix & F, const Matrix & S, Matrix & cauchy, const Real & C33 = 1.0) const; template void computeAllStressesFromTangentModuli(const ElementType & type, GhostType ghost_type); template void assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type); /// assembling in finite deformation template void assembleStiffnessMatrixNL(const ElementType & type, GhostType ghost_type); template void assembleStiffnessMatrixL2(const ElementType & type, GhostType ghost_type); /// Size of the Stress matrix for the case of finite deformation see: Bathe et /// al, IJNME, Vol 9, 353-386, 1975 inline UInt getCauchyStressMatrixSize(UInt spatial_dimension) const; /// Sets the stress matrix according to Bathe et al, IJNME, Vol 9, 353-386, 1975 template inline void setCauchyStressMatrix(const Matrix & S_t, Matrix & sigma); /// write the stress tensor in the Voigt notation. template inline void setCauchyStressArray(const Matrix & S_t, Matrix & sigma_voight); /* ------------------------------------------------------------------------ */ /* Conversion functions */ /* ------------------------------------------------------------------------ */ public: template static inline void gradUToF (const Matrix & grad_u, Matrix & F); static inline void rightCauchy(const Matrix & F, Matrix & C); static inline void leftCauchy (const Matrix & F, Matrix & B); template static inline void gradUToEpsilon(const Matrix & grad_u, Matrix & epsilon); template static inline void gradUToGreenStrain(const Matrix & grad_u, Matrix & epsilon); static inline Real stressToVonMises(const Matrix & stress); protected: /// converts global element to local element inline Element convertToLocalElement(const Element & global_element) const; /// converts local element to global element inline Element convertToGlobalElement(const Element & local_element) const; /// converts global quadrature point to local quadrature point inline IntegrationPoint convertToLocalPoint(const IntegrationPoint & global_point) const; /// converts local quadrature point to global quadrature point inline IntegrationPoint convertToGlobalPoint(const IntegrationPoint & local_point) const; /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: virtual inline UInt getNbDataForElements(const Array & elements, SynchronizationTag tag) const; virtual inline void packElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag) const; virtual inline void unpackElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag); template inline void packElementDataHelper(const ElementTypeMapArray & data_to_pack, CommunicationBuffer & buffer, const Array & elements, const ID & fem_id = ID()) const; template inline void unpackElementDataHelper(ElementTypeMapArray & data_to_unpack, CommunicationBuffer & buffer, const Array & elements, const ID & fem_id = ID()); /* ------------------------------------------------------------------------ */ /* MeshEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ virtual void onElementsAdded(const Array & element_list, const NewElementsEvent & event); virtual void onElementsRemoved(const Array & element_list, const ElementTypeMapArray & new_numbering, const RemovedElementsEvent & event); /* ------------------------------------------------------------------------ */ /* SolidMechanicsModelEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: virtual void onBeginningSolveStep(const AnalysisMethod & method); virtual void onEndSolveStep(const AnalysisMethod & method); virtual void onDamageIteration(); virtual void onDamageUpdate(); virtual void onDump(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(Name, name, const std::string &); AKANTU_GET_MACRO(Model, *model, const SolidMechanicsModel &) AKANTU_GET_MACRO(ID, Memory::getID(), const ID &); AKANTU_GET_MACRO(Rho, rho, Real); AKANTU_SET_MACRO(Rho, rho, Real); AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); /// return the potential energy for the subset of elements contained by the material Real getPotentialEnergy(); /// return the potential energy for the provided element Real getPotentialEnergy(ElementType & type, UInt index); /// return the energy (identified by id) for the subset of elements contained by the material virtual Real getEnergy(std::string energy_id); /// return the energy (identified by id) for the provided element virtual Real getEnergy(std::string energy_id, ElementType type, UInt index); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(GradU, gradu, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PotentialEnergy, potential_energy, Real); AKANTU_GET_MACRO(GradU, gradu, const ElementTypeMapArray &); AKANTU_GET_MACRO(Stress, stress, const ElementTypeMapArray &); AKANTU_GET_MACRO(ElementFilter, element_filter, const ElementTypeMapArray &); AKANTU_GET_MACRO(FEEngine, *fem, FEEngine &); bool isNonLocal() const { return is_non_local; } template const Array & getArray(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost) const; template Array & getArray(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost); template const InternalField & getInternal(const ID & id) const; template InternalField & getInternal(const ID & id); inline bool isInternal(const ID & id, const ElementKind & element_kind) const; virtual ElementTypeMap getInternalDataPerElem(const ID & id, const ElementKind & element_kind, const ID & fe_engine_id = "") const; bool isFiniteDeformation() const { return finite_deformation; } bool isInelasticDeformation() const { return inelastic_deformation; } template inline void setParam(const ID & param, T value); template inline const T & getParam(const ID & param) const; virtual void flattenInternal(const std::string & field_id, ElementTypeMapArray & internal_flat, const GhostType ghost_type = _not_ghost, ElementKind element_kind = _ek_not_defined) const; + + /// apply a constant eigengrad_u everywhere in the material + virtual void applyEigenGradU(const Matrix & prescribed_eigen_grad_u, const GhostType = _not_ghost); + protected: /// internal variation of the flatten function that is more flexible and can /// be used by inherited materials to change some behavior virtual void flattenInternalIntern(const std::string & field_id, ElementTypeMapArray & internal_flat, UInt spatial_dimension, const GhostType ghost_type, ElementKind element_kind, const ElementTypeMapArray * element_filter = NULL, const Mesh * mesh = NULL) const; protected: bool isInit() const { return is_init; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// boolean to know if the material has been initialized bool is_init; std::map *> internal_vectors_real; std::map *> internal_vectors_uint; std::map *> internal_vectors_bool; protected: /// Link to the fem object in the model FEEngine * fem; /// Finite deformation bool finite_deformation; /// Finite deformation bool inelastic_deformation; /// material name std::string name; /// The model to witch the material belong SolidMechanicsModel * model; /// density : rho Real rho; /// spatial dimension UInt spatial_dimension; /// list of element handled by the material ElementTypeMapArray element_filter; /// stresses arrays ordered by element types InternalField stress; /// eigengrad_u arrays ordered by element types InternalField eigengradu; /// grad_u arrays ordered by element types InternalField gradu; /// Green Lagrange strain (Finite deformation) InternalField green_strain; /// Second Piola-Kirchhoff stress tensor arrays ordered by element types (Finite deformation) InternalField piola_kirchhoff_2; /// potential energy by element InternalField potential_energy; /// tell if using in non local mode or not bool is_non_local; /// tell if the material need the previous stress state bool use_previous_stress; /// tell if the material need the previous strain state bool use_previous_gradu; /// elemental field interpolation coordinates InternalField interpolation_inverse_coordinates; /// elemental field interpolation points InternalField interpolation_points_matrices; /// vector that contains the names of all the internals that need to /// be transferred when material interfaces move std::vector internals_to_transfer; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_inline_impl.cc" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Material & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #include "internal_field_tmpl.hh" #include "random_internal_field_tmpl.hh" /* -------------------------------------------------------------------------- */ /* Auto loop */ /* -------------------------------------------------------------------------- */ /// This can be used to automatically write the loop on quadrature points in /// functions such as computeStress. This macro in addition to write the loop /// provides two tensors (matrices) sigma and grad_u #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type) \ Array::matrix_iterator gradu_it = \ this->gradu(el_type, ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ Array::matrix_iterator gradu_end = \ this->gradu(el_type, ghost_type).end(this->spatial_dimension, \ this->spatial_dimension); \ \ this->stress(el_type, \ ghost_type).resize(this->gradu(el_type, \ ghost_type).getSize()); \ \ Array::iterator< Matrix > stress_it = \ this->stress(el_type, ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ \ if(this->isFiniteDeformation()){ \ this->piola_kirchhoff_2(el_type, \ ghost_type).resize(this->gradu(el_type, \ ghost_type).getSize()); \ stress_it = \ this->piola_kirchhoff_2(el_type, \ ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ } \ \ for(;gradu_it != gradu_end; ++gradu_it, ++stress_it) { \ Matrix & __attribute__((unused)) grad_u = *gradu_it; \ Matrix & __attribute__((unused)) sigma = *stress_it #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END \ } \ /// This can be used to automatically write the loop on quadrature points in /// functions such as computeTangentModuli. This macro in addition to write the /// loop provides two tensors (matrices) sigma_tensor, grad_u, and a matrix /// where the elemental tangent moduli should be stored in Voigt Notation #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_mat) \ Array::matrix_iterator gradu_it = \ this->gradu(el_type, ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ Array::matrix_iterator gradu_end = \ this->gradu(el_type, ghost_type).end(this->spatial_dimension, \ this->spatial_dimension); \ Array::matrix_iterator sigma_it = \ this->stress(el_type, ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ \ tangent_mat.resize(this->gradu(el_type, ghost_type).getSize()); \ \ UInt tangent_size = \ this->getTangentStiffnessVoigtSize(this->spatial_dimension); \ Array::matrix_iterator tangent_it = \ tangent_mat.begin(tangent_size, \ tangent_size); \ \ for(;gradu_it != gradu_end; ++gradu_it, ++sigma_it, ++tangent_it) { \ Matrix & __attribute__((unused)) grad_u = *gradu_it; \ Matrix & __attribute__((unused)) sigma_tensor = *sigma_it; \ Matrix & tangent = *tangent_it #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END \ } \ /* -------------------------------------------------------------------------- */ #define INSTANTIATE_MATERIAL(mat_name) \ template class mat_name<1>; \ template class mat_name<2>; \ template class mat_name<3> #endif /* __AKANTU_MATERIAL_HH__ */ diff --git a/src/model/solid_mechanics/material_selector.hh b/src/model/solid_mechanics/material_selector.hh index a30a09818..91cbfecef 100644 --- a/src/model/solid_mechanics/material_selector.hh +++ b/src/model/solid_mechanics/material_selector.hh @@ -1,148 +1,148 @@ /** * @file material_selector.hh * * @author Nicolas Richart * @author Lucas Frérot * * @date creation: Wed Nov 13 2013 * @date last modification: Thu Jun 05 2014 * * @brief class describing how to choose a material for a given element * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_SELECTOR_HH__ #define __AKANTU_MATERIAL_SELECTOR_HH__ /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class SolidMechanicsModel; /** * main class to assign same or different materials for different * elements */ class MaterialSelector { public: MaterialSelector() : fallback_value(0) {} virtual ~MaterialSelector() {} virtual UInt operator()(const Element & element) { return fallback_value; } void setFallback(UInt f) { fallback_value = f; } protected: UInt fallback_value; }; /* -------------------------------------------------------------------------- */ /** * class that assigns the first material to regular elements by default */ class DefaultMaterialSelector : public MaterialSelector { public: DefaultMaterialSelector(const ElementTypeMapArray & material_index) : material_index(material_index) { } UInt operator()(const Element & element) { try { DebugLevel dbl = debug::getDebugLevel(); debug::setDebugLevel(dblError); const Array & mat_indexes = material_index(element.type, element.ghost_type); UInt mat = this->fallback_value; if(element.element < mat_indexes.getSize()) mat = mat_indexes(element.element); debug::setDebugLevel(dbl); return mat; } catch (...) { return MaterialSelector::operator()(element); } } private: const ElementTypeMapArray & material_index; }; /* -------------------------------------------------------------------------- */ /** * class that uses element data to assign materials (to be completed * by lucas, any implementation apart from the * MeshDataMaterialSelector?) */ template class ElementDataMaterialSelector : public MaterialSelector { public: ElementDataMaterialSelector(const ElementTypeMapArray & element_data, const SolidMechanicsModel & model, UInt first_index = 1): element_data(element_data), model(model), first_index(first_index) {} inline T elementData(const Element & element) { DebugLevel dbl = debug::getDebugLevel(); debug::setDebugLevel(dblError); T data = element_data(element.type, element.ghost_type)(element.element); debug::setDebugLevel(dbl); return data; } inline UInt operator() (const Element & element) { return MaterialSelector::operator()(element); } -private: +protected: /// list of element with the specified data (i.e. tag value) const ElementTypeMapArray & element_data; /// the model that the materials belong const SolidMechanicsModel & model; /// first material index: equal to 1 if none specified UInt first_index; }; /* -------------------------------------------------------------------------- */ /** * class to use mesh data information to assign different materials * where name is the tag value: tag_0, tag_1 */ template class MeshDataMaterialSelector : public ElementDataMaterialSelector { public: MeshDataMaterialSelector(const std::string & name, const SolidMechanicsModel & model, UInt first_index = 1); }; __END_AKANTU__ #endif /* __AKANTU_MATERIAL_SELECTOR_HH__ */ diff --git a/src/model/solid_mechanics/materials/internal_field_tmpl.hh b/src/model/solid_mechanics/materials/internal_field_tmpl.hh index 28f0af7a0..72839fbb4 100644 --- a/src/model/solid_mechanics/materials/internal_field_tmpl.hh +++ b/src/model/solid_mechanics/materials/internal_field_tmpl.hh @@ -1,338 +1,339 @@ /** * @file internal_field_tmpl.hh * * @author Nicolas Richart * * @date creation: Wed Nov 13 2013 * @date last modification: Thu Jun 05 2014 * * @brief Material internal properties * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_INTERNAL_FIELD_TMPL_HH__ #define __AKANTU_INTERNAL_FIELD_TMPL_HH__ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template InternalField::InternalField(const ID & id, Material & material) : ElementTypeMapArray(id, material.getID(), material.getMemoryID()), material(material), fem(&(material.getModel().getFEEngine())), element_filter(material.getElementFilter()), default_value(T()), spatial_dimension(material.getModel().getSpatialDimension()), element_kind(_ek_regular), nb_component(0), is_init(false), previous_values(NULL) { } /* -------------------------------------------------------------------------- */ template InternalField::InternalField(const ID & id, Material & material, FEEngine & fem, const ElementTypeMapArray & element_filter) : ElementTypeMapArray(id, material.getID(), material.getMemoryID()), material(material), fem(&fem), element_filter(element_filter), default_value(T()), spatial_dimension(material.getSpatialDimension()), element_kind(_ek_regular), nb_component(0), is_init(false), previous_values(NULL) { } /* -------------------------------------------------------------------------- */ template InternalField::InternalField(const ID & id, Material & material, UInt dim, FEEngine & fem, const ElementTypeMapArray & element_filter) : ElementTypeMapArray(id, material.getID(), material.getMemoryID()), material(material), fem(&fem), element_filter(element_filter), default_value(T()), spatial_dimension(dim), element_kind(_ek_regular), nb_component(0), is_init(false), previous_values(NULL) { } /* -------------------------------------------------------------------------- */ template InternalField::InternalField(const ID & id, const InternalField & other) : ElementTypeMapArray(id, other.material.getID(), other.material.getMemoryID()), material(other.material), fem(other.fem), element_filter(other.element_filter), default_value(other.default_value), spatial_dimension(other.spatial_dimension), element_kind(other.element_kind), nb_component(other.nb_component), is_init(false), previous_values(NULL) { AKANTU_DEBUG_ASSERT(other.is_init, "Cannot create a copy of a non initialized field"); this->internalInitialize(this->nb_component); } /* -------------------------------------------------------------------------- */ template InternalField::~InternalField() { if(this->is_init) { this->material.unregisterInternal(*this); } delete previous_values; } /* -------------------------------------------------------------------------- */ template void InternalField::setFEEngine(FEEngine & fe_engine) { this->fem = &fe_engine; } /* -------------------------------------------------------------------------- */ template void InternalField::setElementKind(ElementKind element_kind) { this->element_kind = element_kind; } /* -------------------------------------------------------------------------- */ template void InternalField::initialize(UInt nb_component) { internalInitialize(nb_component); } /* -------------------------------------------------------------------------- */ template void InternalField::initializeHistory() { if(!previous_values) previous_values = new InternalField("previous_" + this->getID(), *this); } /* -------------------------------------------------------------------------- */ template void InternalField::resize() { if(!this->is_init) return; for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; typename ElementTypeMapArray::type_iterator it = element_filter.firstType(spatial_dimension, gt, element_kind); typename ElementTypeMapArray::type_iterator end = element_filter.lastType(spatial_dimension, gt, element_kind); for(; it != end; ++it) { UInt nb_element = element_filter(*it, gt).getSize(); UInt nb_quadrature_points = fem->getNbIntegrationPoints(*it, gt); UInt new_size = nb_element * nb_quadrature_points; UInt old_size = 0; Array * vect = NULL; if(this->exists(*it, gt)) { vect = &(this->operator()(*it, gt)); old_size = vect->getSize(); vect->resize(new_size); } else { vect = &(this->alloc(nb_element * nb_quadrature_points, nb_component, *it, gt)); } this->setArrayValues(vect->storage() + old_size * vect->getNbComponent(), vect->storage() + new_size * vect->getNbComponent()); } } } /* -------------------------------------------------------------------------- */ template void InternalField::setDefaultValue(const T & value) { this->default_value = value; this->reset(); } /* -------------------------------------------------------------------------- */ template void InternalField::reset() { for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; typename ElementTypeMapArray::type_iterator it = this->firstType(spatial_dimension, gt, element_kind); typename ElementTypeMapArray::type_iterator end = this->lastType(spatial_dimension, gt, element_kind); for(; it != end; ++it) { Array & vect = this->operator()(*it, gt); vect.clear(); this->setArrayValues(vect.storage(), vect.storage() + vect.getSize() * vect.getNbComponent()); } } } /* -------------------------------------------------------------------------- */ template void InternalField::internalInitialize(UInt nb_component) { if(!this->is_init) { this->nb_component = nb_component; for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; typename ElementTypeMapArray::type_iterator it = element_filter.firstType(spatial_dimension, gt, element_kind); typename ElementTypeMapArray::type_iterator end = element_filter.lastType(spatial_dimension, gt, element_kind); for(; it != end; ++it) { UInt nb_element = element_filter(*it, gt).getSize(); UInt nb_quadrature_points = fem->getNbIntegrationPoints(*it, gt); if(this->exists(*it, gt)) this->operator()(*it, gt).resize(nb_element * nb_quadrature_points); else this->alloc(nb_element * nb_quadrature_points, nb_component, *it, gt); } } this->material.registerInternal(*this); this->is_init = true; } this->reset(); if(previous_values) previous_values->internalInitialize(nb_component); } /* -------------------------------------------------------------------------- */ template void InternalField::setArrayValues(T * begin, T * end) { for(; begin < end; ++begin) *begin = default_value; } /* -------------------------------------------------------------------------- */ template void InternalField::saveCurrentValues() { AKANTU_DEBUG_ASSERT(previous_values != NULL, "The history of the internal " << this->getID() << " has not been activated"); if(!is_init) return; for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; typename ElementTypeMapArray::type_iterator it = this->firstType(spatial_dimension, gt, element_kind); typename ElementTypeMapArray::type_iterator end = this->lastType(spatial_dimension, gt, element_kind); for(; it != end; ++it) { this->previous_values->operator()(*it, gt).copy(this->operator()(*it, gt)); } } } /* -------------------------------------------------------------------------- */ template void InternalField::removeIntegrationPoints(const ElementTypeMapArray & new_numbering) { for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; ElementTypeMapArray::type_iterator it = new_numbering.firstType(_all_dimensions, gt, _ek_not_defined); ElementTypeMapArray::type_iterator end = new_numbering.lastType(_all_dimensions, gt, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; if(this->exists(type, gt)){ - const Array & renumbering = new_numbering(type, gt); - Array & vect = this->operator()(type, gt); + if (!vect.getSize()) + continue; + const Array & renumbering = new_numbering(type, gt); UInt nb_quad_per_elem = fem->getNbIntegrationPoints(type, gt); UInt nb_component = vect.getNbComponent(); Array tmp(renumbering.getSize()*nb_quad_per_elem, nb_component); AKANTU_DEBUG_ASSERT(tmp.getSize() == vect.getSize(), "Something strange append some mater was created from nowhere!!"); AKANTU_DEBUG_ASSERT(tmp.getSize() == vect.getSize(), "Something strange append some mater was created or disappeared in "<< vect.getID() << "("<< vect.getSize() <<"!=" << tmp.getSize() <<") ""!!"); UInt new_size = 0; for (UInt i = 0; i < renumbering.getSize(); ++i) { UInt new_i = renumbering(i); if(new_i != UInt(-1)) { memcpy(tmp.storage() + new_i * nb_component * nb_quad_per_elem, vect.storage() + i * nb_component * nb_quad_per_elem, nb_component * nb_quad_per_elem * sizeof(T)); ++new_size; } } tmp.resize(new_size * nb_quad_per_elem); vect.copy(tmp); } } } } /* -------------------------------------------------------------------------- */ template void InternalField::printself(std::ostream & stream, UInt indent) const { stream << "InternalField [ " << this->getID(); #if !defined(AKANTU_NDEBUG) if(AKANTU_DEBUG_TEST(dblDump)) { stream << std::endl; ElementTypeMapArray::printself(stream, indent + 3); } else { #endif stream << " {" << this->getData(_not_ghost).size() << " types - " << this->getData(_ghost).size() << " ghost types" << "}"; #if !defined(AKANTU_NDEBUG) } #endif stream << " ]"; } /* -------------------------------------------------------------------------- */ template<> inline void ParsableParamTyped< InternalField >::parseParam(const ParserParameter & in_param) { ParsableParam::parseParam(in_param); Real r = in_param; param.setDefaultValue(r); } /* -------------------------------------------------------------------------- */ template inline InternalField::operator T() const { return default_value; } __END_AKANTU__ #endif /* __AKANTU_INTERNAL_FIELD_TMPL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_elastic.hh b/src/model/solid_mechanics/materials/material_elastic.hh index cf1240746..a4e81fce5 100644 --- a/src/model/solid_mechanics/materials/material_elastic.hh +++ b/src/model/solid_mechanics/materials/material_elastic.hh @@ -1,153 +1,156 @@ /** * @file material_elastic.hh * * @author Lucas Frerot * @author Daniel Pino Muñoz * @author Nicolas Richart * * @date creation: Wed Aug 04 2010 * @date last modification: Tue Sep 16 2014 * * @brief Material isotropic elastic * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_thermal.hh" #include "plane_stress_toolbox.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_ELASTIC_HH__ #define __AKANTU_MATERIAL_ELASTIC_HH__ __BEGIN_AKANTU__ /** * Material elastic isotropic * * parameters in the material files : * - 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 PlaneStressToolbox< spatial_dimension, MaterialThermal > { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ private: typedef PlaneStressToolbox< spatial_dimension, MaterialThermal > Parent; public: MaterialElastic(SolidMechanicsModel & model, const ID & id = ""); MaterialElastic(SolidMechanicsModel & model, UInt dim, const Mesh & mesh, FEEngine & fe_engine, const ID & id = ""); virtual ~MaterialElastic() {} protected: void initialize(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void initMaterial(); /// 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 virtual void computeTangentModuli(const ElementType & el_type, Array & tangent_matrix, GhostType ghost_type = _not_ghost); /// compute the elastic potential energy virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); virtual void computePotentialEnergyByElement(ElementType type, UInt index, Vector & epot_on_quad_points); /// compute the p-wave speed in the material virtual Real getPushWaveSpeed(const Element & element) const; /// compute the s-wave speed in the material virtual Real getShearWaveSpeed(const Element & element) const; protected: /// constitutive law for a given quadrature point inline void computeStressOnQuad(const Matrix & grad_u, Matrix & sigma, const Real sigma_th = 0) const; /// compute the tangent stiffness matrix for an element inline void computeTangentModuliOnQuad(Matrix & tangent) const; /// recompute the lame coefficient if E or nu changes virtual void updateInternalParameters(); static inline void computePotentialEnergyOnQuad(const Matrix & grad_u, const Matrix & sigma, Real & epot); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get first Lame constant AKANTU_GET_MACRO(Lambda, lambda, Real); /// get second Lame constant AKANTU_GET_MACRO(Mu, mu, Real); + /// get bulk modulus + AKANTU_GET_MACRO(Kappa, kpa, Real); + /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// First Lamé coefficient Real lambda; /// Second Lamé coefficient (shear modulus) Real mu; /// Bulk modulus Real kpa; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_elastic_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_MATERIAL_ELASTIC_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_non_local.cc b/src/model/solid_mechanics/materials/material_non_local.cc index addd567b3..8fe6e527d 100644 --- a/src/model/solid_mechanics/materials/material_non_local.cc +++ b/src/model/solid_mechanics/materials/material_non_local.cc @@ -1,151 +1,150 @@ /** * @file material_non_local.cc * @author Aurelia Isabel Cuba Ramos * @date Thu Oct 8 15:12:27 2015 * * @brief Implementation of material non-local * * @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_non_local.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template MaterialNonLocal::MaterialNonLocal(SolidMechanicsModel & model, const ID & id) : Material(model, id) { AKANTU_DEBUG_IN(); NonLocalManager & manager = this->model->getNonLocalManager(); manager.registerNonLocalMaterial(*this); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template MaterialNonLocal::~MaterialNonLocal() { } /* -------------------------------------------------------------------------- */ template void MaterialNonLocal::initMaterial() { this->registerNeighborhood(); this->insertQuadsInNeighborhoods(_not_ghost); } /* -------------------------------------------------------------------------- */ template void MaterialNonLocal::insertQuadsInNeighborhoods(GhostType ghost_type) { NonLocalManager & manager = this->model->getNonLocalManager(); UInt spatial_dimension = this->model->getSpatialDimension(); InternalField quadrature_points_coordinates("quadrature_points_coordinates_tmp_nl", *this); quadrature_points_coordinates.initialize(spatial_dimension); /// intialize quadrature point object IntegrationPoint q; q.ghost_type = ghost_type; q.kind = _ek_regular; Mesh::type_iterator it = this->element_filter.firstType(spatial_dimension, ghost_type, _ek_regular); Mesh::type_iterator last_type = this->element_filter.lastType(spatial_dimension, ghost_type, _ek_regular); for(; it != last_type; ++it) { q.type = *it; const Array & elem_filter = this->element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if(nb_element) { UInt nb_quad = this->fem->getNbIntegrationPoints(*it, ghost_type); UInt nb_tot_quad = nb_quad * nb_element; Array & quads = quadrature_points_coordinates(*it, ghost_type); quads.resize(nb_tot_quad); this->model->getFEEngine().computeIntegrationPointsCoordinates(quads, *it, ghost_type, elem_filter); Array::const_vector_iterator quad = quads.begin(spatial_dimension); UInt * elem = elem_filter.storage(); for (UInt e = 0; e < nb_element; ++e) { q.element = *elem; for (UInt nq = 0; nq < nb_quad; ++nq) { q.num_point = nq; q.global_num = q.element * nb_quad + nq; manager.insertQuad(q, *quad, this->name); ++quad; } ++elem; } } } } /* -------------------------------------------------------------------------- */ template void MaterialNonLocal::updateNonLocalInternals(ElementTypeMapReal & non_local_flattened, const ID & field_id, const UInt nb_component) { for (ghost_type_t::iterator g = ghost_type_t::begin(); g != ghost_type_t::end(); ++g) { GhostType ghost_type = *g; /// loop over all types in the material typedef ElementTypeMapArray:: type_iterator iterator; iterator it = this->element_filter.firstType(spatial_dimension, ghost_type, _ek_regular); iterator last_type = this->element_filter.lastType(spatial_dimension, ghost_type, _ek_regular); for(; it != last_type; ++it) { ElementType el_type = *it; Array & internal = this->getInternal(field_id)(el_type, ghost_type); Array::vector_iterator internal_it = internal.begin(nb_component); Array & internal_flat = non_local_flattened(el_type, ghost_type); Array::const_vector_iterator internal_flat_it = internal_flat.begin(nb_component); /// loop all elements for the given type const Array & filter = this->element_filter(el_type,ghost_type); UInt nb_elements = filter.getSize(); UInt nb_quads = this->getFEEngine().getNbIntegrationPoints(el_type, ghost_type); for (UInt e = 0; e < nb_elements; ++e) { UInt global_el = filter(e); for (UInt q = 0; q < nb_quads; ++q, ++internal_it) { UInt global_quad = global_el * nb_quads + q; *internal_it = internal_flat_it[global_quad]; } } } } } /* -------------------------------------------------------------------------- */ template void MaterialNonLocal::updateResidual(GhostType ghost_type) { AKANTU_EXCEPTION("this method has not been implemented"); } /* -------------------------------------------------------------------------- */ template void MaterialNonLocal::registerNeighborhood() { this->model->getNonLocalManager().registerNeighborhood(this->name, this->name); } /* -------------------------------------------------------------------------- */ - INSTANTIATE_MATERIAL(MaterialNonLocal); __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_python/material_python.cc b/src/model/solid_mechanics/materials/material_python/material_python.cc new file mode 100644 index 000000000..4722077fc --- /dev/null +++ b/src/model/solid_mechanics/materials/material_python/material_python.cc @@ -0,0 +1,125 @@ +/** + * @file material_python.cc + * + * @author Guillaume Anciaux + * + */ + +/* -------------------------------------------------------------------------- */ +#include "material_python.hh" +#include "solid_mechanics_model.hh" + +__BEGIN_AKANTU__ + +/* -------------------------------------------------------------------------- */ +MaterialPython::MaterialPython(SolidMechanicsModel & model, + PyObject * obj, + const ID & id) : + + Material(model, id), + PythonFunctor(obj){ + AKANTU_DEBUG_IN(); + + this->registerInternals(); + + std::vector param_names = this->callFunctor >("registerParam"); + + this->local_params.resize(param_names.size()); + + for (UInt i = 0; i < param_names.size(); ++i) { + std::stringstream sstr; + sstr << "PythonParameter" << i; + this->registerParam(param_names[i],local_params[i],0., _pat_parsable,sstr.str() ); + } + + AKANTU_DEBUG_OUT(); +} + +/* -------------------------------------------------------------------------- */ + +void MaterialPython::registerInternals() { + + std::vector internal_names = this->callFunctor >("registerInternals"); + + this->internals.resize(internal_names.size()); + + for (UInt i = 0; i < internal_names.size(); ++i) { + std::stringstream sstr; + sstr << "PythonInternal" << i; + this->internals[i] = new InternalField(internal_names[i],*this); + this->internals[i]->initialize(1); + } + + +} +/* -------------------------------------------------------------------------- */ + + +void MaterialPython::initMaterial() { + AKANTU_DEBUG_IN(); + + Material::initMaterial(); + + // initInternalArray(this->damage, 1); + // resizeInternalArray(this->damage); + + + // lambda = nu * E / ((1 + nu) * (1 - 2*nu)); + // mu = E / (2 * (1 + nu)); + + AKANTU_DEBUG_OUT(); +} + +/* -------------------------------------------------------------------------- */ +void MaterialPython::computeStress(ElementType el_type, GhostType ghost_type) { + AKANTU_DEBUG_IN(); + + typedef Array::iterator it_type; + std::vector its; + for (auto i: this->internals) { + its.push_back((*i)(el_type,ghost_type).begin()); + } + + MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); + + computeStress(grad_u, sigma, its); + + for (auto b: its) ++(*b); + + MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; + + AKANTU_DEBUG_OUT(); +} + +/* -------------------------------------------------------------------------- */ +template +void MaterialPython::computeStress( Matrix & grad_u, + Matrix & sigma, + std::vector & internal_iterators){ + + std::vector inputs; + for (auto i: internal_iterators){ + inputs.push_back(*i); + } + this->callFunctor("computeStress",grad_u,sigma,inputs); + + for (UInt i = 0; i < inputs.size(); ++i) { + *internal_iterators[i] = inputs[i]; + } +} + +/* -------------------------------------------------------------------------- */ +void MaterialPython::computeTangentModuli(const ElementType & el_type, + Array & tangent_matrix, + GhostType ghost_type){ + + this->callFunctor("computeTangentModuli",el_type,tangent_matrix,ghost_type); +} + +/* -------------------------------------------------------------------------- */ + +Real MaterialPython::getPushWaveSpeed(const Element & element) const{ + return this->callFunctor("getPushWaveSpeed"); +} + +__END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_python/material_python.hh b/src/model/solid_mechanics/materials/material_python/material_python.hh new file mode 100644 index 000000000..7abb45fe2 --- /dev/null +++ b/src/model/solid_mechanics/materials/material_python/material_python.hh @@ -0,0 +1,93 @@ +/** + * @file material_python.hh + * + * @author Guillaume Anciaux + * + */ + +/* -------------------------------------------------------------------------- */ +#include "aka_common.hh" +#include "material.hh" +/* -------------------------------------------------------------------------- */ + +#ifndef __AKANTU_MATERIAL_PYTHON_HH__ +#define __AKANTU_MATERIAL_PYTHON_HH__ + +/* -------------------------------------------------------------------------- */ +#include "python_functor.hh" +/* -------------------------------------------------------------------------- */ + + + +__BEGIN_AKANTU__ + +class MaterialPython : public Material, PythonFunctor { + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ +public: + + MaterialPython(SolidMechanicsModel & model, PyObject * obj, const ID & id = ""); + + virtual ~MaterialPython() {}; + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ +public: + + void registerInternals(); + + virtual void initMaterial(); + + + /// constitutive law for all element of a type + void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); + + /// constitutive law for a given quad point + template + void computeStress(Matrix & grad_u, + Matrix & sigma, + std::vector & internal_iterators); + + /// compute the tangent stiffness matrix for an element type + virtual void computeTangentModuli(const ElementType & el_type, + Array & tangent_matrix, + GhostType ghost_type = _not_ghost); + + /// compute the push wave speed of the material + Real getPushWaveSpeed(const Element & element) const; + +protected: + /// update the dissipated energy, must be called after the stress have been computed + //virtual void updateEnergies(ElementType el_type, GhostType ghost_type){}; + + /// compute the tangent stiffness matrix for a given quadrature point + //inline void computeTangentModuliOnQuad(Matrix & tangent, Real & dam){}; + + /* ------------------------------------------------------------------------ */ + /* DataAccessor inherited members */ + /* ------------------------------------------------------------------------ */ +public: + + /* ------------------------------------------------------------------------ */ + /* Accessors */ + /* ------------------------------------------------------------------------ */ +public: + + //virtual Real getEnergy(std::string type){}; + //virtual Real getEnergy(std::string energy_id, ElementType type, UInt index){}; + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ +protected: + + std::vector local_params; + std::vector *> internals; +}; + +__END_AKANTU__ + +#endif /* __AKANTU_MATERIAL_PYTHON_HH__ */ + diff --git a/src/model/solid_mechanics/solid_mechanics_model.hh b/src/model/solid_mechanics/solid_mechanics_model.hh index 7ac5390ab..c02cad0a8 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.hh +++ b/src/model/solid_mechanics/solid_mechanics_model.hh @@ -1,752 +1,763 @@ /** * @file solid_mechanics_model.hh * * @author Guillaume Anciaux * @author Daniel Pino Muñoz * @author Nicolas Richart * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Sep 16 2014 * * @brief Model of Solid Mechanics * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLID_MECHANICS_MODEL_HH__ #define __AKANTU_SOLID_MECHANICS_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_types.hh" #include "model.hh" #include "data_accessor.hh" #include "mesh.hh" #include "dumpable.hh" #include "boundary_condition.hh" #include "integrator_gauss.hh" #include "shape_lagrange.hh" #include "integration_scheme_2nd_order.hh" #include "solver.hh" #include "material_selector.hh" #include "solid_mechanics_model_event_handler.hh" +#ifdef AKANTU_PYTHON_INTERFACE +# include +#endif /* -------------------------------------------------------------------------- */ namespace akantu { class Material; class IntegrationScheme2ndOrder; class SparseMatrix; class DumperIOHelper; class NonLocalManager; } /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ struct SolidMechanicsModelOptions : public ModelOptions { SolidMechanicsModelOptions(AnalysisMethod analysis_method = _explicit_lumped_mass, bool no_init_materials = false) : analysis_method(analysis_method), no_init_materials(no_init_materials) { } AnalysisMethod analysis_method; bool no_init_materials; }; extern const SolidMechanicsModelOptions default_solid_mechanics_model_options; class SolidMechanicsModel : public Model, public DataAccessor, public MeshEventHandler, public BoundaryCondition, public EventHandlerManager { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: class NewMaterialElementsEvent : public NewElementsEvent { public: AKANTU_GET_MACRO_NOT_CONST(MaterialList, material, Array &); AKANTU_GET_MACRO(MaterialList, material, const Array &); protected: Array material; }; typedef FEEngineTemplate MyFEEngineType; protected: typedef EventHandlerManager EventManager; public: SolidMechanicsModel(Mesh & mesh, UInt spatial_dimension = _all_dimensions, const ID & id = "solid_mechanics_model", const MemoryID & memory_id = 0); virtual ~SolidMechanicsModel(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize completely the model virtual void initFull(const ModelOptions & options = default_solid_mechanics_model_options); /// initialize the fem object needed for boundary conditions void initFEEngineBoundary(); /// register the tags associated with the parallel synchronizer virtual void initParallel(MeshPartition *partition, DataAccessor *data_accessor = NULL); /// allocate all vectors virtual void initArrays(); /// allocate all vectors void initArraysPreviousDisplacment(); /// initialize all internal arrays for materials virtual void initMaterials(); /// initialize the model virtual void initModel(); /// init PBC synchronizer void initPBC(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /// re-initialize model to set fields to 0 void reInitialize(); /* ------------------------------------------------------------------------ */ /* PBC */ /* ------------------------------------------------------------------------ */ public: /// change the equation number for proper assembly when using PBC // void changeEquationNumberforPBC(std::map & pbc_pair); /// synchronize Residual for output void synchronizeResidual(); protected: /// register PBC synchronizer void registerPBCSynchronizer(); /* ------------------------------------------------------------------------ */ /* Explicit */ /* ------------------------------------------------------------------------ */ public: /// initialize the stuff for the explicit scheme void initExplicit(AnalysisMethod analysis_method = _explicit_lumped_mass); bool isExplicit() { return method == _explicit_lumped_mass || method == _explicit_consistent_mass; } /// initialize the array needed by updateResidual (residual, current_position) void initializeUpdateResidualData(); /// update the current position vector void updateCurrentPosition(); /// assemble the residual for the explicit scheme virtual void updateResidual(bool need_initialize = true); /** * \brief compute the acceleration from the residual * this function is the explicit equivalent to solveDynamic in implicit * In the case of lumped mass just divide the residual by the mass * In the case of not lumped mass call solveDynamic<_acceleration_corrector> */ void updateAcceleration(); void updateIncrement(); void updatePreviousDisplacement(); void saveStressAndStrainBeforeDamage(); void updateEnergiesAfterDamage(); /// Solve the system @f[ A x = \alpha b @f] with A a lumped matrix void solveLumped(Array & x, const Array & A, const Array & b, const Array & blocked_dofs, Real alpha); /// explicit integration predictor void explicitPred(); /// explicit integration corrector void explicitCorr(); public: void solveStep(); /* ------------------------------------------------------------------------ */ /* Implicit */ /* ------------------------------------------------------------------------ */ public: /// initialize the solver and the jacobian_matrix (called by initImplicit) void initSolver(SolverOptions & options = _solver_no_options); /// initialize the stuff for the implicit solver void initImplicit(bool dynamic = false, SolverOptions & solver_options = _solver_no_options); /// solve Ma = f to get the initial acceleration void initialAcceleration(); /// assemble the stiffness matrix void assembleStiffnessMatrix(); public: /** * solve a step (predictor + convergence loop + corrector) using the * the given convergence method (see akantu::SolveConvergenceMethod) * and the given convergence criteria (see * akantu::SolveConvergenceCriteria) **/ template bool solveStep(Real tolerance, UInt max_iteration = 100); template bool solveStep(Real tolerance, Real & error, UInt max_iteration = 100, bool do_not_factorize = false); public: /** * solve Ku = f using the the given convergence method (see * akantu::SolveConvergenceMethod) and the given convergence * criteria (see akantu::SolveConvergenceCriteria) **/ template bool solveStatic(Real tolerance, UInt max_iteration, bool do_not_factorize = false); /// test if the system is converged template bool testConvergence(Real tolerance, Real & error); /// test the convergence (norm of increment) bool testConvergenceIncrement(Real tolerance) __attribute__((deprecated)); bool testConvergenceIncrement(Real tolerance, Real & error) __attribute__((deprecated)); /// test the convergence (norm of residual) bool testConvergenceResidual(Real tolerance) __attribute__((deprecated)); bool testConvergenceResidual(Real tolerance, Real & error) __attribute__((deprecated)); /// create and return the velocity damping matrix SparseMatrix & initVelocityDampingMatrix(); /// implicit time integration predictor void implicitPred(); /// implicit time integration corrector void implicitCorr(); /// compute the Cauchy stress on user demand. void computeCauchyStresses(); /// compute A and solve @f[ A\delta u = f_ext - f_int @f] template void solve(Array &increment, Real block_val = 1., bool need_factorize = true, bool has_profile_changed = false); protected: /// finish the computation of residual to solve in increment void updateResidualInternal(); /// compute the support reaction and store it in force void updateSupportReaction(); private: /// re-initialize the J matrix (to use if the profile of K changed) void initJacobianMatrix(); /* ------------------------------------------------------------------------ */ /* Explicit/Implicit */ /* ------------------------------------------------------------------------ */ public: /// Update the stresses for the computation of the residual of the Stiffness /// matrix in the case of finite deformation void computeStresses(); /// synchronize the ghost element boundaries values void synchronizeBoundaries(); /* ------------------------------------------------------------------------ */ /* Materials (solid_mechanics_model_material.cc) */ /* ------------------------------------------------------------------------ */ public: /// registers all the custom materials of a given type present in the input file template void registerNewCustomMaterials(const ID & mat_type); /// register an empty material of a given type template Material & registerNewEmptyMaterial(const std::string & name); +#ifdef AKANTU_PYTHON_INTERFACE + /// register an empty material of a given type + void registerNewPythonMaterial(PyObject * obj,const ID & name); +#endif // /// Use a UIntData in the mesh to specify the material to use per element // void setMaterialIDsFromIntData(const std::string & data_name); /// reassigns materials depending on the material selector virtual void reassignMaterial(); + /// apply a constant eigen_grad_u on all quadrature points of a given material + virtual void applyEigenGradU(const Matrix & prescribed_eigen_grad_u, const ID & material_name, const GhostType ghost_type = _not_ghost); + + protected: /// register a material in the dynamic database template Material & registerNewMaterial(const ParserSection & mat_section); /// read the material files to instantiate all the materials void instantiateMaterials(); /// set the element_id_by_material and add the elements to the good materials void assignMaterialToElements(const ElementTypeMapArray * filter = NULL); /* ------------------------------------------------------------------------ */ /* Mass (solid_mechanics_model_mass.cc) */ /* ------------------------------------------------------------------------ */ public: /// assemble the lumped mass matrix void assembleMassLumped(); /// assemble the mass matrix for consistent mass resolutions void assembleMass(); protected: /// assemble the lumped mass matrix for local and ghost elements void assembleMassLumped(GhostType ghost_type); /// assemble the mass matrix for either _ghost or _not_ghost elements void assembleMass(GhostType ghost_type); /// fill a vector of rho void computeRho(Array & rho, ElementType type, GhostType ghost_type); /// compute the kinetic energy Real getKineticEnergy(); Real getKineticEnergy(const ElementType & type, UInt index); /// compute the external work (for impose displacement, the velocity should be given too) Real getExternalWork(); /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ public: inline virtual UInt getNbDataForElements(const Array & elements, SynchronizationTag tag) const; inline virtual void packElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag) const; inline virtual void unpackElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag); inline virtual UInt getNbDataToPack(SynchronizationTag tag) const; inline virtual UInt getNbDataToUnpack(SynchronizationTag tag) const; inline virtual void packData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const; inline virtual void unpackData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag); protected: inline void splitElementByMaterial(const Array & elements, Array * elements_per_mat) const; /* ------------------------------------------------------------------------ */ /* Mesh Event Handler inherited members */ /* ------------------------------------------------------------------------ */ protected: virtual void onNodesAdded(const Array & nodes_list, const NewNodesEvent & event); virtual void onNodesRemoved(const Array & element_list, const Array & new_numbering, const RemovedNodesEvent & event); virtual void onElementsAdded(const Array & nodes_list, const NewElementsEvent & event); virtual void onElementsRemoved(const Array & element_list, const ElementTypeMapArray & new_numbering, const RemovedElementsEvent & event); /* ------------------------------------------------------------------------ */ /* Dumpable interface (kept for convenience) and dumper relative functions */ /* ------------------------------------------------------------------------ */ public: virtual void onDump(); //! decide wether a field is a material internal or not bool isInternal(const std::string & field_name, const ElementKind & element_kind); #ifndef SWIG //! give the amount of data per element virtual ElementTypeMap getInternalDataPerElem(const std::string & field_name, const ElementKind & kind); //! flatten a given material internal field ElementTypeMapArray & flattenInternal(const std::string & field_name, const ElementKind & kind, const GhostType ghost_type = _not_ghost); //! flatten all the registered material internals void flattenAllRegisteredInternals(const ElementKind & kind); #endif virtual dumper::Field * createNodalFieldReal(const std::string & field_name, const std::string & group_name, bool padding_flag); virtual dumper::Field * createNodalFieldBool(const std::string & field_name, const std::string & group_name, bool padding_flag); virtual dumper::Field * createElementalField(const std::string & field_name, const std::string & group_name, bool padding_flag, const UInt & spatial_dimension, const ElementKind & kind); virtual void dump(const std::string & dumper_name); virtual void dump(const std::string & dumper_name, UInt step); virtual void dump(const std::string & dumper_name, Real time, UInt step); virtual void dump(); virtual void dump(UInt step); virtual void dump(Real time, UInt step); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// return the dimension of the system space AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); /// get the current value of the time step AKANTU_GET_MACRO(TimeStep, time_step, Real); /// set the value of the time step void setTimeStep(Real time_step); /// return the of iterations done in the last solveStep AKANTU_GET_MACRO(NumberIter, n_iter, UInt); /// get the value of the conversion from forces/ mass to acceleration AKANTU_GET_MACRO(F_M2A, f_m2a, Real); /// set the value of the conversion from forces/ mass to acceleration AKANTU_SET_MACRO(F_M2A, f_m2a, Real); /// get the SolidMechanicsModel::displacement vector AKANTU_GET_MACRO(Displacement, *displacement, Array &); /// get the SolidMechanicsModel::previous_displacement vector AKANTU_GET_MACRO(PreviousDisplacement, *previous_displacement, Array &); /// get the SolidMechanicsModel::current_position vector \warn only consistent /// after a call to SolidMechanicsModel::updateCurrentPosition AKANTU_GET_MACRO(CurrentPosition, *current_position, const Array &); /// get the SolidMechanicsModel::increment vector \warn only consistent if /// SolidMechanicsModel::setIncrementFlagOn has been called before AKANTU_GET_MACRO(Increment, *increment, Array &); /// get the lumped SolidMechanicsModel::mass vector AKANTU_GET_MACRO(Mass, *mass, Array &); /// get the SolidMechanicsModel::velocity vector AKANTU_GET_MACRO(Velocity, *velocity, Array &); /// get the SolidMechanicsModel::acceleration vector, updated by /// SolidMechanicsModel::updateAcceleration AKANTU_GET_MACRO(Acceleration, *acceleration, Array &); /// get the SolidMechanicsModel::force vector (boundary forces) AKANTU_GET_MACRO(Force, *force, Array &); /// get the SolidMechanicsModel::residual vector, computed by /// SolidMechanicsModel::updateResidual AKANTU_GET_MACRO(Residual, *residual, Array &); /// get the SolidMechanicsModel::blocked_dofs vector AKANTU_GET_MACRO(BlockedDOFs, *blocked_dofs, Array &); /// get the SolidMechnicsModel::incrementAcceleration vector AKANTU_GET_MACRO(IncrementAcceleration, *increment_acceleration, Array &); /// get the value of the SolidMechanicsModel::increment_flag AKANTU_GET_MACRO(IncrementFlag, increment_flag, bool); /// get a particular material (by material index) inline Material & getMaterial(UInt mat_index); /// get a particular material (by material index) inline const Material & getMaterial(UInt mat_index) const; /// get a particular material (by material name) inline Material & getMaterial(const std::string & name); /// get a particular material (by material name) inline const Material & getMaterial(const std::string & name) const; /// get a particular material id from is name inline UInt getMaterialIndex(const std::string & name) const; /// give the number of materials inline UInt getNbMaterials() const { return materials.size(); } inline void setMaterialSelector(MaterialSelector & selector); /// give the material internal index from its id Int getInternalIndexFromID(const ID & id) const; /// compute the stable time step Real getStableTimeStep(); /// get the energies Real getEnergy(const std::string & energy_id); /// compute the energy for energy Real getEnergy(const std::string & energy_id, const ElementType & type, UInt index); /** * @brief set the SolidMechanicsModel::increment_flag to on, the activate the * update of the SolidMechanicsModel::increment vector */ void setIncrementFlagOn(); /// get the stiffness matrix AKANTU_GET_MACRO(StiffnessMatrix, *stiffness_matrix, SparseMatrix &); /// get the global jacobian matrix of the system AKANTU_GET_MACRO(GlobalJacobianMatrix, *jacobian_matrix, const SparseMatrix &); /// get the mass matrix AKANTU_GET_MACRO(MassMatrix, *mass_matrix, SparseMatrix &); /// get the velocity damping matrix AKANTU_GET_MACRO(VelocityDampingMatrix, *velocity_damping_matrix, SparseMatrix &); /// get the FEEngine object to integrate or interpolate on the boundary inline FEEngine & getFEEngineBoundary(const ID & name = ""); /// get integrator AKANTU_GET_MACRO(Integrator, *integrator, const IntegrationScheme2ndOrder &); /// get access to the internal solver AKANTU_GET_MACRO(Solver, *solver, Solver &); /// get synchronizer AKANTU_GET_MACRO(Synchronizer, *synch_parallel, const DistributedSynchronizer &); AKANTU_GET_MACRO(MaterialByElement, material_index, const ElementTypeMapArray &); /// vectors containing local material element index for each global element index AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialByElement, material_index, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialByElement, material_index, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialLocalNumbering, material_local_numbering, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialLocalNumbering, material_local_numbering, UInt); /// Get the type of analysis method used AKANTU_GET_MACRO(AnalysisMethod, method, AnalysisMethod); /// get the non-local manager AKANTU_GET_MACRO(NonLocalManager, *non_local_manager, NonLocalManager &); template friend struct ContactData; template friend class ContactResolution; protected: friend class Material; protected: /// compute the stable time step Real getStableTimeStep(const GhostType & ghost_type); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// number of iterations UInt n_iter; /// time step Real time_step; /// conversion coefficient form force/mass to acceleration Real f_m2a; /// displacements array Array *displacement; /// displacements array at the previous time step (used in finite deformation) Array *previous_displacement; /// lumped mass array Array *mass; /// velocities array Array *velocity; /// accelerations array Array *acceleration; /// accelerations array Array *increment_acceleration; /// forces array Array *force; /// residuals array Array *residual; /// array specifing if a degree of freedom is blocked or not Array *blocked_dofs; /// array of current position used during update residual Array *current_position; /// mass matrix SparseMatrix *mass_matrix; /// velocity damping matrix SparseMatrix *velocity_damping_matrix; /// stiffness matrix SparseMatrix *stiffness_matrix; /// jacobian matrix @f[A = cM + dD + K@f] with @f[c = \frac{1}{\beta \Delta /// t^2}, d = \frac{\gamma}{\beta \Delta t} @f] SparseMatrix *jacobian_matrix; /// Arrays containing the material index for each element ElementTypeMapArray material_index; /// Arrays containing the position in the element filter of the material (material's local numbering) ElementTypeMapArray material_local_numbering; /// list of used materials std::vector materials; /// mapping between material name and material internal id std::map materials_names_to_id; /// class defining of to choose a material MaterialSelector *material_selector; /// define if it is the default selector or not bool is_default_material_selector; /// integration scheme of second order used IntegrationScheme2ndOrder *integrator; /// increment of displacement Array *increment; /// flag defining if the increment must be computed or not bool increment_flag; /// solver for implicit Solver *solver; /// analysis method check the list in akantu::AnalysisMethod AnalysisMethod method; /// internal synchronizer for parallel computations DistributedSynchronizer *synch_parallel; /// tells if the material are instantiated bool are_materials_instantiated; /// map a registered internals to be flattened for dump purposes std::map,ElementTypeMapArray *> registered_internals; /// pointer to non-local manager: For non-local continuum damage computations NonLocalManager * non_local_manager; }; /* -------------------------------------------------------------------------- */ namespace BC { namespace Neumann { typedef FromHigherDim FromStress; typedef FromSameDim FromTraction; } } __END_AKANTU__ /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "parser.hh" #include "material.hh" __BEGIN_AKANTU__ #include "solid_mechanics_model_tmpl.hh" #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "solid_mechanics_model_inline_impl.cc" #endif /// standard output stream operator inline std::ostream & operator << (std::ostream & stream, const SolidMechanicsModel &_this) { _this.printself(stream); return stream; } __END_AKANTU__ #include "material_selector_tmpl.hh" #endif /* __AKANTU_SOLID_MECHANICS_MODEL_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_material.cc b/src/model/solid_mechanics/solid_mechanics_model_material.cc index 8f9af3d61..c842bc33e 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_material.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_material.cc @@ -1,320 +1,365 @@ /** * @file solid_mechanics_model_material.cc * * @author Guillaume Anciaux * @author Nicolas Richart * * @date creation: Fri Nov 26 2010 * @date last modification: Tue Jun 24 2014 * * @brief instatiation of materials * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "material_list.hh" #include "aka_math.hh" #ifdef AKANTU_DAMAGE_NON_LOCAL # include "non_local_manager.hh" #endif +#ifdef AKANTU_PYTHON_INTERFACE +# include "material_python.hh" +#endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #define AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL(dim, elem) \ registerNewMaterial< BOOST_PP_ARRAY_ELEM(1, elem)< dim > >(section) #define AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL_EACH(r, data, i, elem) \ BOOST_PP_EXPR_IF(BOOST_PP_NOT_EQUAL(0, i), else ) \ if(opt_param == BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, elem))) { \ registerNewMaterial< BOOST_PP_ARRAY_ELEM(1, data)< BOOST_PP_ARRAY_ELEM(0, data), \ BOOST_PP_SEQ_ENUM(BOOST_PP_TUPLE_ELEM(2, 1, elem)) > >(section); \ } #define AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL(dim, elem) \ BOOST_PP_SEQ_FOR_EACH_I(AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL_EACH, \ (2, (dim, BOOST_PP_ARRAY_ELEM(1, elem))), \ BOOST_PP_ARRAY_ELEM(2, elem)) \ else { \ AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL(dim, elem); \ } #define AKANTU_INTANTIATE_MATERIAL_BY_DIM(dim, elem) \ BOOST_PP_IF(BOOST_PP_EQUAL(3, BOOST_PP_ARRAY_SIZE(elem) ), \ AKANTU_INTANTIATE_MATERIAL_BY_DIM_TMPL, \ AKANTU_INTANTIATE_MATERIAL_BY_DIM_NO_TMPL)(dim, elem) #define AKANTU_INTANTIATE_MATERIAL(elem) \ switch(spatial_dimension) { \ case 1: { AKANTU_INTANTIATE_MATERIAL_BY_DIM(1, elem); break; } \ case 2: { AKANTU_INTANTIATE_MATERIAL_BY_DIM(2, elem); break; } \ case 3: { AKANTU_INTANTIATE_MATERIAL_BY_DIM(3, elem); break; } \ } #define AKANTU_INTANTIATE_MATERIAL_IF(elem) \ if (mat_type == BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(0, elem))) { \ AKANTU_INTANTIATE_MATERIAL(elem); \ } #define AKANTU_INTANTIATE_OTHER_MATERIAL(r, data, elem) \ else AKANTU_INTANTIATE_MATERIAL_IF(elem) #define AKANTU_INSTANTIATE_MATERIALS() \ do { \ AKANTU_INTANTIATE_MATERIAL_IF(BOOST_PP_SEQ_HEAD(AKANTU_MATERIAL_LIST)) \ BOOST_PP_SEQ_FOR_EACH(AKANTU_INTANTIATE_OTHER_MATERIAL, \ _, \ BOOST_PP_SEQ_TAIL(AKANTU_MATERIAL_LIST)) \ else { \ if(getStaticParser().isPermissive()) \ AKANTU_DEBUG_INFO("Malformed material file " << \ ": unknown material type '" \ << mat_type << "'"); \ else \ AKANTU_DEBUG_WARNING("Malformed material file " \ <<": unknown material type " << mat_type \ << ". This is perhaps a user" \ << " defined material ?"); \ } \ } while(0) /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::instantiateMaterials() { std::pair sub_sect = this->parser->getSubSections(_st_material); Parser::const_section_iterator it = sub_sect.first; for (; it != sub_sect.second; ++it) { const ParserSection & section = *it; std::string mat_type = section.getName(); std::string opt_param = section.getOption(); AKANTU_INSTANTIATE_MATERIALS(); } are_materials_instantiated = true; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assignMaterialToElements(const ElementTypeMapArray * filter) { Material ** mat_val = &(materials.at(0)); Element element; element.ghost_type = _not_ghost; Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(spatial_dimension, _not_ghost, _ek_not_defined); if(filter != NULL) { it = filter->firstType(spatial_dimension, _not_ghost, _ek_not_defined); end = filter->lastType(spatial_dimension, _not_ghost, _ek_not_defined); } // Fill the element material array from the material selector for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, _not_ghost); const Array * filter_array = NULL; if (filter != NULL) { filter_array = &((*filter)(*it, _not_ghost)); nb_element = filter_array->getSize(); } element.type = *it; element.kind = mesh.getKind(element.type); Array & mat_indexes = material_index(*it, _not_ghost); for (UInt el = 0; el < nb_element; ++el) { if (filter != NULL) element.element = (*filter_array)(el); else element.element = el; UInt mat_index = (*material_selector)(element); AKANTU_DEBUG_ASSERT(mat_index < materials.size(), "The material selector returned an index that does not exists"); mat_indexes(element.element) = mat_index; } } // synchronize the element material arrays synch_registry->synchronize(_gst_material_id); /// fill the element filters of the materials using the element_material arrays for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; it = mesh.firstType(spatial_dimension, gt, _ek_not_defined); end = mesh.lastType(spatial_dimension, gt, _ek_not_defined); if(filter != NULL) { it = filter->firstType(spatial_dimension, gt, _ek_not_defined); end = filter->lastType(spatial_dimension, gt, _ek_not_defined); } for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, gt); const Array * filter_array = NULL; if (filter != NULL) { filter_array = &((*filter)(*it, gt)); nb_element = filter_array->getSize(); } Array & mat_indexes = material_index(*it, gt); Array & mat_local_num = material_local_numbering(*it, gt); for (UInt el = 0; el < nb_element; ++el) { UInt element; if (filter != NULL) element = (*filter_array)(el); else element = el; UInt mat_index = mat_indexes(element); UInt index = mat_val[mat_index]->addElement(*it, element, gt); mat_local_num(element) = index; } } } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initMaterials() { AKANTU_DEBUG_ASSERT(materials.size() != 0, "No material to initialize !"); if(!are_materials_instantiated) instantiateMaterials(); this->assignMaterialToElements(); std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { /// init internals properties (*mat_it)->initMaterial(); } synch_registry->synchronize(_gst_smm_init_mat); // initialize mass switch(method) { case _explicit_lumped_mass: assembleMassLumped(); break; case _explicit_consistent_mass: case _implicit_dynamic: assembleMass(); break; case _static: break; default: AKANTU_EXCEPTION("analysis method not recognised by SolidMechanicsModel"); break; } // initialize the previous displacement array if at least on material needs it for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; if (mat.isFiniteDeformation() || mat.isInelasticDeformation()) { initArraysPreviousDisplacment(); break; } } #ifdef AKANTU_DAMAGE_NON_LOCAL /// initialize the non-local manager for non-local computations this->non_local_manager->init(); #endif } /* -------------------------------------------------------------------------- */ Int SolidMechanicsModel::getInternalIndexFromID(const ID & id) const { AKANTU_DEBUG_IN(); std::vector::const_iterator first = materials.begin(); std::vector::const_iterator last = materials.end(); for (; first != last; ++first) if ((*first)->getID() == id) { AKANTU_DEBUG_OUT(); return (first - materials.begin()); } AKANTU_DEBUG_OUT(); return -1; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::reassignMaterial() { AKANTU_DEBUG_IN(); std::vector< Array > element_to_add (materials.size()); std::vector< Array > element_to_remove(materials.size()); Element element; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; element.ghost_type = ghost_type; Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type, _ek_not_defined); for(; it != end; ++it) { ElementType type = *it; element.type = type; element.kind = Mesh::getKind(type); UInt nb_element = mesh.getNbElement(type, ghost_type); Array & mat_indexes = material_index(type, ghost_type); for (UInt el = 0; el < nb_element; ++el) { element.element = el; UInt old_material = mat_indexes(el); UInt new_material = (*material_selector)(element); if(old_material != new_material) { element_to_add [new_material].push_back(element); element_to_remove[old_material].push_back(element); } } } } std::vector::iterator mat_it; UInt mat_index = 0; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it, ++mat_index) { (*mat_it)->removeElements(element_to_remove[mat_index]); (*mat_it)->addElements (element_to_add[mat_index]); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ +void SolidMechanicsModel::applyEigenGradU(const Matrix & prescribed_eigen_grad_u, const ID & material_name, + const GhostType ghost_type) { + + AKANTU_DEBUG_ASSERT(prescribed_eigen_grad_u.size() == spatial_dimension * spatial_dimension, + "The prescribed grad_u is not of the good size"); + std::vector::iterator mat_it; + for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { + if ((*mat_it)->getName() == material_name) + (*mat_it)->applyEigenGradU(prescribed_eigen_grad_u, ghost_type); + } +} + +/* -------------------------------------------------------------------------- */ +#ifdef AKANTU_PYTHON_INTERFACE +void SolidMechanicsModel::registerNewPythonMaterial(PyObject * obj, const ID & mat_type) { + + std::pair + sub_sect = getStaticParser().getSubSections(_st_material); + + Parser::const_section_iterator it = sub_sect.first; + for (; it != sub_sect.second; ++it) { + if(it->getName() == mat_type) { + + AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_type) == materials_names_to_id.end(), + "A material with this name '" << mat_type + << "' has already been registered. " + << "Please use unique names for materials"); + + UInt mat_count = materials.size(); + materials_names_to_id[mat_type] = mat_count; + + std::stringstream sstr_mat; sstr_mat << id << ":" << mat_count << ":" << mat_type; + ID mat_id = sstr_mat.str(); + + Material * material = new MaterialPython(*this, obj,mat_id); + materials.push_back(material); + material->parseSection(*it); + } + } +} +#endif +/* -------------------------------------------------------------------------- */ __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 851f71ae6..c39b04988 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh +++ b/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh @@ -1,104 +1,106 @@ /** * @file solid_mechanics_model_tmpl.hh * * @author Guillaume Anciaux * @author Dana Christen * @author Nicolas Richart * * @date creation: Thu Nov 24 2011 * @date last modification: Thu Apr 03 2014 * * @brief template part of solid mechanics model * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ template Material & SolidMechanicsModel::registerNewMaterial(const ParserSection & section) { std::string mat_name; std::string mat_type = section.getName(); try { std::string tmp = section.getParameter("name"); mat_name = tmp; /** this can seam weird, but there is an ambiguous operator * overload that i couldn't solve. @todo remove the * weirdness of this code */ } catch(debug::Exception & ){ AKANTU_DEBUG_ERROR("A material of type \'" << mat_type << "\' in the input file has been defined without a name!"); } AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_name) == materials_names_to_id.end(), "A material with this name '" << mat_name << "' has already been registered. " << "Please use unique names for materials"); UInt mat_count = materials.size(); materials_names_to_id[mat_name] = mat_count; std::stringstream sstr_mat; sstr_mat << this->id << ":" << mat_count << ":" << mat_type; ID mat_id = sstr_mat.str(); Material * material; material = new M(*this, mat_id); materials.push_back(material); material->parseSection(section); return *material; } /* -------------------------------------------------------------------------- */ template Material & SolidMechanicsModel::registerNewEmptyMaterial(const std::string & mat_name) { AKANTU_DEBUG_ASSERT(materials_names_to_id.find(mat_name) == materials_names_to_id.end(), "A material with this name '" << mat_name << "' has already been registered. " << "Please use unique names for materials"); UInt mat_count = materials.size(); materials_names_to_id[mat_name] = mat_count; std::stringstream sstr_mat; sstr_mat << id << ":" << mat_count << ":" << mat_name; ID mat_id = sstr_mat.str(); Material * material; material = new M(*this, mat_id); materials.push_back(material); return *material; } /* -------------------------------------------------------------------------- */ template void SolidMechanicsModel::registerNewCustomMaterials(const ID & mat_type) { std::pair sub_sect = getStaticParser().getSubSections(_st_material); Parser::const_section_iterator it = sub_sect.first; for (; it != sub_sect.second; ++it) { if(it->getName() == mat_type) { registerNewMaterial(*it); } } } +/* -------------------------------------------------------------------------- */ + diff --git a/src/python/python_functor.cc b/src/python/python_functor.cc new file mode 100644 index 000000000..9e82870ca --- /dev/null +++ b/src/python/python_functor.cc @@ -0,0 +1,76 @@ +/** + * @file python_functor.cc + * + + * @author Guillaume Anciaux + * + * + * @section LICENSE + * + * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see . + * + */ + +/* -------------------------------------------------------------------------- */ +#include "python_functor.hh" +#include "aka_common.hh" +/* -------------------------------------------------------------------------- */ +__BEGIN_AKANTU__ +/* -------------------------------------------------------------------------- */ + +PythonFunctor::PythonFunctor(PyObject * obj):python_obj(obj){ +} + +/* -------------------------------------------------------------------------- */ + + +PyObject * PythonFunctor::callFunctor(PyObject * functor, + PyObject * args, + PyObject * kwargs) const{ + + + if (!PyCallable_Check(functor)) + AKANTU_EXCEPTION("Provided functor is not a function"); + + PyObject * pValue = PyObject_Call(functor, args,kwargs); + + PyObject* exception_type = PyErr_Occurred(); + if (exception_type){ + PyObject * exception; + PyObject * traceback; + PyErr_Fetch(&exception_type, &exception, &traceback); + + PyObject_Print(exception_type, stdout, Py_PRINT_RAW); + PyObject_Print(exception, stdout, Py_PRINT_RAW); + std::stringstream sstr; + sstr << "Exception occured while calling the functor: "; + + PyObject * exception_mesg = PyObject_GetAttrString(exception,"message"); + if (exception_mesg && PyString_Check(exception_mesg)) + sstr << PyString_AsString(exception_mesg); + else + sstr << PyString_AsString(exception); + + AKANTU_EXCEPTION(sstr.str()); + } + + return pValue; +} + +/* -------------------------------------------------------------------------- */ + +__END_AKANTU__ diff --git a/src/python/python_functor.hh b/src/python/python_functor.hh new file mode 100644 index 000000000..5237cef37 --- /dev/null +++ b/src/python/python_functor.hh @@ -0,0 +1,124 @@ +/** + * @file python_functor.hh + * + + * @author Guillaume Anciaux + * + * + * @section LICENSE + * + * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see . + * + */ + + +#ifndef __AKANTU_PYTHON_FUNCTOR_HH__ +#define __AKANTU_PYTHON_FUNCTOR_HH__ +/* -------------------------------------------------------------------------- */ +#include "aka_common.hh" +#include +/* -------------------------------------------------------------------------- */ +__BEGIN_AKANTU__ +/* -------------------------------------------------------------------------- */ + + +class PythonFunctor { + + + /* ------------------------------------------------------------------------ */ + /* Constructors/Destructors */ + /* ------------------------------------------------------------------------ */ + +public: + PythonFunctor(PyObject * obj); + + + /* ------------------------------------------------------------------------ */ + /* Methods */ + /* ------------------------------------------------------------------------ */ + +protected: + + /// call the python functor + PyObject * callFunctor(PyObject * functor, + PyObject * args, + PyObject * kwargs) const; + + /// call the python functor from variadic types + template + return_type callFunctor(const std::string & functor_name, + Params&... parameters) const; + + /// empty function to cose the recursive template loop + inline void packArguments(std::vector & pArgs) const; + + /// get the python function object + inline PyObject * getPythonFunction(const std::string & functor_name) const; + + + /// variadic template for unknown number of arguments to unpack + template + inline void packArguments(std::vector & pArgs, + T & p, + Args&...params) const; + + /// convert an akantu object to python + template + inline PyObject *convertToPython(const T & akantu_obj) const; + + /// convert a stl vector to python + template + inline PyObject *convertToPython(const std::vector & akantu_obj) const; + + /// convert an akantu vector to python + template + inline PyObject *convertToPython(const Vector & akantu_obj) const; + + /// convert a akantu matrix to python + template + inline PyObject *convertToPython(const Matrix & akantu_obj) const; + + /// convert a python object to an akantu object + template + inline return_type convertToAkantu(PyObject * python_obj) const; + + /// convert a python object to an akantu object + template + inline std::vector convertListToAkantu(PyObject * python_obj) const; + + + /// returns the numpy data type code + template + inline int getPythonDataTypeCode() const; + + /* ------------------------------------------------------------------------ */ + /* Class Members */ + /* ------------------------------------------------------------------------ */ + + + PyObject * python_obj; + +}; +/* -------------------------------------------------------------------------- */ +__END_AKANTU__ +/* -------------------------------------------------------------------------- */ +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include "python_functor_inline_impl.cc" +/* -------------------------------------------------------------------------- */ + + +#endif /* __AKANTU_PYTHON_FUNCTOR_HH__ */ diff --git a/src/python/python_functor_inline_impl.cc b/src/python/python_functor_inline_impl.cc new file mode 100644 index 000000000..1b1c4fd6c --- /dev/null +++ b/src/python/python_functor_inline_impl.cc @@ -0,0 +1,244 @@ +#ifndef __AKANTU_PYTHON_FUNCTOR_INLINE_IMPL_CC__ +#define __AKANTU_PYTHON_FUNCTOR_INLINE_IMPL_CC__ +/* -------------------------------------------------------------------------- */ +#include +#include "integration_point.hh" +/* -------------------------------------------------------------------------- */ +__BEGIN_AKANTU__ +/* -------------------------------------------------------------------------- */ + + + +template +inline int PythonFunctor::getPythonDataTypeCode() const{ + AKANTU_EXCEPTION("undefined type"); +} + +/* -------------------------------------------------------------------------- */ + +template <> +inline int PythonFunctor::getPythonDataTypeCode() const{ + int data_typecode = NPY_NOTYPE; + size_t s = sizeof(bool); + switch(s) { + case 1: data_typecode = NPY_BOOL; break; + case 2: data_typecode = NPY_UINT16; break; + case 4: data_typecode = NPY_UINT32; break; + case 8: data_typecode = NPY_UINT64; break; + } + return data_typecode; +} +/* -------------------------------------------------------------------------- */ + +template <> +inline int PythonFunctor::getPythonDataTypeCode() const{ + return NPY_DOUBLE; +} + +/* -------------------------------------------------------------------------- */ + +template +PyObject *PythonFunctor::convertToPython(const T & akantu_object) const{ + AKANTU_DEBUG_TO_IMPLEMENT(); +} +/* -------------------------------------------------------------------------- */ + +template <> +inline PyObject *PythonFunctor::convertToPython(const double & akantu_object) const{ + return PyFloat_FromDouble(akantu_object); +} +/* -------------------------------------------------------------------------- */ + +template <> +inline PyObject *PythonFunctor::convertToPython(const UInt & akantu_object) const{ + return PyInt_FromLong(akantu_object); +} +/* -------------------------------------------------------------------------- */ + +template <> +inline PyObject *PythonFunctor::convertToPython(const bool & akantu_object) const{ + return PyBool_FromLong(long(akantu_object)); +} +/* -------------------------------------------------------------------------- */ + +template +inline PyObject *PythonFunctor::convertToPython(const std::vector & array) const{ + int data_typecode = getPythonDataTypeCode< T >(); + npy_intp dims[1] = {int(array.size())}; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, data_typecode, const_cast(&array[0])); + PyArrayObject* res = (PyArrayObject*) obj; + return (PyObject*)res; +} +/* -------------------------------------------------------------------------- */ + +template +PyObject *PythonFunctor::convertToPython(const Vector & array) const{ + int data_typecode = getPythonDataTypeCode< T >(); + npy_intp dims[1] = {array.size()}; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, data_typecode, array.storage()); + PyArrayObject* res = (PyArrayObject*) obj; + return (PyObject*)res; +} +/* -------------------------------------------------------------------------- */ + +template +PyObject *PythonFunctor::convertToPython(const Matrix & mat) const{ + int data_typecode = getPythonDataTypeCode< T >(); + npy_intp dims[2] = {mat.size(0),mat.size(1)}; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, data_typecode, mat.storage()); + PyArrayObject* res = (PyArrayObject*) obj; + return (PyObject*)res; +} +/* -------------------------------------------------------------------------- */ + +template <> +inline PyObject *PythonFunctor::convertToPython(const std::string & str) const{ + return PyString_FromString(str.c_str()); +} +/* -------------------------------------------------------------------------- */ + +template <> +inline PyObject *PythonFunctor::convertToPython(const IntegrationPoint & qp) const{ + + PyObject * input = PyDict_New(); + PyObject * num_point = this->convertToPython(qp.num_point); + PyObject * global_num = this->convertToPython(qp.global_num); + PyObject * material_id = this->convertToPython(qp.material_id); + PyObject * position = this->convertToPython(qp.getPosition()); + PyDict_SetItemString(input,"num_point",num_point); + PyDict_SetItemString(input,"global_num",global_num); + PyDict_SetItemString(input,"material_id",material_id); + PyDict_SetItemString(input,"position",position); + return input; +} +/* -------------------------------------------------------------------------- */ + + +inline PyObject * PythonFunctor::getPythonFunction(const std::string & functor_name) const{ + + if (!PyInstance_Check(this->python_obj)) + AKANTU_EXCEPTION("Python object is not an instance"); + + // if (!PyDict_Check(this->python_obj)) + // AKANTU_EXCEPTION("Python object is not a dictionary"); + + //PyObject * keys = PyDict_Keys(dict); + //PyObject_Print(keys, stdout, Py_PRINT_RAW); + + PyObject * pFunctor = PyObject_GetAttrString(this->python_obj, functor_name.c_str()); + if (!pFunctor) AKANTU_EXCEPTION("Python dictionary has no " << functor_name << " entry"); + + return pFunctor; +} +/* -------------------------------------------------------------------------- */ + +inline void PythonFunctor::packArguments(std::vector & pArgs)const {} + +/* -------------------------------------------------------------------------- */ + + +template +inline void PythonFunctor::packArguments(std::vector & pArgs, + T & p, + Args&...params)const{ + + pArgs.push_back(this->convertToPython(p)); + if (sizeof...(params) != 0) + this->packArguments(pArgs,params...); +} + +/* -------------------------------------------------------------------------- */ + + +template +return_type PythonFunctor::callFunctor(const std::string & functor_name, + Params&... parameters) const{ + + + _import_array(); + + std::vector arg_vector; + this->packArguments(arg_vector,parameters...); + + PyObject * pArgs = PyTuple_New(arg_vector.size()); + for (UInt i = 0; i < arg_vector.size(); ++i) { + PyTuple_SetItem(pArgs,i,arg_vector[i]); + } + + PyObject * kwargs = PyDict_New(); + + PyObject * pFunctor = getPythonFunction(functor_name); + PyObject * res = this->callFunctor(pFunctor,pArgs,kwargs); + + for (auto a: arg_vector) { + // if (PyDict_Check(a)){ + // PyObject* values = PyDict_Values(a); + // UInt sz = PyList_GET_SIZE(values); + // for (UInt i = 0; i < sz; ++i) { + // Py_XDECREF(PyList_GetItem(values,i)); + // } + // } + // Py_XDECREF(a); + } + Py_XDECREF(pArgs); + Py_XDECREF(kwargs); + + return this->convertToAkantu(res); + +} + +/* -------------------------------------------------------------------------- */ + +template +inline return_type PythonFunctor::convertToAkantu(PyObject * python_obj) const{ + + if (PyList_Check(python_obj)){ + return this->convertListToAkantu(python_obj); + } + AKANTU_DEBUG_TO_IMPLEMENT(); +} + +/* -------------------------------------------------------------------------- */ + +template <> +inline void PythonFunctor::convertToAkantu(PyObject * python_obj) const{ + if (python_obj != Py_None) AKANTU_DEBUG_WARNING("functor return a value while none was expected: ignored"); +} + +/* -------------------------------------------------------------------------- */ + + +template <> +inline std::string PythonFunctor::convertToAkantu(PyObject * python_obj) const{ + if (!PyString_Check(python_obj)) AKANTU_EXCEPTION("cannot convert object to string"); + return PyString_AsString(python_obj); +} + +/* -------------------------------------------------------------------------- */ + +template <> +inline Real PythonFunctor::convertToAkantu(PyObject * python_obj) const{ + if (!PyFloat_Check(python_obj)) AKANTU_EXCEPTION("cannot convert object to float"); + return PyFloat_AsDouble(python_obj); +} + +/* -------------------------------------------------------------------------- */ + +template +inline std::vector PythonFunctor::convertListToAkantu(PyObject * python_obj) const{ + + std::vector res; + UInt size = PyList_Size(python_obj); + for (UInt i = 0; i < size; ++i) { + PyObject * item = PyList_GET_ITEM(python_obj,i); + res.push_back(this->convertToAkantu(item)); + } + return res; +} + +/* -------------------------------------------------------------------------- */ + +__END_AKANTU__ + + +#endif /* __AKANTU_PYTHON_FUNCTOR_INLINE_IMPL_CC__ */ diff --git a/test/test_solver/test_petsc_matrix_apply_boundary.cc b/test/test_solver/test_petsc_matrix_apply_boundary.cc index 92e598bab..54cb37117 100644 --- a/test/test_solver/test_petsc_matrix_apply_boundary.cc +++ b/test/test_solver/test_petsc_matrix_apply_boundary.cc @@ -1,140 +1,141 @@ /** * @file test_petsc_matrix_profile.cc * @author Aurelia Cuba Ramos * @date Wed Jul 30 12:34:08 2014 * * @brief test the applyBoundary method of the PETScMatrix 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 "static_communicator.hh" #include "aka_common.hh" #include "aka_csr.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_utils.hh" #include "distributed_synchronizer.hh" #include "petsc_matrix.hh" #include "fe_engine.hh" #include "dof_synchronizer.hh" #include "mesh_partition_scotch.hh" using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const ElementType element_type = _triangle_3; const GhostType ghost_type = _not_ghost; UInt spatial_dimension = 2; StaticCommunicator & comm = akantu::StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); /// read the mesh and partition it Mesh mesh(spatial_dimension); /* ------------------------------------------------------------------------ */ /* Parallel initialization */ /* ------------------------------------------------------------------------ */ DistributedSynchronizer * communicator = NULL; if(prank == 0) { /// creation mesh mesh.read("triangle.msh"); MeshPartitionScotch * partition = new MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); communicator = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, partition); delete partition; } else { communicator = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, NULL); } FEEngine *fem = new FEEngineTemplate(mesh, spatial_dimension, "my_fem"); DOFSynchronizer dof_synchronizer(mesh, spatial_dimension); UInt nb_global_nodes = mesh.getNbGlobalNodes(); dof_synchronizer.initGlobalDOFEquationNumbers(); // fill the matrix with UInt nb_element = mesh.getNbElement(element_type); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(element_type); UInt nb_dofs_per_element = spatial_dimension * nb_nodes_per_element; SparseMatrix K(nb_global_nodes * spatial_dimension, _symmetric); K.buildProfile(mesh, dof_synchronizer, spatial_dimension); Matrix element_input(nb_dofs_per_element, nb_dofs_per_element, 1); Array K_e = Array(nb_element, nb_dofs_per_element * nb_dofs_per_element, "K_e"); Array::matrix_iterator K_e_it = K_e.begin(nb_dofs_per_element, nb_dofs_per_element); Array::matrix_iterator K_e_end = K_e.end(nb_dofs_per_element, nb_dofs_per_element); for(; K_e_it != K_e_end; ++K_e_it) *K_e_it = element_input; // assemble the test matrix fem->assembleMatrix(K_e, K, spatial_dimension, element_type, ghost_type); // create petsc matrix PETScMatrix petsc_matrix(nb_global_nodes * spatial_dimension, _symmetric); petsc_matrix.buildProfile(mesh, dof_synchronizer, spatial_dimension); // add stiffness matrix to petsc matrix petsc_matrix.add(K, 1); // create boundary array: block all dofs UInt nb_nodes = mesh.getNbNodes(); Array boundary = Array(nb_nodes, spatial_dimension, true); // apply boundary petsc_matrix.applyBoundary(boundary); // test if all entries except the diagonal ones have been zeroed Real test_passed = 0; for (UInt i = 0; i < nb_nodes * spatial_dimension; ++i) { if (dof_synchronizer.isLocalOrMasterDOF(i)) { for (UInt j = 0; j < nb_nodes * spatial_dimension; ++j) { if (dof_synchronizer.isLocalOrMasterDOF(j)) { if (i == j) test_passed += petsc_matrix(i, j) - 1; else test_passed += petsc_matrix(i, j) - 0; } } } } - if (std::abs(test_passed) > Math::getTolerance()) + if (std::abs(test_passed) > Math::getTolerance()) { + finalize(); return EXIT_FAILURE; - + } delete communicator; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_solver/test_petsc_matrix_diagonal.cc b/test/test_solver/test_petsc_matrix_diagonal.cc index e7fa90127..dd3eed87d 100644 --- a/test/test_solver/test_petsc_matrix_diagonal.cc +++ b/test/test_solver/test_petsc_matrix_diagonal.cc @@ -1,146 +1,147 @@ /** * @file test_petsc_matrix_diagonal.cc * @author Aurelia Isabel Cuba Ramos * @date Wed Apr 22 09:41:14 2015 * * @brief test the connectivity is correctly represented in the PETScMatrix * * @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 "static_communicator.hh" #include "aka_common.hh" #include "aka_csr.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_utils.hh" #include "distributed_synchronizer.hh" #include "petsc_matrix.hh" #include "fe_engine.hh" #include "dof_synchronizer.hh" #include "dumper_paraview.hh" #include "mesh_partition_scotch.hh" using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const ElementType element_type = _triangle_3; const GhostType ghost_type = _not_ghost; UInt spatial_dimension = 2; StaticCommunicator & comm = akantu::StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); /// read the mesh and partition it Mesh mesh(spatial_dimension); /* ------------------------------------------------------------------------ */ /* Parallel initialization */ /* ------------------------------------------------------------------------ */ DistributedSynchronizer * communicator = NULL; if(prank == 0) { /// creation mesh mesh.read("triangle.msh"); MeshPartitionScotch * partition = new MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); communicator = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, partition); delete partition; } else { communicator = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, NULL); } // DumperParaview mesh_dumper("mesh_dumper"); // mesh_dumper.registerMesh(mesh, spatial_dimension, _not_ghost); // mesh_dumper.dump(); /// initialize the FEEngine and the dof_synchronizer FEEngine *fem = new FEEngineTemplate(mesh, spatial_dimension, "my_fem"); DOFSynchronizer dof_synchronizer(mesh, spatial_dimension); UInt nb_global_nodes = mesh.getNbGlobalNodes(); dof_synchronizer.initGlobalDOFEquationNumbers(); // construct an Akantu sparse matrix, build the profile and fill the matrix for the given mesh UInt nb_element = mesh.getNbElement(element_type); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(element_type); UInt nb_dofs_per_element = spatial_dimension * nb_nodes_per_element; SparseMatrix K_akantu(nb_global_nodes * spatial_dimension, _unsymmetric); K_akantu.buildProfile(mesh, dof_synchronizer, spatial_dimension); /// use as elemental matrices a matrix with values equal to 1 every where Matrix element_input(nb_dofs_per_element, nb_dofs_per_element, 1.); Array K_e = Array(nb_element, nb_dofs_per_element * nb_dofs_per_element, "K_e"); Array::matrix_iterator K_e_it = K_e.begin(nb_dofs_per_element, nb_dofs_per_element); Array::matrix_iterator K_e_end = K_e.end(nb_dofs_per_element, nb_dofs_per_element); for(; K_e_it != K_e_end; ++K_e_it) *K_e_it = element_input; // assemble the test matrix fem->assembleMatrix(K_e, K_akantu, spatial_dimension, element_type, ghost_type); /// construct a PETSc matrix PETScMatrix K_petsc(nb_global_nodes * spatial_dimension, _unsymmetric); /// build the profile of the PETSc matrix for the mesh of this example K_petsc.buildProfile(mesh, dof_synchronizer, spatial_dimension); /// add an Akantu sparse matrix to a PETSc sparse matrix K_petsc.add(K_akantu, 1); /// check to how many elements each node is connected CSR node_to_elem; MeshUtils::buildNode2Elements(mesh, node_to_elem, spatial_dimension); /// test the diagonal of the PETSc matrix: the diagonal entries /// of the PETSc matrix correspond to the number of elements /// connected to the node of the dof. Note: for an Akantu matrix this is only true for the serial case Real error = 0.; /// loop over all diagonal values of the matrix for (UInt i = 0; i < mesh.getNbNodes(); ++i) { for (UInt j = 0; j < spatial_dimension; ++j) { UInt dof = i * spatial_dimension + j; /// for PETSc matrix only DOFs on the processor and be accessed if (dof_synchronizer.isLocalOrMasterDOF(dof)) { UInt global_dof = dof_synchronizer.getDOFGlobalID(dof); std::cout << "Number of elements connected: " << node_to_elem.getNbCols(i) << std::endl; std::cout << "K_petsc(" << global_dof << "," << global_dof << ")=" << K_petsc(dof,dof) << std::endl; error += std::abs(K_petsc(dof, dof) - node_to_elem.getNbCols(i)); } } } if(error > Math::getTolerance() ) { std::cout << "error in the stiffness matrix!!!" << std::cout; + finalize(); return EXIT_FAILURE; } delete communicator; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_solver/test_solver_petsc.cc b/test/test_solver/test_solver_petsc.cc index 2eb172f50..2ad17899c 100644 --- a/test/test_solver/test_solver_petsc.cc +++ b/test/test_solver/test_solver_petsc.cc @@ -1,161 +1,162 @@ /** * @file test_solver_petsc.cc * @author Aurelia Cuba Ramos * @date Tue Dec 2 17:17:34 2014 * * @brief test the PETSc solver interface * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include "static_communicator.hh" #include "aka_common.hh" #include "aka_csr.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_utils.hh" #include "distributed_synchronizer.hh" #include "petsc_matrix.hh" #include "solver_petsc.hh" #include "fe_engine.hh" #include "dof_synchronizer.hh" #include "mesh_partition_scotch.hh" using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const ElementType element_type = _segment_2; const GhostType ghost_type = _not_ghost; UInt spatial_dimension = 1; StaticCommunicator & comm = akantu::StaticCommunicator::getStaticCommunicator(); Int psize = comm.getNbProc(); Int prank = comm.whoAmI(); /// read the mesh and partition it Mesh mesh(spatial_dimension); /* ------------------------------------------------------------------------ */ /* Parallel initialization */ /* ------------------------------------------------------------------------ */ DistributedSynchronizer * communicator = NULL; if(prank == 0) { /// creation mesh mesh.read("1D_bar.msh"); MeshPartitionScotch * partition = new MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); communicator = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, partition); delete partition; } else { communicator = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, NULL); } FEEngine *fem = new FEEngineTemplate(mesh, spatial_dimension, "my_fem"); DOFSynchronizer dof_synchronizer(mesh, spatial_dimension); UInt nb_global_nodes = mesh.getNbGlobalNodes(); dof_synchronizer.initGlobalDOFEquationNumbers(); // fill the matrix with UInt nb_element = mesh.getNbElement(element_type); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(element_type); UInt nb_dofs_per_element = spatial_dimension * nb_nodes_per_element; SparseMatrix K(nb_global_nodes * spatial_dimension, _symmetric); K.buildProfile(mesh, dof_synchronizer, spatial_dimension); Matrix element_input(nb_dofs_per_element, nb_dofs_per_element, 0); for (UInt i = 0; i < nb_dofs_per_element; ++i) { for (UInt j = 0; j < nb_dofs_per_element; ++j) { element_input(i, j) = ((i == j) ? 1 : -1); } } Array K_e = Array(nb_element, nb_dofs_per_element * nb_dofs_per_element, "K_e"); Array::matrix_iterator K_e_it = K_e.begin(nb_dofs_per_element, nb_dofs_per_element); Array::matrix_iterator K_e_end = K_e.end(nb_dofs_per_element, nb_dofs_per_element); for(; K_e_it != K_e_end; ++K_e_it) *K_e_it = element_input; // assemble the test matrix fem->assembleMatrix(K_e, K, spatial_dimension, element_type, ghost_type); // apply boundary: block first node const Array & position = mesh.getNodes(); UInt nb_nodes = mesh.getNbNodes(); Array boundary = Array(nb_nodes, spatial_dimension, false); for (UInt i = 0; i < nb_nodes; ++i) { if (std::abs(position(i, 0)) < Math::getTolerance() ) boundary(i, 0) = true; } K.applyBoundary(boundary); /// create the PETSc matrix for the solve step PETScMatrix petsc_matrix(nb_global_nodes * spatial_dimension, _symmetric); petsc_matrix.buildProfile(mesh, dof_synchronizer, spatial_dimension); /// copy the stiffness matrix into the petsc matrix petsc_matrix.add(K, 1); // initialize internal forces: they are zero because imposed displacement is zero Array internal_forces(nb_nodes, spatial_dimension, 0.); // compute residual: apply nodal force on last node Array residual(nb_nodes, spatial_dimension, 0.); for (UInt i = 0; i < nb_nodes; ++i) { if (std::abs(position(i, 0) - 10) < Math::getTolerance() ) residual(i, 0) += 2; } residual -= internal_forces; /// initialize solver and solution Array solution(nb_nodes, spatial_dimension, 0.); SolverPETSc solver(petsc_matrix); solver.initialize(); solver.setOperators(); solver.setRHS(residual); solver.solve(solution); /// verify solution Math::setTolerance(1e-11); for (UInt i = 0; i < nb_nodes; ++i) { if (!dof_synchronizer.isPureGhostDOF(i) && !Math::are_float_equal(2 * position(i, 0), solution(i, 0))) { std::cout << "The solution is not correct!!!!" << std::endl; + finalize(); return EXIT_FAILURE; } } delete communicator; finalize(); return EXIT_SUCCESS; } diff --git a/third-party/cmake/blas.cmake b/third-party/cmake/blas.cmake index 1e3a8bd50..62288c4f3 100644 --- a/third-party/cmake/blas.cmake +++ b/third-party/cmake/blas.cmake @@ -1,22 +1,24 @@ set(BLAS_DIR ${PROJECT_BINARY_DIR}/third-party) configure_file( ${PROJECT_SOURCE_DIR}/third-party/blas_${BLAS_VERSION}_make.inc.cmake ${BLAS_DIR}/blas_make.inc @ONLY) +file(MAKE_DIRECTORY ${BLAS_DIR}/lib) + ExternalProject_Add(netlib-blas PREFIX ${BLAS_DIR} URL ${BLAS_ARCHIVE} CONFIGURE_COMMAND cmake -E copy ${BLAS_DIR}/blas_make.inc make.inc BUILD_IN_SOURCE 1 BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} INSTALL_COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SHARED_LIBRARY_PREFIX}blas${CMAKE_SHARED_LIBRARY_SUFFIX} /lib LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 ) package_add_extra_dependency(BLAS netlib-blas) set_third_party_shared_libirary_name(BLAS_LIBRARIES blas) diff --git a/third-party/cmake/iohelper.cmake b/third-party/cmake/iohelper.cmake index 687bf6942..507973371 100644 --- a/third-party/cmake/iohelper.cmake +++ b/third-party/cmake/iohelper.cmake @@ -1,40 +1,45 @@ if(NOT EXISTS ${PROJECT_SOURCE_DIR}/third-party/${IOHELPER_ARCHIVE}) set(_iohelper_download_command GIT_REPOSITORY ${IOHELPER_GIT} GIT_TAG ${IOHELPER_VERSION} ) else() set(_iohelper_download_command URL ${PROJECT_SOURCE_DIR}/third-party/${IOHELPER_ARCHIVE} ) endif() if(CMAKE_VERSION VERSION_GREATER 3.1) set(_extra_options UPDATE_DISCONNECTED 1 DOWNLOAD_NO_PROGRESS 1 EXCLUDE_FROM_ALL 1 ) endif() ExternalProject_Add(iohelper PREFIX ${PROJECT_BINARY_DIR}/third-party ${_iohelper_download_command} ${_extra_options} CMAKE_ARGS / CMAKE_CACHE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_CXX_COMPILER:PATH=${CMAKE_CXX_COMPILER} LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 ) set_third_party_shared_libirary_name(IOHELPER_LIBRARIES iohelper) +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(_tmp ${IOHELPER_LIBRARIES}) + set(IOHELPER_LIBRARIES "${_tmp}.a" CACHE FILEPATH "" FORCE) +endif() + set(IOHELPER_INCLUDE_DIR "${PROJECT_BINARY_DIR}/third-party/include/iohelper" CACHE PATH "IOHelper include directory") mark_as_advanced( IOHELPER_LIBRARIES IOHELPER_INCLUDE_DIR ) package_add_extra_dependency(IOHelper iohelper) diff --git a/third-party/cmake/mumps.cmake b/third-party/cmake/mumps.cmake index 514057d90..2153aa534 100644 --- a/third-party/cmake/mumps.cmake +++ b/third-party/cmake/mumps.cmake @@ -1,153 +1,152 @@ #=============================================================================== # @file mumps.cmake # # @author Nicolas Richart # # @date creation: Mon Nov 21 2011 # @date last modification: Mon Sep 15 2014 # # @brief compilation of the third-party MUMPS # # @section LICENSE # # Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # #=============================================================================== enable_language(Fortran) set(MUMPS_VERSION ${AKANTU_USE_MUMPS_VERSION}) set(MUMPS_ARCHIVE "${PROJECT_SOURCE_DIR}/third-party/MUMPS_${MUMPS_VERSION}.tar.gz") set(MUMPS_ARCHIVE_HASH_4.9.2 "MD5=d0b8f139a4acf29b76dbae69ade8ac54") set(MUMPS_ARCHIVE_HASH_4.10.0 "MD5=959e9981b606cd574f713b8422ef0d9f") set(MUMPS_ARCHIVE_HASH_5.0.0 "MD5=3c6aeab847e9d775ca160194a9db2b75") if(NOT EXISTS ${MUMPS_ARCHIVE}) message(FATAL_ERROR "To be able to compile MUMPS please download it from " "http://mumps.enseeiht.fr/ or http://graal.ens-lyon.fr/MUMPS and place it " "in the directory: ${PROJECT_SOURCE_DIR}/third-party and in cmake set the " "variable AKANTU_MUMPS_VERSION to the corresponding version " "\n" "Supported version for automated compilation in Akantu are 4.9.2, 4.10.0 " "and 5.0.0") endif() package_get_option_name(MPI _mpi_option) if(${_mpi_option}) unset(MUMPS_PREFIX) else() set(MUMPS_PREFIX _seq) endif() -package_get_option_name(Scotch _scotch_option) package_use_system(Scotch _scotch_use_system) -if(NOT _scotch_use_system AND ${_scotch_option}) +if(NOT _scotch_use_system) list(APPEND MUMPS_DEPENDS Scotch) endif() package_get_option_name(ScaLAPACK _scalapack_option) package_use_system(ScaLAPACK _scalapack_use_system) if(NOT _scalapack_use_system AND ${_scalapack_option}) list(APPEND MUMPS_DEPENDS ScaLAPACK) endif() include(AkantuMacros) package_get_libraries(Scotch _scotch_libraries) string(REPLACE ";" " " MUMPS_SCOTCH_LIBRARIES "${_scotch_libraries};${SCOTCH_LIBRARY_ESMUMPS}") package_get_libraries(BLAS _blas_libraries) foreach(_blas_lib ${_blas_libraries}) if("${_blas_lib}" MATCHES ".*\\.framework") get_filename_component(_blas_framework "${_blas_lib}" NAME_WE) set(MUMPS_BLAS_LIBRARIES "${MUMPS_BLAS_LIBRARIES} -framework ${_blas_framework}") else() set(MUMPS_BLAS_LIBRARIES "${MUMPS_BLAS_LIBRARIES} ${_blas_lib}") endif() endforeach() if("${MUMPS_TYPE}" STREQUAL "seq") set_third_party_shared_libirary_name(MUMPS_LIBRARY_MPI mpiseq${MUMPS_PREFIX}) mark_as_advanced(MUMPS_LIBRARY_MPI) else() set(MUMPS_LIBRARY_MPI "") endif() if(CMAKE_C_COMPILER_ID STREQUAL "Intel") set(MUMPS_EXTRA_Fortran_FLAGS "-nofor_main") else() set(MUMPS_EXTRA_Fortran_FLAGS "") endif() if(CMAKE_VERSION VERSION_GREATER 3.1) set(_extra_options DOWNLOAD_NO_PROGRESS 1 EXCLUDE_FROM_ALL 1 ) endif() if(CMAKE_SYSTEM_NAME STREQUAL "Windows") set(AKANTU_MUMPS_CDEFS "-DAdd_ -DWITHOUT_PTHREAD") else() set(AKANTU_MUMPS_CDEFS "-DAdd_") set(AKANTU_MUMPS_PTHREAD "-lpthread") endif() configure_file(${PROJECT_SOURCE_DIR}/third-party/MUMPS_${MUMPS_VERSION}_make.inc.cmake ${PROJECT_BINARY_DIR}/third-party/MUMPS_make.inc @ONLY) ExternalProject_Add(MUMPS DEPENDS ${MUMPS_DEPENDS} PREFIX ${PROJECT_BINARY_DIR}/third-party URL ${MUMPS_ARCHIVE} URL_HASH ${MUMPS_ARCHIVE_HASH_${MUMPS_VERSION}} ${_extra_options} BUILD_IN_SOURCE 1 - PATCH_COMMAND patch -p2 < ${PROJECT_SOURCE_DIR}/third-party/MUMPS_${MUMPS_VERSION}.patch + PATCH_COMMAND ${PATCH_COMMAND} -p2 < ${PROJECT_SOURCE_DIR}/third-party/MUMPS_${MUMPS_VERSION}.patch CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/third-party/MUMPS_make.inc Makefile.inc BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} d INSTALL_COMMAND "${CMAKE_MAKE_PROGRAM}" prefix= install LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 ) set_third_party_shared_libirary_name(MUMPS_LIBRARY_DMUMPS dmumps${MUMPS_PREFIX}) set_third_party_shared_libirary_name(MUMPS_LIBRARY_COMMON mumps_common${MUMPS_PREFIX}) set_third_party_shared_libirary_name(MUMPS_LIBRARY_PORD pord${MUMPS_PREFIX}) mark_as_advanced( MUMPS_LIBRARY_COMMON MUMPS_LIBRARY_DMUMPS MUMPS_LIBRARY_PORD MUMPS_LIBRARY_MPI MUMPS_INCLUDE_DIR ) set(MUMPS_LIBRARIES_ALL ${MPI_Fortran_LIBRARIES} ${MUMPS_LIBRARY_COMMON} ${MUMPS_LIBRARY_DMUMPS} ${MUMPS_LIBRARY_PORD} ${MUMPS_LIBRARY_MPI}) set(MUMPS_INCLUDE_DIR ${PROJECT_BINARY_DIR}/third-party/include CACHE PATH "" FORCE) set(MUMPS_LIBRARIES ${MUMPS_LIBRARIES_ALL} CACHE INTERNAL "Libraries for MUMPS" FORCE) package_add_extra_dependency(Mumps MUMPS) diff --git a/third-party/cmake/scotch.cmake b/third-party/cmake/scotch.cmake index 96f37c928..31e9ddc1e 100644 --- a/third-party/cmake/scotch.cmake +++ b/third-party/cmake/scotch.cmake @@ -1,98 +1,98 @@ if(TARGET Scotch) return() endif() if(NOT EXISTS ${PROJECT_SOURCE_DIR}/third-party/${SCOTCH_ARCHIVE}) set(_scotch_download_command URL ${SCOTCH_URL} # URL_HASH ${SCOTCH_ARCHIVE_HASH} TLS_VERIFY FALSE ) else() set(_scotch_download_command URL ${PROJECT_SOURCE_DIR}/third-party/${SCOTCH_ARCHIVE} URL_HASH ${SCOTCH_ARCHIVE_HASH}) endif() if(CMAKE_VERSION VERSION_GREATER 3.1) set(_extra_options DOWNLOAD_NO_PROGRESS 1 EXCLUDE_FROM_ALL 1 ) endif() find_package(BISON REQUIRED) find_package(FLEX REQUIRED) find_package(ZLIB) #if(ZLIB_FOUND) # set(_zlib_cflags "-DCOMMON_FILE_COMPRESS_GZ -I${ZLIB_INCLUDE_DIR}") # set(_zlib_ldflags "${ZLIB_LIBRARY}") #endif() if(NOT CMAKE_SYSTEM_NAME STREQUAL "Windows") if (AKANTU_USE_OBSOLETE_GETTIMEOFDAY) set(_timing_cflags -DCOMMON_TIMING_OLD) endif() set(_system_cflags "-DCOMMON_PTHREAD -DSCOTCH_PTHREAD ${_timing_cflags}") set(_system_ldflags "-lpthread") else() set(_system_cflags "-DCOMMON_RANDOM_RAND -DCOMMON_WINDOWS -DCOMMON_STUB_FORK -D'pipe(pfds)=_pipe(pfds,1024,0x8000)'") endif() if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(_architecture_cflags -DIDXSIZE64) endif() math(EXPR _n "${AKANTU_INTEGER_SIZE} * 8") if(NOT _n EQUAL 32) set(_num_size_cflags "-DINTSIZE${_n}") endif() if(HAVE_STDINT_H) set(_stdint -DHAVE_STDINT_H) endif() set(AKANTU_SCOTCH_CFLAGS "-O3 -w -fPIC -Drestrict=__restrict -DCOMMON_RANDOM_FIXED_SEED -DSCOTCH_RENAME -DSCOTCH_RENAME_PARSER ${_zlib_cflags} ${_system_cflags} ${_architecture_cflags} ${_num_size_cflags} ${_stdint}") set(AKANTU_SCOTCH_LDFLAGS "${_zlib_ldflags} ${_system_ldflags} -lm") set(SCOTCH_DIR ${PROJECT_BINARY_DIR}/third-party) configure_file( ${PROJECT_SOURCE_DIR}/third-party/scotch_${SCOTCH_VERSION}_make.inc.cmake ${SCOTCH_DIR}/scotch_make.inc) include(ExternalProject) ExternalProject_Add(Scotch PREFIX ${SCOTCH_DIR} ${_scotch_download_command} ${_extra_options} - PATCH_COMMAND patch -p1 < ${PROJECT_SOURCE_DIR}/third-party/scotch_${SCOTCH_VERSION}.patch - CONFIGURE_COMMAND cmake -E copy ${SCOTCH_DIR}/scotch_make.inc src/Makefile.inc + PATCH_COMMAND ${PATCH_COMMAND} -p1 < ${PROJECT_SOURCE_DIR}/third-party/scotch_${SCOTCH_VERSION}.patch + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E copy ${SCOTCH_DIR}/scotch_make.inc src/Makefile.inc BUILD_IN_SOURCE 1 BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} -C src INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} prefix= -C src install LOG_DOWNLOAD 1 LOG_CONFIGURE 1 LOG_BUILD 1 LOG_INSTALL 1 ) set_third_party_shared_libirary_name(SCOTCH_LIBRARY scotch) set_third_party_shared_libirary_name(SCOTCH_LIBRARY_ERR scotcherr) set_third_party_shared_libirary_name(SCOTCH_LIBRARY_ERREXIT scotcherrexit) set_third_party_shared_libirary_name(SCOTCH_LIBRARY_ESMUMPS esmumps) set(SCOTCH_INCLUDE_DIR ${SCOTCH_DIR}/include CACHE PATH "" FORCE) mark_as_advanced( SCOTCH_LIBRARY SCOTCH_LIBRARY_ERR SCOTCH_LIBRARY_ERREXIT SCOTCH_LIBRARY_ESMUMPS SCOTCH_INCLUDE_DIR) set(SCOTCH_LIBRARIES_ALL ${SCOTCH_LIBRARY} ${SCOTCH_LIBRARY_ERR}) set(SCOTCH_LIBRARIES ${SCOTCH_LIBRARIES_ALL} CACHE INTERNAL "Libraries for scotch" FORCE) package_add_extra_dependency(Scotch Scotch)