diff --git a/cmake/AkantuTestAndExamples.cmake b/cmake/AkantuTestAndExamples.cmake index da4351c65..d5a82c54a 100644 --- a/cmake/AkantuTestAndExamples.cmake +++ b/cmake/AkantuTestAndExamples.cmake @@ -1,321 +1,336 @@ #=============================================================================== # @file AkantuTestAndExamples.cmake # # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @author Nicolas Richart <nicolas.richart@epfl.ch> # # @date creation: Mon Oct 25 2010 # @date last modification: Tue Jun 24 2014 # # @brief macros for tests and examples # # @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 <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== set(AKANTU_DIFF_SCRIPT ${AKANTU_CMAKE_DIR}/akantu_diff.sh) #=============================================================================== function(manage_test_and_example et_name desc build_all label) string(TOUPPER ${et_name} upper_name) cmake_parse_arguments(manage_test_and_example "" "PACKAGE" "" ${ARGN} ) set(_activated ON) if(manage_test_and_example_PACKAGE) list(FIND ${_project}_PACKAGE_SYSTEM_PACKAGES_ON ${manage_test_and_example_PACKAGE} _ret) if(_ret EQUAL -1) set(_activated OFF) file(RELATIVE_PATH _dir ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${et_name}) list(APPEND AKANTU_TESTS_EXCLUDE_FILES /${_dir}) set(AKANTU_TESTS_EXCLUDE_FILES ${AKANTU_TESTS_EXCLUDE_FILES} CACHE INTERNAL "") endif() endif() if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${et_name} AND _activated) # message("Example or test ${et_name} not present") return() endif() option(AKANTU_BUILD${label}${upper_name} "${desc}") mark_as_advanced(AKANTU_BUILD_${upper_name}) if(${build_all} OR NOT _activated) set(AKANTU_BUILD${label}${upper_name}_OLD ${AKANTU_BUILD${label}${upper_name}} CACHE INTERNAL "${desc}" FORCE) set(AKANTU_BUILD${label}${upper_name} ${_activated} CACHE INTERNAL "${desc}" FORCE) else() if(DEFINED AKANTU_BUILD${label}${upper_name}_OLD) set(AKANTU_BUILD${label}${upper_name} ${AKANTU_BUILD${label}${upper_name}_OLD} CACHE BOOL "${desc}" FORCE) unset(AKANTU_BUILD${label}${upper_name}_OLD CACHE) endif(DEFINED AKANTU_BUILD${label}${upper_name}_OLD) endif() if(AKANTU_BUILD${label}${upper_name}) add_subdirectory(${et_name}) endif(AKANTU_BUILD${label}${upper_name}) endfunction() #=============================================================================== # Tests #=============================================================================== if(AKANTU_TESTS) option(AKANTU_BUILD_ALL_TESTS "Build all tests" ON) + option(AKANTU_BUILD_UNSTABLE_TESTS "Build the tests marked as unstable" OFF) mark_as_advanced(AKANTU_BUILD_ALL_TESTS) + mark_as_advanced(AKANTU_BUILD_UNSTABLE_TESTS) endif(AKANTU_TESTS) #=============================================================================== # Examples #=============================================================================== if(AKANTU_EXAMPLES) option(AKANTU_BUILD_ALL_EXAMPLES "Build all examples") # mark_as_advanced(AKANTU_BUILD_ALL_EXAMPLES) endif(AKANTU_EXAMPLES) #=============================================================================== macro(register_example example_name) add_executable(${example_name} ${ARGN}) target_link_libraries(${example_name} akantu ${AKANTU_EXTERNAL_LIBRARIES}) endmacro() #=============================================================================== macro(add_example example_name desc) manage_test_and_example(${example_name} ${desc} AKANTU_BUILD_ALL_EXAMPLES _EXAMPLE_ ${ARGN}) endmacro() # ============================================================================== # this should be a macro due to the enable_testing macro(add_test_tree dir) if(AKANTU_TESTS) enable_testing() include(CTest) mark_as_advanced(BUILD_TESTING) set(AKANTU_TESTS_EXCLUDE_FILES "" CACHE INTERNAL "") set(_akantu_current_parent_test ${dir} CACHE INTERNAL "Current test folder" FORCE) set(_akantu_${dir}_tests_count 0 CACHE INTERNAL "" FORCE) string(TOUPPER ${dir} _u_dir) set(AKANTU_BUILD_${_u_dir} ON CACHE INTERNAL "${desc}" FORCE) package_get_all_test_folders(_test_dirs) foreach(_dir ${_test_dirs}) add_subdirectory(${_dir}) endforeach() else() set(AKANTU_TESTS_EXCLUDE_FILES "${CMAKE_CURRENT_BINARY_DIR}/${dir}" CACHE INTERNAL "") endif() endmacro() # ============================================================================== function(add_akantu_test dir desc) set(_my_parent_dir ${_akantu_current_parent_test}) # initialize variables set(_akantu_current_parent_test ${dir} CACHE INTERNAL "Current test folder" FORCE) set(_akantu_${dir}_tests_count 0 CACHE INTERNAL "" FORCE) # set the option for this directory string(TOUPPER ${dir} _u_dir) option(AKANTU_BUILD_${_u_dir} "${desc}") mark_as_advanced(AKANTU_BUILD_${_u_dir}) # add the sub-directory add_subdirectory(${dir}) # if no test can be activated make the option disappear set(_force_deactivate_count FALSE) if(${_akantu_${dir}_tests_count} EQUAL 0) set(_force_deactivate_count TRUE) endif() # if parent off make the option disappear set(_force_deactivate_parent FALSE) string(TOUPPER ${_my_parent_dir} _u_parent_dir) if(NOT AKANTU_BUILD_${_u_parent_dir}) set(_force_deactivate_parent TRUE) endif() if(_force_deactivate_parent OR _force_deactivate_count OR AKANTU_BUILD_ALL_TESTS) if(NOT DEFINED _AKANTU_BUILD_${_u_dir}_SAVE) set(_AKANTU_BUILD_${_u_dir}_SAVE ${AKANTU_BUILD_${_u_dir}} CACHE INTERNAL "" FORCE) endif() unset(AKANTU_BUILD_${_u_dir} CACHE) if(AKANTU_BUILD_ALL_TESTS AND NOT _force_deactivate_count) set(AKANTU_BUILD_${_u_dir} ON CACHE INTERNAL "${desc}" FORCE) else() set(AKANTU_BUILD_${_u_dir} OFF CACHE INTERNAL "${desc}" FORCE) endif() else() if(DEFINED _AKANTU_BUILD_${_u_dir}_SAVE) unset(AKANTU_BUILD_${_u_dir} CACHE) set(AKANTU_BUILD_${_u_dir} ${_AKANTU_BUILD_${_u_dir}_SAVE} CACHE BOOL "${desc}") unset(_AKANTU_BUILD_${_u_dir}_SAVE CACHE) endif() endif() # adding up to the parent count math(EXPR _tmp_parent_count "${_akantu_${dir}_tests_count} + ${_akantu_${_my_parent_dir}_tests_count}") set(_akantu_${_my_parent_dir}_tests_count ${_tmp_parent_count} CACHE INTERNAL "" FORCE) # restoring the parent current dir set(_akantu_current_parent_test ${_my_parent_dir} CACHE INTERNAL "Current test folder" FORCE) endfunction() # ============================================================================== function(register_test test_name) set(multi_variables - SOURCES FILES_TO_COPY DEPENDENCIES DIRECTORIES_TO_CREATE COMPILE_OPTIONS EXTRA_FILES + SOURCES FILES_TO_COPY DEPENDENCIES DIRECTORIES_TO_CREATE COMPILE_OPTIONS EXTRA_FILES PACKAGE ) cmake_parse_arguments(_register_test + "UNSTABLE" "" - "PACKAGE" "${multi_variables}" ${ARGN} ) if(NOT _register_test_PACKAGE) message(FATAL_ERROR "No reference package was defined for the test ${test_name} in folder ${CMAKE_CURRENT_SOURCE_DIR}") endif() - package_is_activated(${_register_test_PACKAGE} _act) + set(_test_act TRUE) + # Activate the test anly if all packages associated to the test are activated + foreach(_package ${_register_test_PACKAGE}) + package_is_activated(${_package} _act) + if(NOT _act) + set(_test_act FALSE) + endif() + endforeach() + + # check if the test is marked unstable and if the unstable test should be run + if(_register_test_UNSTABLE AND NOT AKANTU_BUILD_UNSTABLE_TESTS) + set(_test_act FALSE) + endif() - if(_act) + # todo this should be checked for the build package_sources since the file will not be listed. + if(_test_act) math(EXPR _tmp_parent_count "${_akantu_${_akantu_current_parent_test}_tests_count} + 1") set(_akantu_${_akantu_current_parent_test}_tests_count ${_tmp_parent_count} CACHE INTERNAL "" FORCE) string(TOUPPER ${_akantu_current_parent_test} _u_parent) if(AKANTU_BUILD_${_u_parent} OR AKANTU_BUILD_ALL_TESTS) # get the include directories for sources in activated directories package_get_all_include_directories( AKANTU_LIBRARY_INCLUDE_DIRS ) # get the external packages compilation and linking informations package_get_all_external_informations( AKANTU_EXTERNAL_INCLUDE_DIR AKANTU_EXTERNAL_LIBRARIES ) # set the proper includes to build most of the tests include_directories( ${AKANTU_INCLUDE_DIRS} ${AKANTU_EXTERNAL_LIB_INCLUDE_DIR} ) # Register the executable to compile add_executable(${test_name} ${_register_test_SOURCES} ${_register_test_UNPARSED_ARGUMENTS}) set_property(TARGET ${test_name} APPEND PROPERTY INCLUDE_DIRECTORIES ${AKANTU_LIBRARY_INCLUDE_DIRS} ${AKANTU_EXTERNAL_INCLUDE_DIR}) target_link_libraries(${test_name} akantu ${AKANTU_EXTERNAL_LIBRARIES}) # add the extra compilation options if(_register_test_COMPILE_OPTIONS) set_target_properties(${test_name} PROPERTIES COMPILE_DEFINITIONS "${_register_test_COMPILE_OPTIONS}") endif() set(_test_all_files) # add the different dependencies (meshes, local libraries, ...) foreach(_dep ${_register_test_DEPENDENCIES}) add_dependencies(${test_name} ${_dep}) get_target_property(_dep_in_ressources ${_dep} RESSOURCES) if(_dep_in_ressources) list(APPEND _test_all_files ${_dep_in_ressources}) endif() endforeach() # copy the needed files to the build folder if(_register_test_FILES_TO_COPY) foreach(_file ${_register_test_FILES_TO_COPY}) file(COPY ${_file} DESTINATION .) list(APPEND _test_all_files ${CMAKE_CURRENT_SOURCE_DIR}/${_file}) endforeach() endif() # create the needed folders in the build folder if(_register_test_DIRECTORIES_TO_CREATE) foreach(_dir ${_register_test_DIRECTORIES_TO_CREATE}) if(IS_ABSOLUTE ${dir}) file(MAKE_DIRECTORY ${_dir}) else() file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${_dir}) endif() endforeach() endif() # add the source files in the list of all files foreach(_file ${_register_test_SOURCES} ${_register_test_UNPARSED_ARGUMENTS} ${_register_test_EXTRA_FILES}) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_file}) list(APPEND _test_all_files ${CMAKE_CURRENT_SOURCE_DIR}/${_file}) else() message("The file \"${_file}\" registred by the test \"${test_name}\" does not exists") endif() endforeach() # register the test for ctest if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.sh) file(COPY ${test_name}.sh DESTINATION .) list(APPEND _test_all_files ${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.sh) add_test(${test_name}_run ${CMAKE_CURRENT_BINARY_DIR}/${test_name}.sh) elseif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.verified) list(APPEND _test_all_files ${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.verified) add_test(${test_name}_run ${AKANTU_DIFF_SCRIPT} ${test_name} ${CMAKE_CURRENT_SOURCE_DIR}/${test_name}.verified) else() add_test(${test_name}_run ${CMAKE_CURRENT_BINARY_DIR}/${test_name}) endif() # add the executable as a dependency of the run set_tests_properties(${test_name}_run PROPERTIES DEPENDS ${test_name}) # clean the list of all files for this test and add them in the total list set(_tmp ${AKANTU_TESTS_FILES}) foreach(_file ${_source_file}) get_filename_component(_full ${_file} ABSOLUTE) file(RELATIVE_PATH __file ${PROJECT_SOURCE_DIR} ${_full}) list(APPEND _tmp ${__file}) list(APPEND _pkg_tmp ${__file}) endforeach() set(AKANTU_TESTS_FILES ${_tmp} CACHE INTERNAL "") endif() endif() endfunction() \ No newline at end of file diff --git a/cmake/Modules/CMakePackagesSystem.cmake b/cmake/Modules/CMakePackagesSystem.cmake index 7e7dce30d..fb9148fda 100644 --- a/cmake/Modules/CMakePackagesSystem.cmake +++ b/cmake/Modules/CMakePackagesSystem.cmake @@ -1,1639 +1,1642 @@ #=============================================================================== # @file CMakePackagesSystem.cmake # # @author Nicolas Richart <nicolas.richart@epfl.ch> # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # # @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(<regular_package_folder> # [ EXTRA_PACKAGE_FOLDER <extra_package_folder> ] # [ SOURCE_FOLDER <source_folder>] # [ TEST_FOLDER <test_folder> ] # [ MANUAL_FOLDER <manual_folder> ] # ) # # This command will look for packages name like # <regular_package_folder>/<package>.cmake # OR <extra_package_folder>/<package>/package.cmake # # A package is a cmake script that should contain at list the declaration of a # package # # package_declare(<package real name> # [EXTERNAL] [META] [ADVANCED] [NOT_OPTIONAL] # [DESCRIPTION <description>] [DEFAULT <default_value>] # [DEPENDS <pkg> ...] # [BOOST_COMPONENTS <pkg> ...] # [EXTRA_PACKAGE_OPTIONS <opt> ...] # [COMPILE_FLAGS <flags>] # [SYSTEM <bool> [ <script_to_compile> ]]) # # It can also declare multiple informations: # source files: # package_declare_sources(<package real name> # <src1> <src2> ... <srcn>) # # a LaTeX documentation: # package_declare_documentation(<package real name> # <line1> <line2> ...<linen>) # # LaTeX documentation files # package_declare_documentation_files(<package real name> # <file1> <file2> ... <filen>) # # Different function can also be retrieved from the package system by using the # different accessors # package_get_name(<pkg> <retval>) # package_get_real_name(<pkg> <retval>) # # package_get_option_name(<pkg> <retval>) # # package_use_system(<pkg> <retval>) # # package_get_nature(<pkg> <retval>) # # package_get_description(<pkg> <retval>) # # package_get_filename(<pkg> <retval>) # # package_get_sources_folder(<pkg> <retval>) # package_get_tests_folder(<pkg> <retval>) # package_get_manual_folder(<pkg> <retval>) # # package_get_find_package_extra_options(<pkg> <retval>) # # package_get_compile_flags(<pkg> <retval>) # # package_get_include_dir(<pkg> <retval>) # package_set_include_dir(<pkg> <inc1> <inc2> ... <incn>) # # package_get_libraries(<pkg> <retval>) # package_set_libraries(<pkg> <lib1> <lib2> ... <libn>) # # package_add_extra_dependency(pkg <dep1> <dep2> ... <depn>) # package_rm_extra_dependency(<pkg> <dep>) # package_get_extra_dependencies(<pkg> <retval>) # # package_is_activated(<pkg> <retval>) # package_is_deactivated(<pkg> <retval>) # # package_get_dependencies(<pkg> <retval>) # package_add_dependencies(<pkg> <dep1> <dep2> ... <depn>) # # package_get_all_source_files(<srcs> <public_headers> <private_headers>) # package_get_all_include_directories(<inc_dirs>) # package_get_all_external_informations(<include_dir> <libraries>) # package_get_all_definitions(<definitions>) # package_get_all_extra_dependencies(<dependencies>) # package_get_all_test_folders(<test_dirs>) # package_get_all_documentation_files(<doc_files>) # package_get_all_activated_packages(<activated_list>) # package_get_all_packages(<packages_list>) # # # @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 <http://www.gnu.org/licenses/>. # #=============================================================================== 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() include(CMakeDebugMessages) cmake_register_debug_message_module(PackagesSystem) #=============================================================================== 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) # ============================================================================== # "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() # ------------------------------------------------------------------------------ # 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 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) set(_tmp_dep ${${_pkg_name}_EXTRA_DEPENDS}) list(APPEND _tmp_dep ${ARGN}) list(REMOVE_DUPLICATES _tmp_dep) set(${_pkg_name}_EXTRA_DEPENDENCY "${_tmp_dep}" CACHE INTERNAL "External dependencies") endfunction() function(package_rm_extra_dependency pkg DEP) package_get_name(${pkg} _pkg_name) if(${_pkg_name}_EXTRA_DEPENDENCY) set(_tmp_dep ${${_pkg_name}_EXTRA_DEPENDENCY}) list(REMOVE_ITEM _tmp_dep ${DEP}) set(${_pkg_name}_EXTRA_DEPENDENCY "${_tmp_dep}" CACHE INTERNAL "External dependencies" FORCE) endif() 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) # \n replaced by && and \\ by ££ to avoid cache problems set(_doc_str "") foreach(_str ${ARGN}) set(_doc_str "${_doc_str}&&${_str}") endforeach() string(REPLACE "\\" "££" _doc_escaped "${_doc_str}") package_get_name(${pkg} _pkg_name) set(${_pkg_name}_DOCUMENTATION "${_doc_escaped}" CACHE INTERNAL "Latex doc of package ${pkg}" FORCE) endfunction() function(package_declare_documentation_files pkg) package_get_name(${pkg} _pkg_name) set(${_pkg_name}_DOCUMENTATION_FILES "${ARGN}" CACHE INTERNAL "Latex doc files for package ${pkg}" FORCE) endfunction() # ============================================================================== # 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) 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 ) list(APPEND tmp_SRCS ${_tmp_SRCS}) list(APPEND tmp_PUBLIC_HEADERS ${tmp_PUBLIC_HEADERS}) list(APPEND tmp_PRIVATE_HEADERS ${tmp_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) endfunction() # ------------------------------------------------------------------------------ # Get include directories # ------------------------------------------------------------------------------ function(package_get_all_include_directories inc_dirs) string(TOUPPER ${PROJECT_NAME} _project) 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() list(REMOVE_DUPLICATES _tmp) set(${inc_dirs} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get external libraries informations # ------------------------------------------------------------------------------ function(package_get_all_external_informations INCLUDE_DIR LIBRARIES) string(TOUPPER ${PROJECT_NAME} _project) set(tmp_INCLUDE_DIR) set(tmp_LIBRARIES) package_get_all_activated_packages(_activated_list) foreach(_pkg_name ${_activated_list}) _package_get_nature(${_pkg_name} _nature) if(${_nature} MATCHES "external") _package_get_include_dir(${_pkg_name} _inc) _package_get_libraries (${_pkg_name} _libraries) list(APPEND tmp_INCLUDE_DIR ${_inc}) list(APPEND tmp_LIBRARIES ${_libraries}) endif() endforeach() set(${INCLUDE_DIR} ${tmp_INCLUDE_DIR} PARENT_SCOPE) set(${LIBRARIES} ${tmp_LIBRARIES} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get definitions like external projects # ------------------------------------------------------------------------------ function(package_get_all_definitions definitions) set(_tmp) string(TOUPPER ${PROJECT_NAME} _project) package_get_all_activated_packages(_activated_list) foreach(_pkg_name ${_activated_list}) _package_get_option_name(${_pkg_name} _option_name) list(APPEND _tmp ${_option_name}) endforeach() set(${definitions} ${_tmp} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get extra dependencies like external projects # ------------------------------------------------------------------------------ function(package_get_all_extra_dependencies DEPS) string(TOUPPER ${PROJECT_NAME} _project) set(_tmp_DEPS) package_get_all_activated_packages(_activated_list) foreach(_pkg_name ${_activated_list}) _package_get_extra_dependencies(${_pkg_name} _dep) list(APPEND _tmp_DEPS ${_dep}) endforeach() if(_tmp_DEPS) list(REMOVE_DUPLICATES _tmp_DEPS) endif() set(${DEPS} ${_tmp_DEPS} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Get extra infos # ------------------------------------------------------------------------------ function(package_get_all_test_folders TEST_DIRS) string(TOUPPER ${PROJECT_NAME} _project) set(_tmp_TEST_DIRS) package_get_all_activated_packages(_activated_list) foreach(_pkg_name ${_activated_list}) _package_get_tests_folder(${_pkg_name} _test_dir) list(APPEND _tmp_TEST_DIRS ${_test_dir}) endforeach() if(_tmp_TEST_DIRS) list(REMOVE_DUPLICATES _tmp_TEST_DIRS) endif() set(${TEST_DIRS} ${_tmp_TEST_DIRS} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Documentation informations # ------------------------------------------------------------------------------ function(package_get_all_documentation_files doc_files) string(TOUPPER ${PROJECT_NAME} _project) 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) string(TOUPPER ${PROJECT_NAME} _project) set(${activated_list} ${${_project}_ACTIVATED_PACKAGE_LIST} PARENT_SCOPE) endfunction() function(package_get_all_packages packages_list) string(TOUPPER ${PROJECT_NAME} _project) set(${packages_list} ${${_project}_ALL_PACKAGES_LIST} PARENT_SCOPE) endfunction() # ============================================================================== # User Functions # ============================================================================== # ------------------------------------------------------------------------------ # list all the packages in the PACKAGE_FOLDER # extra packages can be given with an EXTRA_PACKAGE_FOLDER # <package_folder>/<package>.cmake # # Extra packages folder structure # <extra_package_folder>/<package>/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 <package_folder> 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(<package real name> # [EXTERNAL] [META] [ADVANCED] [NOT_OPTIONAL] # [DESCRIPTION <description>] [DEFAULT <default_value>] # [DEPENDS <pkg> ...] # [BOOST_COMPONENTS <pkg> ...] # [EXTRA_PACKAGE_OPTIONS <opt> ...] # [COMPILE_FLAGS <flags>] # [SYSTEM <bool> [ <script_to_compile> ]]) # ------------------------------------------------------------------------------ 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 description if(_opt_pkg_DESCRIPTION) _package_set_description(${_pkg_name} ${_opt_pkg_DESCRIPTION}) else() _package_set_description(${_pkg_name} "") 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_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(<package> <list of sources> # SOURCES <source file> ... # PUBLIC_HEADER <header file> ... # PRIVATE_HEADER <header file> ...) # ------------------------------------------------------------------------------ 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() # ============================================================================== # "Private" Accessors # ============================================================================== # ------------------------------------------------------------------------------ # Real name # ------------------------------------------------------------------------------ function(_package_get_real_name pkg_name real_name) set(${real_name} ${${pkg_name}} PARENT_SCOPE) endfunction() function(_package_set_real_name pkg_name real_name) set(${pkg_name} ${real_name} CACHE INTERNAL "" FORCE) endfunction() # ------------------------------------------------------------------------------ # Option name # ------------------------------------------------------------------------------ function(_package_get_option_name pkg_name opt_name) string(TOUPPER "${PROJECT_NAME}" _project) _package_get_real_name(${pkg_name} _real_name) string(TOUPPER "${_real_name}" _u_package) _package_get_nature(${pkg_name} _nature) if(${_nature} MATCHES "internal" OR ${_nature} MATCHES "meta") set(${opt_name} ${_project}_${_u_package} PARENT_SCOPE) elseif(${_nature} MATCHES "external") set(${opt_name} ${_project}_USE_${_u_package} PARENT_SCOPE) else() set(${opt_name} UNKNOWN_NATURE_${_project}_${_u_package} PARENT_SCOPE) endif() endfunction() # ------------------------------------------------------------------------------ # Set if system package or compile external lib # ------------------------------------------------------------------------------ function(_package_set_system_option pkg_name default) string(TOUPPER "${PROJECT_NAME}" _project) _package_get_real_name(${pkg_name} _real_name) string(TOUPPER "${_real_name}" _u_package) option(${_project}_USE_SYSTEM_${_u_package} "Should akantu compile the third-party: \"${_real_name}\"" ${default}) mark_as_advanced(${_project}_USE_SYSTEM_${_u_package}) endfunction() function(_package_use_system pkg_name use) string(TOUPPER "${PROJECT_NAME}" _project) _package_get_real_name(${pkg_name} _real_name) string(TOUPPER "${_real_name}" _u_package) if(DEFINED ${_project}_USE_SYSTEM_${_u_package}) set(${use} ${${_project}_USE_SYSTEM_${_u_package}} PARENT_SCOPE) else() set(${use} TRUE PARENT_SCOPE) endif() endfunction() function(_package_set_system_script pkg_name script) set(${_pkg_name}_COMPILE_SCRIPT "${script}" CACHE INTERNAL "Script associated to package ${pkg_name}" FORCE) endfunction() function(_package_add_third_party_script_variable pkg var) set(${_pkg_name}_VARIABLE_${var} "${ARGN}" CACHE INTERNAL "Script associated to package ${pkg_name}" FORCE) set(${var} ${ARGN} PARENT_SCOPE) endfunction() function(_package_load_third_party_script pkg_name) if(${pkg_name}_COMPILE_SCRIPT) # set the stored variable get_cmake_property(_all_vars VARIABLES) foreach(_var ${_all_vars}) if(_var MATCHES "^${pkg_name}_VARIABLE_.*") string(REPLACE "${pkg_name}_VARIABLE_" "" _orig_var "${_var}") set(${_orig_var} ${${_var}}) endif() endforeach() _package_get_real_name(${pkg_name} _name) string(TOUPPER "${_name}" _u_name) _package_get_option_name(${pkg_name} _opt_name) if(${_opt_name}_VERSION) set(_version " (version ${${_opt_name}_VERSION})") elseif(${_u_name}_VERSION) set(_version " (version ${${_u_name}_VERSION})") endif() # load the script message(STATUS "${_name}: building as third-party${_version}") include(ExternalProject) include(${${pkg_name}_COMPILE_SCRIPT}) endif() endfunction() # ------------------------------------------------------------------------------ # Nature # ------------------------------------------------------------------------------ function(_package_set_nature pkg_name NATURE) set(${pkg_name}_NATURE ${NATURE} CACHE INTERNAL "" FORCE) endfunction() function(_package_get_nature pkg_name NATURE) if(${pkg_name}_NATURE) set(${NATURE} ${${pkg_name}_NATURE} PARENT_SCOPE) else() set(${NATURE} "unknown" PARENT_SCOPE) endif() endfunction() # ------------------------------------------------------------------------------ # Description # ------------------------------------------------------------------------------ function(_package_set_description pkg_name DESC) set(${pkg_name}_DESC ${DESC} CACHE INTERNAL "" FORCE) endfunction() function(_package_get_description pkg_name DESC) if(${pkg_name}_DESC) set(${DESC} ${${pkg_name}_DESC} PARENT_SCOPE) else() message("No description set for the package ${${pkg_name}} (${pkg_name})") endif() endfunction() # ------------------------------------------------------------------------------ # Package file name # ------------------------------------------------------------------------------ function(_package_set_filename pkg_name FILE) set(${pkg_name}_FILE ${FILE} CACHE INTERNAL "" FORCE) endfunction() function(_package_get_filename pkg_name FILE) if(${pkg_name}_FILE) set(${FILE} ${${pkg_name}_FILE} PARENT_SCOPE) else() message(ERROR "No filename set for the package ${${pkg_name}}") endif() endfunction() # ------------------------------------------------------------------------------ # Source folder # ------------------------------------------------------------------------------ function(_package_set_sources_folder pkg_name src_folder) set(${pkg_name}_SRCS_FOLDER "${src_folder}" CACHE INTERNAL "" FORCE) endfunction() function(_package_get_sources_folder pkg_name src_folder) set(${src_folder} ${${pkg_name}_SRCS_FOLDER} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Test folder # ------------------------------------------------------------------------------ function(_package_set_tests_folder pkg_name test_folder) set(${pkg_name}_TESTS_FOLDER "${test_folder}" CACHE INTERNAL "" FORCE) endfunction() function(_package_get_tests_folder pkg_name test_folder) set(${test_folder} ${${pkg_name}_TESTS_FOLDER} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Manual folder # ------------------------------------------------------------------------------ function(_package_set_manual_folder pkg_name manual_folder) set(${pkg_name}_MANUAL_FOLDER "${manual_folder}" CACHE INTERNAL "" FORCE) endfunction() function(_package_get_manual_folder pkg_name manual_folder) set(${manual_folder} ${${pkg_name}_MANUAL_FOLDER} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Extra option for the find_package # ------------------------------------------------------------------------------ function(_package_set_find_package_extra_options pkg_name) set(${pkg_name}_FIND_PKG_OPTIONS "${ARGN}" CACHE INTERNAL "Extra option for the fin_package function" FORCE) endfunction() function(_package_get_find_package_extra_options pkg_name options) set(${options} "${${pkg_name}_FIND_PKG_OPTIONS}" PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Compilation flags # ------------------------------------------------------------------------------ function(_package_set_compile_flags pkg_name) set(${pkg_name}_COMPILE_FLAGS ${ARGN} CACHE INTERNAL "Additional compile flags" FORCE) endfunction() function(_package_get_compile_flags pkg_name flags) set(${flags} "${${pkg_name}_COMPILE_FLAGS}" PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Include dir # ------------------------------------------------------------------------------ function(_package_set_include_dir pkg_name) _package_get_real_name(${pkg_name} _real_name) set(${pkg_name}_INCLUDE_DIR "${ARGN}" CACHE INTERNAL "Include folder for the package ${_real_name}" FORCE) endfunction() function(_package_get_include_dir pkg_name include_dir) set(${include_dir} ${${pkg_name}_INCLUDE_DIR} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Libraries # ------------------------------------------------------------------------------ function(_package_set_libraries pkg_name) _package_get_real_name(${pkg_name} _real_name) set(${pkg_name}_LIBRARIES "${ARGN}" CACHE INTERNAL "Libraries for the package ${_real_name}" FORCE) endfunction() function(_package_get_libraries pkg_name libraries) if(${pkg_name}_LIBRARIES) set(${libraries} ${${pkg_name}_LIBRARIES} PARENT_SCOPE) else() set(${libraries} "" PARENT_SCOPE) endif() endfunction() # ------------------------------------------------------------------------------ # Extra dependencies like custom commands of ExternalProject # ------------------------------------------------------------------------------ function(_package_get_extra_dependencies pkg deps) if(${_pkg_name}_EXTRA_DEPENDENCY) set(${deps} ${${_pkg_name}_EXTRA_DEPENDENCY} PARENT_SCOPE) else() set(${deps} PARENT_SCOPE) endif() endfunction() function(_package_unset_extra_dependencies pkg_name) unset(${pkg_name}_EXTRA_DEPENDENCY CACHE) endfunction() # ------------------------------------------------------------------------------ # Activate/deactivate # ------------------------------------------------------------------------------ function(_package_activate pkg_name) set(${pkg_name}_STATE ON CACHE INTERNAL "" FORCE) endfunction() function(_package_deactivate pkg_name) set(${pkg_name}_STATE OFF CACHE INTERNAL "" FORCE) endfunction() function(_package_is_activated pkg_name _act) if(DEFINED ${pkg_name}_STATE AND ${pkg_name}_STATE) set(${_act} TRUE PARENT_SCOPE) else() set(${_act} FALSE PARENT_SCOPE) endif() endfunction() function(_package_is_deactivated pkg_name _act) if(DEFINED ${pkg_name}_STATE AND NOT ${pkg_name}_STATE) set(${_act} TRUE PARENT_SCOPE) else() set(${_act} FALSE PARENT_SCOPE) endif() endfunction() function(_package_unset_activated pkg_name) unset(${pkg_name}_STATE CACHE) endfunction() # ------------------------------------------------------------------------------ # Direct dependencies # ------------------------------------------------------------------------------ function(_package_add_dependencies pkg_name) set(_tmp_deps ${${pkg_name}_DEPENDENCIES}) list(APPEND _tmp_deps ${ARGN}) list(REMOVE_DUPLICATES _tmp_deps) set(${pkg_name}_DEPENDENCIES "${_tmp_deps}" CACHE INTERNAL "List of dependencies for package ${_opt_name}" FORCE) endfunction() function(_package_get_dependencies pkg_name dependencies) set(${dependencies} "${${pkg_name}_DEPENDENCIES}" PARENT_SCOPE) endfunction() function(_package_unset_dependencies pkg_name) unset(${pkg_name}_DEPENDENCIES CACHE) endfunction() # ------------------------------------------------------------------------------ # Functions to handle reverse dependencies # ------------------------------------------------------------------------------ function(_package_set_rdependencies pkg_name) set(${pkg_name}_RDEPENDENCIES "${ARGN}" CACHE INTERNAL "Dependencies ON with package ${pkg_name}" FORCE) endfunction() function(_package_get_rdependencies pkg_name RDEPENDENCIES) set(${RDEPENDENCIES} "${${pkg_name}_RDEPENDENCIES}" PARENT_SCOPE) endfunction() function(_package_add_rdependency pkg_name rdep) # store the reverse dependency set(_rdeps ${${pkg_name}_RDEPENDENCIES}) list(APPEND _rdeps ${rdep}) list(REMOVE_DUPLICATES _rdeps) _package_set_rdependencies(${pkg_name} ${_rdeps}) endfunction() function(_package_remove_rdependency pkg_name rdep) set(_rdeps ${${pkg_name}_RDEPENDENCIES}) list(FIND _rdeps ${rdep} pos) if(NOT pos EQUAL -1) list(REMOVE_AT _rdeps ${pos}) _package_set_rdependencies(${pkg_name} ${_rdeps}) endif() endfunction() # ------------------------------------------------------------------------------ # Function to handle forcing dependencies (Package turn ON that enforce their # dependencies ON) # ------------------------------------------------------------------------------ function(_package_set_fdependencies pkg_name) set(${pkg_name}_FDEPENDENCIES "${ARGN}" CACHE INTERNAL "Dependencies ON with package ${pkg_name}" FORCE) endfunction() function(_package_get_fdependencies pkg_name fdependencies) set(${fdependencies} "${${pkg_name}_FDEPENDENCIES}" PARENT_SCOPE) endfunction() function(_package_add_fdependency pkg_name fdep) # store the enforcing dependency set(_fdeps ${${pkg_name}_FDEPENDENCIES}) list(APPEND _fdeps ${fdep}) list(REMOVE_DUPLICATES _fdeps) _package_set_fdependencies(${pkg_name} ${_fdeps}) endfunction() function(_package_remove_fdependency pkg_name fdep) set(_fdeps ${${pkg_name}_FDEPENDENCIES}) list(FIND _fdeps ${fdep} pos) if(NOT pos EQUAL -1) list(REMOVE_AT _fdeps ${pos}) _package_set_fdependencies(${pkg_name} ${_fdeps}) endif() endfunction() # ------------------------------------------------------------------------------ # Documentation related functions # ------------------------------------------------------------------------------ function(_package_get_documentation_files pkg_name doc_files) if(DEFINED ${pkg_name}_DOCUMENTATION_FILES) set(${doc_files} ${${pkg_name}_DOCUMENTATION_FILES} PARENT_SCOPE) else() set(${doc_files} "" PARENT_SCOPE) endif() endfunction() function(_package_get_documentation pkg_name _doc) # \n replaced by && and \\ by ££ to avoid cache problems if (DEFINED ${_pkg_name}_DOCUMENTATION) set(_doc_tmp ${${_pkg_name}_DOCUMENTATION}) string(REPLACE "££" "\\" _doc_escaped "${_doc_tmp}") string(REPLACE "&&" "\n" _doc_newlines "${_doc_escaped}") set(${_doc} "${_doc_newlines}" PARENT_SCOPE) else() set(${_doc} "" PARENT_SCOPE) endif() endfunction() # ------------------------------------------------------------------------------ # Special boost thingy # ------------------------------------------------------------------------------ function(_package_set_boost_component_needed pkg_name) set(_tmp ${${pkg_name}_BOOST_COMPONENTS_NEEDED}) list(APPEND _tmp ${ARGN}) list(REMOVE_DUPLICATES _tmp) set(${pkg_name}_BOOST_NEEDED_COMPONENTS ${_tmp} CACHE INTERNAL "List of Boost component needed by package ${${pkg_name}}" FORCE) package_get_name(Boost _boost_pkg_name) _package_add_dependencies(${pkg_name} ${_boost_pkg_name}) endfunction() function(_package_get_boost_component_needed pkg_name needed) if(${pkg_name}_BOOST_NEEDED_COMPONENTS) set(${needed} ${${pkg_name}_BOOST_NEEDED_COMPONENTS} PARENT_SCOPE) else() set(${needed} PARENT_SCOPE) endif() endfunction() function(_package_load_boost_components) string(TOUPPER ${PROJECT_NAME} _project) package_get_name(Boost _pkg_name) set(_boost_needed_components) package_get_all_activated_packages(_activated_list) foreach(_pkg_name ${_activated_list}) _package_get_boost_component_needed(${_pkg_name} _boost_comp) list(APPEND _boost_needed_components ${_boost_comp}) endforeach() if(_boost_needed_components) message(STATUS "Looking for Boost liraries: ${_boost_needed_components}") foreach(_comp ${_boost_needed_components}) find_package(Boost COMPONENTS ${_comp} QUIET) string(TOUPPER ${_comp} _u_comp) if(Boost_${_u_comp}_FOUND) message(STATUS " ${_comp}: FOUND") set(${_project}_BOOST_${_u_comp} TRUE CACHE INTERNAL "" FORCE) # Generate the libraries for the package _package_set_libraries(${_pkg_name} ${Boost_${_u_comp}_LIBRARY}) else() message(STATUS " ${_comp}: NOT FOUND") endif() endforeach() endif() endfunction() # ------------------------------------------------------------------------------ # get the list of source files for a given package # ------------------------------------------------------------------------------ function(_package_get_source_files pkg_name SRCS PUBLIC_HEADERS PRIVATE_HEADERS) string(TOUPPER ${PROJECT_NAME} _project) set(tmp_SRCS) set(tmp_PUBLIC_HEADERS) set(tmp_PRIVATE_HEADERS) foreach(_type SRCS PUBLIC_HEADERS PRIVATE_HEADERS) foreach(_file ${${pkg_name}_${_type}}) string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" _rel_file "${_file}") list(APPEND tmp_${_type} "${_rel_file}") endforeach() endforeach() set(${SRCS} ${tmp_SRCS} PARENT_SCOPE) set(${PUBLIC_HEADERS} ${tmp_PUBLIC_HEADERS} PARENT_SCOPE) set(${PRIVATE_HEADERS} ${tmp_PRIVATE_HEADERS} PARENT_SCOPE) endfunction() # ============================================================================== # Internal functions # ============================================================================== # ------------------------------------------------------------------------------ # Build the reverse dependencies from the dependencies # ------------------------------------------------------------------------------ function(_package_build_rdependencies) string(TOUPPER ${PROJECT_NAME} _project) # set empty lists foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST}) set(${_pkg_name}_rdeps) endforeach() # fill the dependencies list foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST}) _package_get_dependencies(${_pkg_name} _deps) foreach(_dep_name ${_deps}) list(APPEND ${_dep_name}_rdeps ${_pkg_name}) endforeach() endforeach() # clean and set the reverse dependencies foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST}) if(${_pkg_name}_rdeps) list(REMOVE_DUPLICATES ${_pkg_name}_rdeps) _package_set_rdependencies(${_pkg_name} ${${_pkg_name}_rdeps}) endif() endforeach() endfunction() # ------------------------------------------------------------------------------ # This function resolve the dependance order run the needed find_packages # ------------------------------------------------------------------------------ function(_package_load_packages) string(TOUPPER ${PROJECT_NAME} _project) # Activate the dependencies of activated package and generate an ordered list # of dependencies set(ordered_loading_list) foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST}) _package_load_dependencies_package(${_pkg_name} ordered_loading_list) endforeach() # Load the packages in the propoer order foreach(_pkg_name ${ordered_loading_list}) _package_get_option_name(${_pkg_name} _option_name) if(${_option_name}) _package_load_package(${_pkg_name}) else() # deactivate the packages than can already be deactivated _package_deactivate(${_pkg_name}) endif() endforeach() # generates the activated and unactivated lists of packages set(_packages_activated) set(_packages_deactivated) foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST}) _package_is_activated(${_pkg_name} _act) if(_act) list(APPEND _packages_activated ${_pkg_name}) else() list(APPEND _packages_deactivated ${_pkg_name}) endif() endforeach() # generate the list usable by the calling code set(${_project}_ACTIVATED_PACKAGE_LIST "${_packages_activated}" CACHE INTERNAL "List of activated packages" FORCE) set(${_project}_DEACTIVATED_PACKAGE_LIST "${_packages_deactivated}" CACHE INTERNAL "List of deactivated packages" FORCE) endfunction() # ------------------------------------------------------------------------------ # This load an external package and recursively all its dependencies # ------------------------------------------------------------------------------ function(_package_load_dependencies_package pkg_name loading_list) # Get packages informations _package_get_option_name(${pkg_name} _pkg_option_name) _package_get_dependencies(${pkg_name} _dependencies) # handle the dependencies foreach(_dep_name ${_dependencies}) _package_get_description(${_dep_name} _dep_desc) _package_get_option_name(${_dep_name} _dep_option_name) _package_get_fdependencies(${_dep_name} _fdeps) if(${_pkg_option_name}) if("${_fdeps}" STREQUAL "") set(${_dep_name}_OLD ${${_dep_option_name}} CACHE INTERNAL "" FORCE) endif() # set the option to on set(${_dep_option_name} ON CACHE BOOL "${_dep_desc}" FORCE) # store the reverse dependency _package_add_fdependency(${_dep_name} ${pkg_name}) else() # check if this is the last reverse dependency list(LENGTH _fdeps len) list(FIND _fdeps ${pkg_name} pos) if((len EQUAL 1) AND (NOT pos EQUAL -1)) set(${_dep_option_name} ${${_dep_name}_OLD} CACHE BOOL "${_dep_desc}" FORCE) unset(${_dep_name}_OLD CACHE) endif() # remove the pkg_name form the reverse dependency _package_remove_fdependency(${_dep_name} ${pkg_name}) endif() # recusively load the dependencies _package_load_dependencies_package(${_dep_name} ${loading_list}) endforeach() # get the compile flags _package_get_compile_flags(${pkg_name} _pkg_comile_flags) # if package option is on add it in the list if(${_pkg_option_name}) list(FIND ${loading_list} ${pkg_name} _pos) if(_pos EQUAL -1) set(_tmp_loading_list ${${loading_list}}) list(APPEND _tmp_loading_list ${pkg_name}) set(${loading_list} "${_tmp_loading_list}" PARENT_SCOPE) endif() #add the comilation flags if needed if(_pkg_comile_flags) add_flags(cxx ${_pkg_comile_flags}) endif() else() #remove the comilation flags if needed if(_pkg_comile_flags) remove_flags(cxx ${_pkg_comile_flags}) endif() endif() endfunction() # ------------------------------------------------------------------------------ # Load the package if it is an external one # ------------------------------------------------------------------------------ function(_package_load_package pkg_name) # load the package if it is an external _package_get_nature(${pkg_name} _nature) if(${_nature} MATCHES "external") _package_use_system(${pkg_name} _use_system) set(_activated TRUE) if(_use_system) _package_load_external_package(${pkg_name} _activated) else() _package_load_third_party_script(${pkg_name}) endif() if(_activated) _package_activate(${pkg_name}) elseif() _package_deactivate(${pkg_name}) endif() else(${_nature}) _package_activate(${pkg_name}) endif() endfunction() # ------------------------------------------------------------------------------ # Load external packages # ------------------------------------------------------------------------------ function(_package_load_external_package pkg_name activate) string(TOUPPER ${PROJECT_NAME} _project) _package_get_find_package_extra_options(${pkg_name} _options) if(_options) cmake_parse_arguments(_opt_pkg "" "LANGUAGE" "PREFIX;FOUND;ARGS" ${_options}) if(_opt_pkg_UNPARSED_ARGUMENTS) message("You passed too many options for the find_package related to ${${pkg_name}} \"${_opt_pkg_UNPARSED_ARGUMENTS}\"") endif() endif() if(_opt_pkg_LANGUAGE) foreach(_language ${_opt_pkg_LANGUAGE}) enable_language(${_language}) endforeach() endif() _package_get_real_name(${pkg_name} _real_name) # find the package find_package(${_real_name} REQUIRED ${_opt_pkg_ARGS}) # check if the package is found if(_opt_pkg_PREFIX) set(_package_prefix ${_opt_pkg_PREFIX}) else() string(TOUPPER ${${pkg_name}} _u_package) set(_package_prefix ${_u_package}) endif() set(_act FALSE) set(_prefix_to_consider) if(_opt_pkg_FOUND) set(_act TRUE) set(_prefix_to_consider ${_package_prefix}) else() foreach(_prefix ${_package_prefix}) if(${_prefix}_FOUND) set(_act TRUE) list(APPEND _prefix_to_consider ${_prefix}) endif() endforeach() endif() if(_act) foreach(_prefix ${_prefix_to_consider}) # Generate the include dir for the package if(DEFINED ${_prefix}_INCLUDE_DIRS) _package_set_include_dir(${_pkg_name} ${${_prefix}_INCLUDE_DIRS}) elseif(DEFINED ${_prefix}_INCLUDE_DIR) _package_set_include_dir(${_pkg_name} ${${_prefix}_INCLUDE_DIR}) elseif(DEFINED ${_prefix}_INCLUDE_PATH) _package_set_include_dir(${_pkg_name} ${${_prefix}_INCLUDE_PATH}) endif() # Generate the libraries for the package if(DEFINED ${_prefix}_LIBRARIES) _package_set_libraries(${_pkg_name} ${${_prefix}_LIBRARIES}) elseif(DEFINED ${_prefix}_LIBRARY) _package_set_libraries(${_pkg_name} ${${_prefix}_LIBRARY}) endif() endforeach() endif() set(${activate} ${_act} PARENT_SCOPE) endfunction() # ------------------------------------------------------------------------------ # Sanity check functions # ------------------------------------------------------------------------------ function(_package_check_files_exists) string(TOUPPER ${PROJECT_NAME} _project) set(_message FALSE) foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST}) set(_pkg_files ${${_pkg_name}_SRCS} ${${_pkg_name}_PUBLIC_HEADERS} ${${_pkg_name}_PRIVATE_HEADERS} ) _package_get_real_name(${_pkg_name} _real_name) foreach(_file ${_pkg_files}) if(NOT EXISTS "${_file}") if(NOT _message) set(_message TRUE) message("This file(s) is(are) present in a package but are not present on disk.") endif() message(" PACKAGE ${_real_name} FILE ${_file}") endif() endforeach() endforeach() if(_message) message(SEND_ERROR "Please check the content of your packages to correct this warnings") endif() endfunction() # ------------------------------------------------------------------------------ function(_package_check_files_registered) set(_pkg_files) # generates a file list of registered files foreach(_pkg_name ${${_project}_ALL_PACKAGES_LIST}) list(APPEND _pkg_files ${${_pkg_name}_SRCS} ${${_pkg_name}_PUBLIC_HEADERS} ${${_pkg_name}_PRIVATE_HEADERS} ) endforeach() # generates the list of files in the source folders set(_all_src_files) foreach(_src_folder ${ARGN}) foreach(_ext "cc" "hh" "c" "h" "hpp") file(GLOB_RECURSE _src_files "${_src_folder}/*.${_ext}") list(APPEND _all_src_files ${_src_files}) endforeach() endforeach() if(_all_src_files) list(REMOVE_DUPLICATES _all_src_files) endif() set(_not_registerd_files) # check only sources files ine the source folders foreach(_src_folder ${ARGN}) foreach(_file ${_all_src_files}) if("${_file}" MATCHES "${_src_folder}") list(FIND _pkg_files "${_file}" _index) if (_index EQUAL -1) list(APPEND _not_registerd_files ${_file}) endif() endif() endforeach() endforeach() if(AUTO_MOVE_UNKNOWN_FILES) file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/unknown_files) endif() # warn the user and move the files if needed if(_not_registerd_files) if(EXISTS ${PROJECT_BINARY_DIR}/missing_files_in_packages) file(REMOVE ${PROJECT_BINARY_DIR}/missing_files_in_packages) endif() message("This files are present in the source folders but are not registered in any package") foreach(_file ${_not_registerd_files}) message(" ${_file}") if(AUTO_MOVE_UNKNOWN_FILES) get_filename_component(_file_name ${_file} NAME) file(RENAME ${_file} ${PROJECT_BINARY_DIR}/unknown_files/${_file_name}) endif() file(APPEND ${PROJECT_BINARY_DIR}/missing_files_in_packages "${_file} ") endforeach() if(AUTO_MOVE_UNKNOWN_FILES) message(SEND_ERROR "The files where moved in the followinf folder ${PROJECT_BINARY_DIR}/unknown_files\n Please register them in the good package or clean the sources") else() message(SEND_ERROR "Please register them in the good package or clean the sources") endif() endif() endfunction() diff --git a/extra_packages/students-extra-package b/extra_packages/students-extra-package index d1c4780c2..05c0a753f 160000 --- a/extra_packages/students-extra-package +++ b/extra_packages/students-extra-package @@ -1 +1 @@ -Subproject commit d1c4780c20ef5e5f6aaa49f8242770d03f817911 +Subproject commit 05c0a753ff1d0ba7650bc6671894bae570d0f593 diff --git a/packages/embedded.cmake b/packages/embedded.cmake index a25bcb541..df0eeb3ae 100644 --- a/packages/embedded.cmake +++ b/packages/embedded.cmake @@ -1,55 +1,55 @@ #=============================================================================== # @file embedded.cmake # # @author Lucas Frérot <lucas.frerot@epfl.ch> # # @date creation: Tue Oct 16 2012 # @date last modification: Thu Jun 12 2014 # # @brief package descrition for embedded model use # # @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 <http://www.gnu.org/licenses/>. # #=============================================================================== package_declare(embedded DESCRIPTION "Add support for the embedded solid mechanics model" DEPENDS CGAL) package_declare_sources(embedded model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh model/solid_mechanics/embedded_interface_intersector.hh model/solid_mechanics/embedded_interface_intersector.cc model/solid_mechanics/embedded_interface_model.hh model/solid_mechanics/embedded_interface_model.cc model/solid_mechanics/materials/material_embedded/embedded_internal_field.hh model/solid_mechanics/materials/material_embedded/material_reinforcement.hh model/solid_mechanics/materials/material_embedded/material_reinforcement.cc model/solid_mechanics/materials/material_embedded/material_reinforcement_inline_impl.cc model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh - model/solid_mechanics/materials/material_embedded/material_reinforcement_template_inline_impl.cc + model/solid_mechanics/materials/material_embedded/material_reinforcement_template_tmpl.hh ) package_declare_documentation(embedded "This package allows the use of the embedded model in solid mechanics. This package depends on the CGAL package." ) diff --git a/src/common/aka_types.hh b/src/common/aka_types.hh index dd98e4a82..0bc0ed8e9 100644 --- a/src/common/aka_types.hh +++ b/src/common/aka_types.hh @@ -1,1073 +1,1076 @@ /** * @file aka_types.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Feb 17 2011 * @date last modification: Tue Aug 19 2014 * * @brief description of the "simple" types * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_error.hh" #include "aka_fwd.hh" #include "aka_math.hh" #include "aka_array.hh" /* -------------------------------------------------------------------------- */ #include <iomanip> #ifndef __INTEL_COMPILER #include <tr1/unordered_map> #else #include <map> #endif /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_TYPES_HH__ #define __AKANTU_AKA_TYPES_HH__ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* maps */ /* -------------------------------------------------------------------------- */ #ifndef __INTEL_COMPILER template<class Key, class Ty> struct unordered_map { typedef typename std::tr1::unordered_map<Key, Ty> type; }; #else template<class Key, class Ty> struct unordered_map { typedef typename std::map<Key, Ty> type; }; #endif enum NormType { L_1 = 1, L_2 = 2, L_inf = UInt(-1) }; /** * DimHelper is a class to generalize the setup of a dim array from 3 * values. This gives a common interface in the TensorStorage class * independently of its derived inheritance (Vector, Matrix, Tensor3) */ template<UInt dim> struct DimHelper { static inline void setDims(UInt m, UInt n, UInt p, UInt dims[dim]); }; /* -------------------------------------------------------------------------- */ template<> struct DimHelper<1> { static inline void setDims(UInt m, __attribute__((unused)) UInt n, __attribute__((unused)) UInt p, UInt dims[1]) { dims[0] = m; } }; /* -------------------------------------------------------------------------- */ template<> struct DimHelper<2> { static inline void setDims(UInt m, UInt n, __attribute__((unused)) UInt p, UInt dims[2]) { dims[0] = m; dims[1] = n; } }; /* -------------------------------------------------------------------------- */ template<> struct DimHelper<3> { static inline void setDims(UInt m, UInt n, UInt p, UInt dims[3]) { dims[0] = m; dims[1] = n; dims[2] = p; } }; /* -------------------------------------------------------------------------- */ template<typename T, UInt ndim, class RetType> class TensorStorage; /* -------------------------------------------------------------------------- */ /* Proxy classes */ /* -------------------------------------------------------------------------- */ /** * The TensorProxy class is a proxy class to the TensorStorage it handles the * wrapped case. That is to say if an accessor should give access to a Tensor * wrapped on some data, like the Array<T>::iterator they can return a * TensorProxy that will be automatically transformed as a TensorStorage wrapped * on the same data */ template<typename T, UInt ndim, class RetType> class TensorProxy { protected: TensorProxy(T * data, UInt m, UInt n, UInt p) { DimHelper<ndim>::setDims(m, n, p, this->n); this->values = data; } TensorProxy(const TensorProxy & other) { this->values = other.storage(); for (UInt i = 0; i < ndim; ++i) this->n[i] = other.n[i]; } inline TensorProxy(const TensorStorage<T, ndim, RetType> & other); public: UInt size(UInt i) const { AKANTU_DEBUG_ASSERT(i < ndim, "This tensor has only " << ndim << " dimensions, not " << (i + 1)); return n[i]; } inline UInt size() const{ UInt _size = 1; for (UInt d = 0; d < ndim; ++d) _size *= this->n[d]; return _size; } T * storage() const { return values; } inline TensorProxy & operator=(const RetType & src) { AKANTU_DEBUG_ASSERT(src.size() == this->size(), "You are trying to copy two tensors with different sizes"); memcpy(this->values, src.storage(), this->size() * sizeof(T)); return *this; } inline TensorProxy & operator=(const TensorProxy & src) { AKANTU_DEBUG_ASSERT(src.size() == this->size(), "You are trying to copy two tensors with different sizes"); memcpy(this->values, src.storage(), this->size() * sizeof(T)); return *this; } protected: T * values; UInt n[ndim]; }; /* -------------------------------------------------------------------------- */ template<typename T> class VectorProxy : public TensorProxy<T, 1, Vector<T> > { typedef TensorProxy<T, 1, Vector<T> > parent; typedef Vector<T> type; public: VectorProxy(T * data, UInt n) : parent(data, n, 0, 0) { } VectorProxy(const VectorProxy & src) : parent(src) { } VectorProxy(const Vector<T> & src) : parent(src) { } VectorProxy & operator=(const type & src) { parent::operator=(src); return *this; } VectorProxy & operator=(const VectorProxy & src) { parent::operator=(src); return *this; } + + T & operator()(UInt index){return this->values[index];}; + const T & operator()(UInt index) const {return this->values[index];}; }; template<typename T> class MatrixProxy : public TensorProxy<T, 2, Matrix<T> > { typedef TensorProxy<T, 2, Matrix<T> > parent; typedef Matrix<T> type; public: MatrixProxy(T * data, UInt m, UInt n) : parent(data, m, n, 0) { } MatrixProxy(const MatrixProxy & src) : parent(src) { } MatrixProxy(const type & src) : parent(src) { } MatrixProxy & operator=(const type & src) { parent::operator=(src); return *this; } MatrixProxy & operator=(const MatrixProxy & src) { parent::operator=(src); return *this; } }; template<typename T> class Tensor3Proxy : public TensorProxy<T, 3, Tensor3<T> > { typedef TensorProxy<T, 3, Tensor3<T> > parent; typedef Tensor3<T> type; public: Tensor3Proxy(T * data, UInt m, UInt n, UInt k) : parent(data, m, n, k) { } Tensor3Proxy(const Tensor3Proxy & src) : parent(src) { } Tensor3Proxy(const Tensor3<T> & src) : parent(src) { } Tensor3Proxy & operator=(const type & src) { parent::operator=(src); return *this; } Tensor3Proxy & operator=(const Tensor3Proxy & src) { parent::operator=(src); return *this; } }; /* -------------------------------------------------------------------------- */ /* Tensor base class */ /* -------------------------------------------------------------------------- */ template<typename T, UInt ndim, class RetType> class TensorStorage { public: typedef T value_type; protected: template<class TensorType> void copySize(const TensorType & src) { for (UInt d = 0; d < ndim; ++d) this->n[d] = src.size(d); this->_size = src.size(); } TensorStorage() : values(NULL), wrapped(false) { for (UInt d = 0; d < ndim; ++d) this->n[d] = 0; _size = 0; } TensorStorage(const TensorProxy<T, ndim, RetType> & proxy) { this->copySize(proxy); this->values = proxy.storage(); this->wrapped = true; } protected: TensorStorage(const TensorStorage & src) { } public: TensorStorage(const TensorStorage & src, bool deep_copy) : values(NULL), wrapped(false) { if(deep_copy) this->deepCopy(src); else this->shallowCopy(src); } protected: TensorStorage(UInt m, UInt n, UInt p, const T & def) { DimHelper<ndim>::setDims(m, n, p, this->n); this->computeSize(); this->values = new T[this->_size]; this->set(def); this->wrapped = false; } TensorStorage(T * data, UInt m, UInt n, UInt p) { DimHelper<ndim>::setDims(m, n, p, this->n); this->computeSize(); this->values = data; this->wrapped = true; } public: /* ------------------------------------------------------------------------ */ template<class TensorType> inline void shallowCopy(const TensorType & src) { this->copySize(src); if(!this->wrapped) delete[] this->values; this->values = src.storage(); this->wrapped = true; } /* ------------------------------------------------------------------------ */ template<class TensorType> inline void deepCopy(const TensorType & src) { this->copySize(src); if(!this->wrapped) delete [] this->values; this->values = new T[this->_size]; memcpy(this->values, src.storage(), this->_size * sizeof(T)); this->wrapped = false; } virtual ~TensorStorage() { if(!this->wrapped) delete [] this->values; } /* ------------------------------------------------------------------------ */ inline TensorStorage & operator=(const RetType & src) { if(this != &src) { if (this->wrapped) { // this test is not sufficient for Tensor of order higher than 1 AKANTU_DEBUG_ASSERT(this->_size == src.size(), "Tensors of different size"); memcpy(this->values, src.storage(), this->_size * sizeof(T)); } else { deepCopy(src); } } return *this; } /* ------------------------------------------------------------------------ */ template<class R> inline RetType & operator+=(const TensorStorage<T, ndim, R> & other) { T * a = this->storage(); T * b = other.storage(); AKANTU_DEBUG_ASSERT(_size == other.size(), "The two tensors do not have the same size, they cannot be subtracted"); for (UInt i = 0; i < _size; ++i) *(a++) += *(b++); return *(static_cast<RetType *>(this)); } /* ------------------------------------------------------------------------ */ template<class R> inline RetType & operator-=(const TensorStorage<T, ndim, R> & other) { T * a = this->storage(); T * b = other.storage(); AKANTU_DEBUG_ASSERT(_size == other.size(), "The two tensors do not have the same size, they cannot be subtracted"); for (UInt i = 0; i < _size; ++i) *(a++) -= *(b++); return *(static_cast<RetType *>(this)); } /* ------------------------------------------------------------------------ */ inline RetType & operator+=(const T & x) { T * a = this->values; for (UInt i = 0; i < _size; ++i) *(a++) += x; return *(static_cast<RetType *>(this)); } /* ------------------------------------------------------------------------ */ inline RetType & operator-=(const T & x) { T * a = this->values; for (UInt i = 0; i < _size; ++i) *(a++) -= x; return *(static_cast<RetType *>(this)); } /* ------------------------------------------------------------------------ */ inline RetType & operator*=(const T & x) { T * a = this->storage(); for (UInt i = 0; i < _size; ++i) *(a++) *= x; return *(static_cast<RetType *>(this)); } /* ---------------------------------------------------------------------- */ inline RetType & operator/=(const T & x) { T * a = this->values; for (UInt i = 0; i < _size; ++i) *(a++) /= x; return *(static_cast<RetType *>(this)); } /* ------------------------------------------------------------------------ */ T * storage() const { return values; } UInt size() const { return _size; } UInt size(UInt i) const { AKANTU_DEBUG_ASSERT(i < ndim, "This tensor has only " << ndim << " dimensions, not " << (i + 1)); return n[i]; }; /* ------------------------------------------------------------------------ */ inline void clear() { memset(values, 0, _size * sizeof(T)); }; inline void set(const T & t) { std::fill_n(values, _size, t); }; template<class TensorType> inline void copy(const TensorType & other) { AKANTU_DEBUG_ASSERT(_size == other.size(), "The two tensors do not have the same size, they cannot be copied"); memcpy(values, other.storage(), _size * sizeof(T)); } bool isWrapped() const { return this->wrapped; } protected: friend class Array<T>; inline void computeSize() { _size = 1; for (UInt d = 0; d < ndim; ++d) _size *= this->n[d]; } protected: template<typename R, NormType norm_type> struct NormHelper { template<class Ten> static R norm(const Ten & ten) { R _norm = 0.; R * it = ten.storage(); R * end = ten.storage() + ten.size(); for (; it < end; ++it) _norm += std::pow(std::abs(*it), norm_type); return std::pow(_norm, 1./norm_type); } }; template<typename R> struct NormHelper<R, L_1> { template<class Ten> static R norm(const Ten & ten) { R _norm = 0.; R * it = ten.storage(); R * end = ten.storage() + ten.size(); for (; it < end; ++it) _norm += std::abs(*it); return _norm; } }; template<typename R> struct NormHelper<R, L_2> { template<class Ten> static R norm(const Ten & ten) { R _norm = 0.; R * it = ten.storage(); R * end = ten.storage() + ten.size(); for (; it < end; ++it) _norm += *it * *it; return sqrt(_norm); } }; template<typename R> struct NormHelper<R, L_inf> { template<class Ten> static R norm(const Ten & ten) { R _norm = 0.; R * it = ten.storage(); R * end = ten.storage() + ten.size(); for (; it < end; ++it) _norm = std::max(std::abs(*it), _norm); return _norm; } }; public: /*----------------------------------------------------------------------- */ /// "Entrywise" norm norm<L_p> @f[ \|\boldsymbol{T}\|_p = \left( /// \sum_i^{n[0]}\sum_j^{n[1]}\sum_k^{n[2]} |T_{ijk}|^p \right)^{\frac{1}{p}} /// @f] template<NormType norm_type> inline T norm() const { return NormHelper<T, norm_type>::norm(*this); } protected: UInt n[ndim]; UInt _size; T * values; bool wrapped; }; template<typename T, UInt ndim, class RetType> inline TensorProxy<T, ndim, RetType>::TensorProxy(const TensorStorage<T, ndim, RetType> & other) { this->values = other.storage(); for (UInt i = 0; i < ndim; ++i) this->n[i] = other.size(i); } /* -------------------------------------------------------------------------- */ /* Vector */ /* -------------------------------------------------------------------------- */ template<typename T> class Vector : public TensorStorage< T, 1, Vector<T> > { typedef TensorStorage< T, 1, Vector<T> > parent; public: typedef typename parent::value_type value_type; typedef VectorProxy<T> proxy; public: Vector() : parent() {} Vector(UInt n, const T & def = T()) : parent(n, 0, 0, def) { } Vector(T * data, UInt n) : parent(data, n, 0, 0) { } Vector(const Vector & src, bool deep_copy = true) : parent(src, deep_copy) { } Vector(const VectorProxy<T> & src) : parent(src) { } public: virtual ~Vector() { }; /* ------------------------------------------------------------------------ */ inline Vector & operator=(const Vector & src) { parent::operator=(src); return *this; } /* ------------------------------------------------------------------------ */ inline T& operator()(UInt i) { return *(this->values + i); }; inline const T& operator()(UInt i) const { return *(this->values + i); }; inline T& operator[](UInt i) { return *(this->values + i); }; inline const T& operator[](UInt i) const { return *(this->values + i); }; /* ------------------------------------------------------------------------ */ inline Vector<T> & operator*=(Real x) { return parent::operator*=(x); } inline Vector<T> & operator/=(Real x) { return parent::operator/=(x); } /* ------------------------------------------------------------------------ */ inline Vector<T> & operator*=(const Vector<T> & vect) { T * a = this->storage(); T * b = vect.storage(); for (UInt i = 0; i < this->_size; ++i) *(a++) *= *(b++); return *this; } /* ------------------------------------------------------------------------ */ inline Real dot(const Vector<T> & vect) const { return Math::vectorDot(this->values, vect.storage(), this->_size); } /* ------------------------------------------------------------------------ */ inline Real mean() const { Real mean = 0; T * a = this->storage(); for (UInt i = 0; i < this->_size; ++i) mean += *(a++); return mean / this->_size; } /* ------------------------------------------------------------------------ */ inline Vector & crossProduct(const Vector<T> & v1, const Vector<T> & v2) { AKANTU_DEBUG_ASSERT(this->size() == 3, "crossProduct is only defined in 3D (n=" << this->size() << ")"); AKANTU_DEBUG_ASSERT(this->size() == v1.size() && this->size() == v2.size(), "crossProduct is not a valid operation non matching size vectors"); Math::vectorProduct3(v1.storage(), v2.storage(), this->values); return *this; } /* ------------------------------------------------------------------------ */ inline void solve(Matrix<T> & A, const Vector<T> & b) { AKANTU_DEBUG_ASSERT(this->size() == A.rows() && this->_size = A.cols(), "The size of the solution vector mismatches the size of the matrix"); AKANTU_DEBUG_ASSERT(this->_size == b._size, "The rhs vector has a mismatch in size with the matrix"); Math::solve(this->_size, A.storage(), this->values, b.storage()); } /* ------------------------------------------------------------------------ */ template<bool tr_A> inline void mul(const Matrix<T> & A, const Vector<T> & x, Real alpha = 1.0); /* ------------------------------------------------------------------------ */ inline Real norm() const { return parent::template norm<L_2>(); } template<NormType nt> inline Real norm() const { return parent::template norm<nt>(); } /* ------------------------------------------------------------------------ */ inline void normalize() { Real n = norm(); operator/=(n); } /* ------------------------------------------------------------------------ */ /// norm of (*this - x) inline Real distance(const Vector<T> & y) const { Real * vx = this->values; Real * vy = y.storage(); Real sum_2 = 0; for (UInt i = 0; i < this->_size; ++i, ++vx, ++vy) sum_2 += (*vx - *vy)*(*vx - *vy); return sqrt(sum_2); } /* ------------------------------------------------------------------------ */ inline bool equal(const Vector<T> & v, Real tolerance = Math::getTolerance()) const { T * a = this->storage(); T * b = v.storage(); UInt i = 0; while (i < this->_size && (std::abs(*(a++) - *(b++)) < tolerance)) ++i; return i == this->_size; } /* ------------------------------------------------------------------------ */ inline short compare(const Vector<T> & v, Real tolerance = Math::getTolerance()) const { T * a = this->storage(); T * b = v.storage(); for (UInt i(0); i < this->_size; ++i, ++a, ++b) { if(std::abs(*a - *b) > tolerance) return (((*a - *b) > tolerance) ? 1 : -1); } return 0; } /* ------------------------------------------------------------------------ */ inline bool operator==(const Vector<T> & v) const { return equal(v); } inline bool operator<(const Vector<T> & v) const { return compare(v) == -1; } inline bool operator>(const Vector<T> & v) const { return compare(v) == 1; } /* ------------------------------------------------------------------------ */ /// 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 << "["; for (UInt i = 0; i < this->_size; ++i) { if(i != 0) stream << ", "; stream << this->values[i]; } stream << "]"; } friend class ::akantu::Array<T>; }; typedef Vector<Real> RVector; /* ------------------------------------------------------------------------ */ template<> inline bool Vector<UInt>::equal(const Vector<UInt> & v, __attribute__((unused)) Real tolerance) const { UInt * a = this->storage(); UInt * b = v.storage(); UInt i = 0; while (i < this->_size && (*(a++) == *(b++))) ++i; return i == this->_size; } /* ------------------------------------------------------------------------ */ /* Matrix */ /* ------------------------------------------------------------------------ */ template<typename T> class Matrix : public TensorStorage< T, 2, Matrix<T> > { typedef TensorStorage< T, 2, Matrix<T> > parent; public: typedef typename parent::value_type value_type; typedef MatrixProxy<T> proxy; public: Matrix() : parent() {} Matrix(UInt m, UInt n, const T & def = T()) : parent(m, n, 0, def) { } Matrix(T * data, UInt m, UInt n) : parent(data, m, n, 0) { } Matrix(const Matrix & src, bool deep_copy = true) : parent(src, deep_copy) { } Matrix(const MatrixProxy<T> & src) : parent(src) { } virtual ~Matrix() { } /* ------------------------------------------------------------------------ */ inline Matrix & operator=(const Matrix & src) { parent::operator=(src); return *this; } public: /* ---------------------------------------------------------------------- */ UInt rows() const { return this->n[0]; } UInt cols() const { return this->n[1]; } /* ---------------------------------------------------------------------- */ inline T& at(UInt i, UInt j) { return *(this->values + i + j*this->n[0]); } inline const T & at(UInt i, UInt j) const { return *(this->values + i + j*this->n[0]); } /* ---------------------------------------------------------------------- */ inline T & operator()(UInt i, UInt j) { return this->at(i,j); } inline const T & operator()(UInt i, UInt j) const { return this->at(i,j); } /// give a line vector wrapped on the column i inline VectorProxy<T> operator()(UInt j) { return VectorProxy<T>(this->values + j*this->n[0], this->n[0]); } inline const VectorProxy<T> operator()(UInt j) const { return VectorProxy<T>(this->values + j*this->n[0], this->n[0]); } inline T& operator[](UInt idx) { return *(this->values + idx); }; inline const T& operator[](UInt idx) const { return *(this->values + idx); }; /* ---------------------------------------------------------------------- */ inline Matrix operator* (const Matrix & B) { Matrix C(this->rows(), B.cols()); C.mul<false, false>(*this, B); return C; } /* ----------------------------------------------------------------------- */ inline Matrix & operator*= (const T & x) { return parent::operator*= (x); } inline Matrix & operator*= (const Matrix & B) { Matrix C(*this); this->mul<false, false>(C, B); return *this; } /* ---------------------------------------------------------------------- */ template<bool tr_A, bool tr_B> inline void mul(const Matrix & A, const Matrix & B, T alpha = 1.0) { UInt k = A.cols(); if(tr_A) k = A.rows(); #ifndef AKANTU_NDEBUG if (tr_B){ AKANTU_DEBUG_ASSERT(k == B.cols(), "matrices to multiply have no fit dimensions"); AKANTU_DEBUG_ASSERT(this->cols() == B.rows(), "matrices to multiply have no fit dimensions"); } else { AKANTU_DEBUG_ASSERT(k == B.rows(), "matrices to multiply have no fit dimensions"); AKANTU_DEBUG_ASSERT(this->cols() == B.cols(), "matrices to multiply have no fit dimensions"); } if (tr_A){ AKANTU_DEBUG_ASSERT(this->rows() == A.cols(), "matrices to multiply have no fit dimensions"); } else{ AKANTU_DEBUG_ASSERT(this->rows() == A.rows(), "matrices to multiply have no fit dimensions"); } #endif //AKANTU_NDEBUG Math::matMul<tr_A, tr_B>(this->rows(), this->cols(), k, alpha, A.storage(), B.storage(), 0., this->storage()); } /* ---------------------------------------------------------------------- */ inline void outerProduct(const Vector<T> & A, const Vector<T> & B) { AKANTU_DEBUG_ASSERT(A.size() == this->rows() && B.size() == this->cols(), "A and B are not compatible with the size of the matrix"); for (UInt i = 0; i < this->rows(); ++i) { for (UInt j = 0; j < this->cols(); ++j) { this->values[i + j * this->rows()] += A[i] * B[j]; } } } private: class EigenSorter { public: EigenSorter(const Vector<T> & eigs) : eigs(eigs) { } bool operator()(const UInt & a, const UInt & b) const { return (eigs(a) > eigs(b)); } private: const Vector<T> & eigs; }; public: /* ---------------------------------------------------------------------- */ inline void eig(Vector<T> & eigenvalues, Matrix<T> & eigenvectors) const { AKANTU_DEBUG_ASSERT(this->cols() == this->rows(), "eig is not a valid operation on a rectangular matrix"); AKANTU_DEBUG_ASSERT(eigenvalues.size() == this->cols(), "eigenvalues should be of size " << this->cols() << "."); #ifndef AKANTU_NDEBUG if(eigenvectors.storage() != NULL) AKANTU_DEBUG_ASSERT((eigenvectors.rows() == eigenvectors.cols()) && (eigenvectors.rows() == this->cols()), "Eigenvectors needs to be a square matrix of size " << this->cols() << " x " << this->cols() << "."); #endif Matrix<T> tmp = *this; Vector<T> tmp_eigs(eigenvalues.size()); Matrix<T> tmp_eig_vects(eigenvectors.rows(), eigenvectors.cols()); if(tmp_eig_vects.rows() == 0 || tmp_eig_vects.cols() == 0) Math::matrixEig(tmp.cols(), tmp.storage(), tmp_eigs.storage()); else Math::matrixEig(tmp.cols(), tmp.storage(), tmp_eigs.storage(), tmp_eig_vects.storage()); Vector<UInt> perm(eigenvalues.size()); for (UInt i = 0; i < perm.size(); ++i) perm(i) = i; std::sort(perm.storage(), perm.storage() + perm.size(), EigenSorter(tmp_eigs)); for (UInt i = 0; i < perm.size(); ++i) eigenvalues(i) = tmp_eigs(perm(i)); if(tmp_eig_vects.rows() != 0 && tmp_eig_vects.cols() != 0) for (UInt i = 0; i < perm.size(); ++i) { for (UInt j = 0; j < eigenvectors.rows(); ++j) { eigenvectors(j, i) = tmp_eig_vects(j, perm(i)); } } } /* ---------------------------------------------------------------------- */ inline void eig(Vector<T> & eigenvalues) const { Matrix<T> empty; eig(eigenvalues, empty); } /* ---------------------------------------------------------------------- */ inline void eye(T alpha = 1.) { AKANTU_DEBUG_ASSERT(this->cols() == this->rows(), "eye is not a valid operation on a rectangular matrix"); this->clear(); for (UInt i = 0; i < this->cols(); ++i) { this->values[i + i * this->rows()] = alpha; } } /* ---------------------------------------------------------------------- */ static inline Matrix<T> eye(UInt m, T alpha = 1.) { Matrix<T> tmp(m, m); tmp.eye(alpha); return tmp; } /* ---------------------------------------------------------------------- */ inline T trace() const { AKANTU_DEBUG_ASSERT(this->cols() == this->rows(), "trace is not a valid operation on a rectangular matrix"); T trace = 0.; for (UInt i = 0; i < this->rows(); ++i) { trace += this->values[i + i * this->rows()]; } return trace; } /* ---------------------------------------------------------------------- */ inline Matrix transpose() const { Matrix tmp(this->cols(), this->rows()); for (UInt i = 0; i < this->rows(); ++i) { for (UInt j = 0; j < this->cols(); ++j) { tmp(j,i) = operator()(i, j); } } return tmp; } /* ---------------------------------------------------------------------- */ inline void inverse(const Matrix & A) { AKANTU_DEBUG_ASSERT(A.cols() == A.rows(), "inv is not a valid operation on a rectangular matrix"); AKANTU_DEBUG_ASSERT(this->cols() == A.cols(), "the matrix should have the same size as its inverse"); if(this->cols() == 1) *this->values = 1./ *A.storage(); else if(this->cols() == 2) Math::inv2(A.storage(), this->values); else if(this->cols() == 3) Math::inv3(A.storage(), this->values); else Math::inv(this->cols(), A.storage(), this->values); } /* --------------------------------------------------------------------- */ inline T det() const { AKANTU_DEBUG_ASSERT(this->cols() == this->rows(), "inv is not a valid operation on a rectangular matrix"); if(this->cols() == 1) return *(this->values); else if(this->cols() == 2) return Math::det2(this->values); else if(this->cols() == 3) return Math::det3(this->values); else return Math::det(this->cols(), this->values); } /* --------------------------------------------------------------------- */ inline T doubleDot(const Matrix<T> & other) const { AKANTU_DEBUG_ASSERT(this->cols() == this->rows(), "doubleDot is not a valid operation on a rectangular matrix"); if(this->cols() == 1) return *(this->values) * *(other.storage()); else if(this->cols() == 2) return Math::matrixDoubleDot22(this->values, other.storage()); else if(this->cols() == 3) return Math::matrixDoubleDot33(this->values, other.storage()); else AKANTU_DEBUG_ERROR("doubleDot is not defined for other spatial dimensions" << " than 1, 2 or 3."); return T(); } /* ---------------------------------------------------------------------- */ /// 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 << "["; for (UInt i = 0; i < this->n[0]; ++i) { if(i != 0) stream << ", "; stream << "["; for (UInt j = 0; j < this->n[1]; ++j) { if(j != 0) stream << ", "; stream << operator()(i, j); } stream << "]"; } stream << "]"; }; }; /* ------------------------------------------------------------------------ */ template<typename T> template<bool tr_A> inline void Vector<T>::mul(const Matrix<T> & A, const Vector<T> & x, Real alpha) { #ifndef AKANTU_NDEBUG UInt n = x.size(); if (tr_A){ AKANTU_DEBUG_ASSERT(n == A.rows(), "matrix and vector to multiply have no fit dimensions"); AKANTU_DEBUG_ASSERT(this->size() == A.cols(), "matrix and vector to multiply have no fit dimensions"); } else { AKANTU_DEBUG_ASSERT(n == A.cols(), "matrix and vector to multiply have no fit dimensions"); AKANTU_DEBUG_ASSERT(this->size() == A.rows(), "matrix and vector to multiply have no fit dimensions"); } #endif Math::matVectMul<tr_A>(A.rows(), A.cols(), alpha, A.storage(), x.storage(), 0., this->storage()); } /* -------------------------------------------------------------------------- */ template<typename T> inline std::ostream & operator<<(std::ostream & stream, const Matrix<T> & _this) { _this.printself(stream); return stream; } /* -------------------------------------------------------------------------- */ template<typename T> inline std::ostream & operator<<(std::ostream & stream, const Vector<T> & _this) { _this.printself(stream); return stream; } /* ------------------------------------------------------------------------ */ /* Tensor3 */ /* ------------------------------------------------------------------------ */ template<typename T> class Tensor3 : public TensorStorage< T, 3, Tensor3<T> > { typedef TensorStorage< T, 3, Tensor3<T> > parent; public: typedef typename parent::value_type value_type; typedef Tensor3Proxy<T> proxy; public: Tensor3() : parent() { }; Tensor3(UInt m, UInt n, UInt p, const T & def = T()) : parent(m, n, p, def) { } Tensor3(T * data, UInt m, UInt n, UInt p) : parent(data, m, n, p) { } Tensor3(const Tensor3 & src, bool deep_copy = true) : parent(src, deep_copy) { } public: /* ------------------------------------------------------------------------ */ inline Tensor3 & operator=(const Tensor3 & src) { parent::operator=(src); return *this; } /* ---------------------------------------------------------------------- */ inline T& operator()(UInt i, UInt j, UInt k) { return *(this->values + (k*this->n[0] + i)*this->n[1] + j); }; inline const T& operator()(UInt i, UInt j, UInt k) const { return *(this->values + (k*this->n[0] + i)*this->n[1] + j); }; inline MatrixProxy<T> operator()(UInt k) { return MatrixProxy<T>(this->values + k*this->n[0]*this->n[1], this->n[0], this->n[1]); } inline const MatrixProxy<T> operator()(UInt k) const { return MatrixProxy<T>(this->values + k*this->n[0]*this->n[1], this->n[0], this->n[1]); } inline MatrixProxy<T> operator[](UInt k) { return Matrix<T>(this->values + k*this->n[0]*this->n[1], this->n[0], this->n[1]); } inline const MatrixProxy<T> operator[](UInt k) const { return MatrixProxy<T>(this->values + k*this->n[0]*this->n[1], this->n[0], this->n[1]); } }; /* -------------------------------------------------------------------------- */ // support operations for the creation of other vectors /* -------------------------------------------------------------------------- */ template <typename T> Vector<T> operator*(const T & scalar, const Vector<T> & a) { Vector<T> r(a); r *= scalar; return r; } template <typename T> Vector<T> operator*(const Vector<T> & a, const T & scalar) { Vector<T> r(a); r *= scalar; return r; } template <typename T> Vector<T> operator/(const Vector<T> & a, const T & scalar) { Vector<T> r(a); r /= scalar; return r; } template <typename T> Vector<T> operator+(const Vector<T> & a, const Vector<T> & b) { Vector<T> r(a); r += b; return r; } template <typename T> Vector<T> operator-(const Vector<T>& a, const Vector<T>& b) { Vector<T> r(a); r -= b; return r; } /* -------------------------------------------------------------------------- */ template <typename T> Matrix<T> operator*(const T & scalar, const Matrix<T>& a) { Matrix<T> r(a); r *= scalar; return r; } template <typename T> Matrix<T> operator*(const Matrix<T>& a, const T & scalar) { Matrix<T> r(a); r *= scalar; return r; } template <typename T> Matrix<T> operator/(const Matrix<T>& a, const T & scalar) { Matrix<T> r(a); r /= scalar; return r; } template <typename T> Matrix<T> operator+(const Matrix<T>& a, const Matrix<T>& b) { Matrix<T> r(a); r += b; return r; } template <typename T> Matrix<T> operator-(const Matrix<T>& a, const Matrix<T>& b) { Matrix<T> r(a); r -= b; return r; } __END_AKANTU__ #endif /* __AKANTU_AKA_TYPES_HH__ */ diff --git a/src/io/mesh_io.cc b/src/io/mesh_io.cc index 7263bc2df..913385b26 100644 --- a/src/io/mesh_io.cc +++ b/src/io/mesh_io.cc @@ -1,95 +1,152 @@ /** * @file mesh_io.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Thu Jul 15 2010 * @date last modification: Fri Jun 13 2014 * * @brief common part for all mesh io classes * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh_io.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MeshIO::MeshIO() { canReadSurface = false; canReadExtendedData = false; } /* -------------------------------------------------------------------------- */ MeshIO::~MeshIO() { } /* -------------------------------------------------------------------------- */ MeshIO * MeshIO::getMeshIO(const std::string & filename, const MeshIOType & type) { MeshIOType t = type; if(type == _miot_auto) { std::string::size_type idx = filename.rfind('.'); std::string ext; if(idx != std::string::npos) { ext = filename.substr(idx+1); } if(ext == "msh") { t = _miot_gmsh; } else if(ext == "diana") { t = _miot_diana; } else if(ext == "inp") { t = _miot_abaqus; } else AKANTU_EXCEPTION("Cannot guess the type of file of " << filename << " (ext "<< ext <<"). " << "Please provide the MeshIOType to the read function"); } switch(t) { case _miot_gmsh : return new MeshIOMSH(); #if defined(AKANTU_STRUCTURAL_MECHANICS) case _miot_gmsh_struct : return new MeshIOMSHStruct(); #endif case _miot_diana : return new MeshIODiana(); case _miot_abaqus : return new MeshIOAbaqus(); default: return NULL; } } /* -------------------------------------------------------------------------- */ void MeshIO::read(const std::string & filename, Mesh & mesh, const MeshIOType & type) { MeshIO * mesh_io = getMeshIO(filename, type); mesh_io->read(filename, mesh); delete mesh_io; } /* -------------------------------------------------------------------------- */ void MeshIO::write(const std::string & filename, Mesh & mesh, const MeshIOType & type) { MeshIO * mesh_io = getMeshIO(filename, type); mesh_io->write(filename, mesh); delete mesh_io; } +/* -------------------------------------------------------------------------- */ +void MeshIO::constructPhysicalNames(const std::string & tag_name, + Mesh & mesh) { + + if(!phys_name_map.empty()) { + for(Mesh::type_iterator type_it = mesh.firstType(); + type_it != mesh.lastType(); + ++type_it) { + + Array<std::string> * name_vec = + mesh.getDataPointer<std::string>("physical_names", *type_it); + + const Array<UInt> & tags_vec = + mesh.getData<UInt>(tag_name, *type_it); + + for(UInt i(0); i < tags_vec.getSize(); i++) { + std::map<UInt, std::string>::const_iterator map_it + = phys_name_map.find(tags_vec(i)); + + if(map_it == phys_name_map.end()) { + std::stringstream sstm; + sstm << tags_vec(i); + name_vec->operator()(i) = sstm.str(); + } else { + name_vec->operator()(i) = map_it->second; + } + } + } + } +} + +/* -------------------------------------------------------------------------- */ + + +void MeshIO::printself(std::ostream & stream, int indent) const{ + + std::string space; + for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); + + if (phys_name_map.size()){ + + stream << space << "Physical map:" << std::endl; + + std::map<UInt, std::string>::const_iterator it = phys_name_map.begin(); + std::map<UInt, std::string>::const_iterator end = phys_name_map.end(); + + + for (; it!=end; ++it) { + stream << space << it->first << ": " << it->second << std::endl; + } + } + +} + +/* -------------------------------------------------------------------------- */ + + __END_AKANTU__ diff --git a/src/io/mesh_io.hh b/src/io/mesh_io.hh index 3cc8c32f7..d7916f62d 100644 --- a/src/io/mesh_io.hh +++ b/src/io/mesh_io.hh @@ -1,102 +1,125 @@ /** * @file mesh_io.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Jun 13 2014 * * @brief interface of a mesh io class, reader and writer * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_IO_HH__ #define __AKANTU_MESH_IO_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class MeshIO { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshIO(); virtual ~MeshIO(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void read(const std::string & filename, Mesh & mesh, const MeshIOType & type); void write(const std::string & filename, Mesh & mesh, const MeshIOType & type); /// read a mesh from the file virtual void read(__attribute__((unused)) const std::string & filename, __attribute__((unused)) Mesh & mesh) { } /// write a mesh to a file virtual void write(__attribute__((unused)) const std::string & filename, __attribute__((unused)) const Mesh & mesh) {} -private: - MeshIO * getMeshIO(const std::string & filename, const MeshIOType & type); + /// function to request the manual construction of the physical names maps + virtual void constructPhysicalNames(const std::string & tag_name, + Mesh & mesh); + + + /// method to permit to be printed to a generic stream + virtual void printself(std::ostream & stream, int indent = 0) const; + + /// static contruction of a meshio object + static MeshIO * getMeshIO(const std::string & filename, const MeshIOType & type); + /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: + std::map<UInt, std::string> & getPhysicalNameMap(){ + return phys_name_map; + } + /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: bool canReadSurface; bool canReadExtendedData; - // std::string filename; + /// correspondance between a tag and physical names (if applicable) + std::map<UInt, std::string> phys_name_map; - // Mesh & mesh; }; +/* -------------------------------------------------------------------------- */ + +inline std::ostream & operator <<(std::ostream & stream, const MeshIO &_this) { + _this.printself(stream); + return stream; +} + +/* -------------------------------------------------------------------------- */ + + + __END_AKANTU__ #include "mesh_io_msh.hh" #include "mesh_io_diana.hh" #include "mesh_io_abaqus.hh" #if defined(AKANTU_STRUCTURAL_MECHANICS) # include "mesh_io_msh_struct.hh" #endif #endif /* __AKANTU_MESH_IO_HH__ */ - diff --git a/src/io/mesh_io/mesh_io_diana.cc b/src/io/mesh_io/mesh_io_diana.cc index 4030c42b4..ae4fe08b0 100644 --- a/src/io/mesh_io/mesh_io_diana.cc +++ b/src/io/mesh_io/mesh_io_diana.cc @@ -1,529 +1,743 @@ /** * @file mesh_io_diana.cc * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Alodie Schneuwly <alodie.schneuwly@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sat Mar 26 2011 * @date last modification: Thu Mar 27 2014 * * @brief handles diana meshes * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include <fstream> #include <iostream> /* -------------------------------------------------------------------------- */ #include "mesh_io_diana.hh" - +#include "mesh_utils.hh" +#include "element_group.hh" /* -------------------------------------------------------------------------- */ #include <string.h> /* -------------------------------------------------------------------------- */ #include <stdio.h> __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Methods Implentations */ /* -------------------------------------------------------------------------- */ MeshIODiana::MeshIODiana() { canReadSurface = true; canReadExtendedData = true; _diana_to_akantu_element_types["T9TM"] = _triangle_3; + _diana_to_akantu_element_types["CT6CM"] = _triangle_6; _diana_to_akantu_element_types["Q12TM"] = _quadrangle_4; + _diana_to_akantu_element_types["CQ8CM"] = _quadrangle_8; _diana_to_akantu_element_types["TP18L"] = _pentahedron_6; + _diana_to_akantu_element_types["CTP45"] = _pentahedron_15; _diana_to_akantu_element_types["TE12L"] = _tetrahedron_4; _diana_to_akantu_element_types["HX24L"] = _hexahedron_8; + _diana_to_akantu_element_types["CHX60"] = _hexahedron_20; _diana_to_akantu_mat_prop["YOUNG"] = "E"; _diana_to_akantu_mat_prop["DENSIT"] = "rho"; _diana_to_akantu_mat_prop["POISON"] = "nu"; } /* -------------------------------------------------------------------------- */ MeshIODiana::~MeshIODiana() { std::map<std::string, Array<UInt> *>::iterator ng_it; std::map<std::string, std::vector<Element> *>::iterator eg_it; for (ng_it = node_groups.begin(); ng_it != node_groups.end(); ++ng_it) { delete ng_it->second; } for (eg_it = element_groups.begin(); eg_it != element_groups.end(); ++eg_it) { delete eg_it->second; } } /* -------------------------------------------------------------------------- */ inline void my_getline(std::ifstream & infile, std::string & line) { std::getline(infile, line); //read the line size_t pos = line.find("\r"); /// remove the extra \r if needed line = line.substr(0, pos); } /* -------------------------------------------------------------------------- */ void MeshIODiana::read(const std::string & filename, Mesh & mesh) { AKANTU_DEBUG_IN(); std::ifstream infile; infile.open(filename.c_str()); std::string line; UInt first_node_number = std::numeric_limits<UInt>::max(); - std::vector<Element> global_to_local_index; + diana_element_number_to_elements.clear(); if(!infile.good()) { AKANTU_DEBUG_ERROR("Cannot open file " << filename); } while(infile.good()) { my_getline(infile, line); /// read all nodes if(line == "'COORDINATES'") { line = readCoordinates(infile, mesh, first_node_number); } /// read all elements if (line == "'ELEMENTS'") { - line = readElements(infile, mesh, global_to_local_index, first_node_number); + line = readElements(infile, mesh, first_node_number); } /// read the material properties and write a .dat file if (line == "'MATERIALS'") { line = readMaterial(infile, filename); } /// read the material properties and write a .dat file if (line == "'GROUPS'") { - line = readGroups(infile, global_to_local_index, first_node_number); + line = readGroups(infile, first_node_number); } } infile.close(); mesh.nb_global_nodes = mesh.nodes->getSize(); - mesh.registerEventHandler(*this); + createGroupsInMesh(mesh); + + MeshUtils::fillElementToSubElementsData(mesh); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshIODiana::write(__attribute__((unused)) const std::string & filename, __attribute__((unused)) const Mesh & mesh) { AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readCoordinates(std::ifstream & infile, Mesh & mesh, UInt & first_node_number) { AKANTU_DEBUG_IN(); Array<Real> & nodes = const_cast<Array<Real> &>(mesh.getNodes()); std::string line; UInt index; Real coord[3]; do { my_getline(infile, line); if("'ELEMENTS'" == line) break; //end = true; //else { /// for each node, read the coordinates std::stringstream sstr_node(line); sstr_node >> index >> coord[0] >> coord[1] >> coord[2]; //if (!sstr_node.fail()) //break; first_node_number = first_node_number < index ? first_node_number : index; nodes.push_back(coord); // } } while(true);//!end); AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ UInt MeshIODiana::readInterval(std::stringstream & line, std::set<UInt> & interval) { + + int space; + space = line.get(); + while (space == ' '){ + space = line.get(); + if(line.fail()) { + line.clear(std::ios::eofbit); + return 0; + } + } + if(!line.fail()) line.unget(); + else { + line.clear(std::ios::eofbit); + return 0; + } + UInt first; line >> first; if(line.fail()) { return 0; } interval.insert(first); + // std::cerr << "first: " << first << std::endl; + UInt second; int dash; dash = line.get(); if(dash == '-') { line >> second; interval.insert(second); + + // std::cerr << "second: " << second << std::endl; + + int bracket; + UInt unknown_stuff; + bracket = line.get(); + if(bracket == '('){ + line >> unknown_stuff; + bracket = line.get(); + } + else{ + if(line.fail()) line.clear(std::ios::eofbit); + else line.unget(); + } return 2; } if(line.fail()) line.clear(std::ios::eofbit); // in case of get at end of the line else line.unget(); return 1; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readGroups(std::ifstream & infile, - std::vector<Element> & global_to_local_index, - UInt first_node_number) { + UInt first_node_number) { AKANTU_DEBUG_IN(); std::string line; my_getline(infile, line); bool reading_nodes_group = false; while(line != "'SUPPORTS'") { if(line == "NODES") { reading_nodes_group = true; my_getline(infile, line); } if(line == "ELEMEN") { reading_nodes_group = false; my_getline(infile, line); } + // std::cerr << line << std::endl; std::stringstream *str = new std::stringstream(line); UInt id; std::string name; char c; *str >> id >> name >> c; + // std::cerr << "AAAA " << id << " " << name << " " << c << std::endl; + Array<UInt> * list_ids = new Array<UInt>(0, 1, name); UInt s = 1; bool end = false; while(!end) { while(!str->eof() && s != 0) { std::set<UInt> interval; s = readInterval(*str, interval); std::set<UInt>::iterator it = interval.begin(); if(s == 1) list_ids->push_back(*it); if(s == 2) { UInt first = *it; ++it; UInt second = *it; for(UInt i = first; i <= second; ++i) { list_ids->push_back(i); } } } if(str->fail()) end = true; else { my_getline(infile, line); delete str; str = new std::stringstream(line); + s = 1; } } delete str; if(reading_nodes_group) { + + // reading a node group + for (UInt i = 0; i < list_ids->getSize(); ++i) { (*list_ids)(i) -= first_node_number; } node_groups[name] = list_ids; } else { + + // reading an element group + std::vector<Element> * elem = new std::vector<Element>; elem->reserve(list_ids->getSize()); for (UInt i = 0; i < list_ids->getSize(); ++i) { - Element & e = global_to_local_index[(*list_ids)(i)-1]; + Element & e = diana_element_number_to_elements[(*list_ids)(i)]; if(e.type != _not_defined) elem->push_back(e); } element_groups[name] = elem; delete list_ids; } my_getline(infile, line); } AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readElements(std::ifstream & infile, Mesh & mesh, - std::vector<Element> & global_to_local_index, UInt first_node_number) { AKANTU_DEBUG_IN(); std::string line; my_getline(infile, line); if("CONNECTIVITY" == line) { - line = readConnectivity(infile, mesh, global_to_local_index, first_node_number); + line = readConnectivity(infile, mesh, first_node_number); } /// read the line corresponding to the materials if ("MATERIALS" == line) { - line = readMaterialElement(infile, mesh, global_to_local_index); + line = readMaterialElement(infile, mesh); } AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readConnectivity(std::ifstream & infile, Mesh & mesh, - std::vector<Element> & global_to_local_index, UInt first_node_number) { AKANTU_DEBUG_IN(); Int index; std::string lline; std::string diana_type; ElementType akantu_type, akantu_type_old = _not_defined; Array<UInt> *connectivity = NULL; UInt node_per_element = 0; Element elem; - bool end = false; - do { + while (1) { my_getline(infile, lline); + // std::cerr << lline << std::endl; std::stringstream sstr_elem(lline); - if(lline == "MATERIALS") end = true; - else { - /// traiter les coordonnees - sstr_elem >> index; - sstr_elem >> diana_type; - - akantu_type = _diana_to_akantu_element_types[diana_type]; - - if(akantu_type != _not_defined) { - if(akantu_type != akantu_type_old) { - connectivity = mesh.getConnectivityPointer(akantu_type); - - node_per_element = connectivity->getNbComponent(); - akantu_type_old = akantu_type; - } - - UInt local_connect[node_per_element]; - for(UInt j = 0; j < node_per_element; ++j) { - UInt node_index; - sstr_elem >> node_index; - - node_index -= first_node_number; - local_connect[j] = node_index; - } - connectivity->push_back(local_connect); + if(lline == "MATERIALS") break; + + /// traiter les coordonnees + sstr_elem >> index; + sstr_elem >> diana_type; + + akantu_type = _diana_to_akantu_element_types[diana_type]; + + if(akantu_type == _not_defined) continue; + + if(akantu_type != akantu_type_old) { + connectivity = mesh.getConnectivityPointer(akantu_type); + + node_per_element = connectivity->getNbComponent(); + akantu_type_old = akantu_type; + } + + UInt local_connect[node_per_element]; + + //used if element is written on two lines + UInt j_last; + + for(UInt j = 0; j < node_per_element; ++j) { + UInt node_index; + sstr_elem >> node_index; + + // check s'il y a pas plus rien après un certain point + + if (sstr_elem.fail()) { + sstr_elem.clear(); + sstr_elem.ignore(); + break; + } + + node_index -= first_node_number; + local_connect[j] = node_index; + j_last = j; + } - elem.type = akantu_type; - elem.element = connectivity->getSize() - 1; - } else { - elem.type = _not_defined; - elem.element = UInt(-1); + // check if element is written in two lines + + if(j_last != (node_per_element-1)){ + + //if this is the case, read on more line + + my_getline(infile, lline); + std::stringstream sstr_elem(lline); + + for(UInt j = (j_last+1); j < node_per_element; ++j) { + + UInt node_index; + sstr_elem >> node_index; + + node_index -= first_node_number; + local_connect[j] = node_index; } + } + + // Exceptions + UInt local_connect_non_modified[node_per_element]; + + // Create a new unmodified vector + for(UInt k = 0; k < node_per_element; ++k) { + local_connect_non_modified[k] = local_connect[k]; + } + + switch(akantu_type){ + + case _pentahedron_15: + local_connect[0] = local_connect_non_modified[2]; + local_connect[1] = local_connect_non_modified[4]; + local_connect[2] = local_connect_non_modified[0]; + local_connect[3] = local_connect_non_modified[11]; + local_connect[4] = local_connect_non_modified[13]; + local_connect[5] = local_connect_non_modified[9]; + local_connect[6] = local_connect_non_modified[3]; + local_connect[7] = local_connect_non_modified[5]; + local_connect[8] = local_connect_non_modified[1]; + local_connect[9] = local_connect_non_modified[7]; + local_connect[10] =local_connect_non_modified[8]; + local_connect[11] =local_connect_non_modified[6]; + local_connect[12] =local_connect_non_modified[12]; + local_connect[13] =local_connect_non_modified[14]; + local_connect[14] =local_connect_non_modified[10]; + break; + + case _hexahedron_20: + local_connect[0] = local_connect_non_modified[14]; + local_connect[8] = local_connect_non_modified[13]; + local_connect[1] = local_connect_non_modified[12]; + local_connect[9] = local_connect_non_modified[19]; + local_connect[2] = local_connect_non_modified[18]; + local_connect[10] = local_connect_non_modified[17]; + local_connect[3] = local_connect_non_modified[16]; + local_connect[11] = local_connect_non_modified[15]; + local_connect[12] = local_connect_non_modified[9]; + local_connect[13] = local_connect_non_modified[8]; + local_connect[14] = local_connect_non_modified[11]; + local_connect[15] = local_connect_non_modified[10]; + local_connect[4] = local_connect_non_modified[2]; + local_connect[16] = local_connect_non_modified[1]; + local_connect[5] = local_connect_non_modified[0]; + local_connect[17] = local_connect_non_modified[7]; + local_connect[6] = local_connect_non_modified[6]; + local_connect[18] = local_connect_non_modified[5]; + local_connect[7] = local_connect_non_modified[4]; + local_connect[19] = local_connect_non_modified[3]; + break; - global_to_local_index.push_back(elem); + default: + //nothing to change + break; } + + connectivity->push_back(local_connect); + + elem.type = akantu_type; + elem.element = connectivity->getSize() - 1; + + diana_element_number_to_elements[index] = elem; + akantu_number_to_diana_number[elem] = index; } - while(!end); AKANTU_DEBUG_OUT(); return lline; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readMaterialElement(std::ifstream & infile, - Mesh & mesh, - std::vector<Element> & global_to_local_index) { + Mesh & mesh) { AKANTU_DEBUG_IN(); std::string line; std::stringstream sstr_tag_name; sstr_tag_name << "tag_" << 0; Mesh::type_iterator it = mesh.firstType(); Mesh::type_iterator end = mesh.lastType(); for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it); mesh.getDataPointer<UInt>("material", *it, _not_ghost, 1)->resize(nb_element); } my_getline(infile, line); while(line != "'MATERIALS'") { line = line.substr(line.find('/') + 1, std::string::npos); // erase the first slash / of the line char tutu[250]; strcpy(tutu, line.c_str()); + + // AKANTU_DEBUG_WARNING("reading line " << line); Array<UInt> temp_id(0, 2); UInt mat; while(true){ std::stringstream sstr_intervals_elements(line); UInt id[2]; char temp; while(sstr_intervals_elements.good()) { sstr_intervals_elements >> id[0] >> temp >> id[1]; // >> "/" >> mat; if(!sstr_intervals_elements.fail()) temp_id.push_back(id); } if (sstr_intervals_elements.fail()) { sstr_intervals_elements.clear(); sstr_intervals_elements.ignore(); sstr_intervals_elements >> mat; break; } my_getline(infile, line); } // loop over elements // UInt * temp_id_val = temp_id.storage(); for (UInt i = 0; i < temp_id.getSize(); ++i) for (UInt j = temp_id(i, 0); j <= temp_id(i, 1); ++j) { - Element & element = global_to_local_index[j - 1]; + Element & element = diana_element_number_to_elements[j]; if(element.type == _not_defined) continue; UInt elem = element.element; ElementType type = element.type; Array<UInt> & data = *(mesh.getDataPointer<UInt>("material", type, _not_ghost)); data(elem) = mat; } my_getline(infile, line); } AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readMaterial(std::ifstream & infile, const std::string & filename) { AKANTU_DEBUG_IN(); std::stringstream mat_file_name; mat_file_name << "material_" << filename; std::ofstream material_file; material_file.open(mat_file_name.str().c_str());//mat_file_name.str()); UInt mat_index; std::string line; bool first_mat = true; bool end = false; UInt mat_id = 0; typedef std::map<std::string, Real> MatProp; MatProp mat_prop; do{ my_getline(infile, line); std::stringstream sstr_material(line); - if("'GROUPS'" == line) { + if(("'GROUPS'" == line) || ( "'END'" == line)) { if(!mat_prop.empty()) { material_file << "material elastic [" << std::endl; material_file << "\tname = material" << ++mat_id << std::endl; for(MatProp::iterator it = mat_prop.begin(); it != mat_prop.end(); ++it) material_file << "\t" << it->first << " = " << it->second << std::endl; material_file << "]" << std::endl; mat_prop.clear(); } end = true; } else { /// traiter les caractéristiques des matériaux sstr_material >> mat_index; if(!sstr_material.fail()) { if(!first_mat) { if(!mat_prop.empty()) { material_file << "material elastic [" << std::endl; material_file << "\tname = material" << ++mat_id << std::endl; for(MatProp::iterator it = mat_prop.begin(); it != mat_prop.end(); ++it) material_file << "\t" << it->first << " = " << it->second << std::endl; material_file << "]" << std::endl; mat_prop.clear(); } } first_mat = false; } else { sstr_material.clear(); } std::string prop_name; sstr_material >> prop_name; std::map<std::string, std::string>::iterator it; it = _diana_to_akantu_mat_prop.find(prop_name); if(it != _diana_to_akantu_mat_prop.end()) { Real value; sstr_material >> value; mat_prop[it->second] = value; } else { AKANTU_DEBUG_INFO("In material reader, property " << prop_name << "not recognized"); } } } while (!end); AKANTU_DEBUG_OUT(); return line; } +/* -------------------------------------------------------------------------- */ + +void MeshIODiana::createGroupsInMesh(Mesh & mesh) { + + /* ------------------------------------------------------------------------ */ + // create the element groups + /* ------------------------------------------------------------------------ */ + + { + std::map<std::string, std::vector<Element> *>::iterator git + = element_groups.begin(); + std::map<std::string, std::vector<Element> *>::iterator gend + = element_groups.end(); + + for (;git != gend; ++git) { + std::string group_name = git->first; + std::vector<Element> & element_group = *git->second; + + if (element_group.size() == 0) continue; + Element & first_element = element_group[0]; + + UInt group_dim = mesh.getSpatialDimension(first_element.type); + mesh.createElementGroup(group_name, group_dim); + ElementGroup & group = mesh.getElementGroup(git->first); + + std::vector<Element>::iterator it = element_group.begin(); + std::vector<Element>::iterator end = element_group.end(); + + for(; it != end; ++it){ + group.add(*it); + } + + } + } + + /* ------------------------------------------------------------------------ */ + // create the node groups + /* ------------------------------------------------------------------------ */ + + { + std::map<std::string, Array<UInt> *>::iterator git + = node_groups.begin(); + std::map<std::string, Array<UInt> *>::iterator gend + = node_groups.end(); + + for (;git != gend; ++git) { + std::string group_name = git->first; + Array<UInt> & node_group = *git->second; + + if (node_group.getSize() == 0) continue; + // Element & first_element = element_group[0]; + + UInt group_dim = 1;//mesh.getSpatialDimension(first_element.type); + mesh.createNodeGroup(group_name, group_dim); + NodeGroup & group = mesh.getNodeGroup(git->first); + + Array<UInt>::iterator<UInt> it = node_group.begin(); + Array<UInt>::iterator<UInt> end = node_group.end(); + + for(; it != end; ++it){ + group.add(*it); + } + + } + } +} + + +/* -------------------------------------------------------------------------- */ + +void MeshIODiana::printself(std::ostream & stream,int indent) const { + + MeshIO::printself(stream,indent); + + std::string space; + for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); + + if (node_groups.size()){ + stream << space << "Read node groups: "; + std::map<std::string, Array<UInt> *>::const_iterator it = node_groups.begin(); + std::map<std::string, Array<UInt> *>::const_iterator end = node_groups.end(); + + for (;it != end; ++it) { + stream << "'" << it->first << "' "; + } + stream << std::endl; + } + + if (element_groups.size()){ + stream << space << "Read element groups: "; + std::map<std::string, std::vector<Element> *>::const_iterator it = element_groups.begin(); + std::map<std::string, std::vector<Element> *>::const_iterator end = element_groups.end(); -void MeshIODiana::onNodesRemoved(const Array<UInt> & element_list, - const Array<UInt> & new_numbering, - const RemovedNodesEvent & event) { - std::map<std::string, Array<UInt> *>::iterator it = node_groups.begin(); - std::map<std::string, Array<UInt> *>::iterator end = node_groups.end(); - for (; it != end; ++it) { - Array<UInt> & group = *(it->second); - Array<UInt>::iterator<> git = group.begin(); - Array<UInt>::iterator<> gend = group.end(); - for (; git != gend; ++git) { - UInt new_id = new_numbering(*git); - AKANTU_DEBUG_ASSERT(new_id != UInt(-1), "Argh " << *git << " was suppressed!"); - *git = new_id; + for (;it != end; ++it) { + stream << "'" << it->first << "' "; } + stream << std::endl; } } __END_AKANTU__ diff --git a/src/io/mesh_io/mesh_io_diana.hh b/src/io/mesh_io/mesh_io_diana.hh index 0c827ccb3..bc349764f 100644 --- a/src/io/mesh_io/mesh_io_diana.hh +++ b/src/io/mesh_io/mesh_io_diana.hh @@ -1,154 +1,150 @@ /** * @file mesh_io_diana.hh * * @author David Simon Kammer <david.kammer@epfl.ch> * @author Alodie Schneuwly <alodie.schneuwly@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Sat Mar 26 2011 * @date last modification: Mon Aug 19 2013 * * @brief diana mesh reader description * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_IO_DIANA_HH__ #define __AKANTU_MESH_IO_DIANA_HH__ /* -------------------------------------------------------------------------- */ #include "mesh_io.hh" /* -------------------------------------------------------------------------- */ #include <vector> /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ -class MeshIODiana : public MeshIO, public MeshEventHandler { +class MeshIODiana : public MeshIO { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshIODiana(); virtual ~MeshIODiana(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// read a mesh from the file virtual void read(const std::string & filename, Mesh&mesh); /// write a mesh to a file virtual void write(const std::string & filename, const Mesh & mesh); private: std::string readCoordinates(std::ifstream & infile, Mesh & mesh, UInt & first_node_number); std::string readElements(std::ifstream & infile, Mesh & mesh, - std::vector<Element> & global_to_local_index, UInt first_node_number); std::string readGroups(std::ifstream & infile, - std::vector<Element> & global_to_local_index, UInt first_node_number); std::string readConnectivity(std::ifstream & infile, Mesh & mesh, - std::vector<Element> & global_to_local_index, UInt first_node_number); std::string readMaterialElement(std::ifstream & infile, - Mesh & mesh, - std::vector<Element> & global_to_local_index); + Mesh & mesh); std::string readMaterial(std::ifstream & infile, const std::string & filename); UInt readInterval(std::stringstream & line, std::set<UInt> & interval); + void createGroupsInMesh(Mesh & mesh); + + virtual void printself(std::ostream & stream, int indent = 0) const; + /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: const Array<UInt> & getNodeGroup(const std::string & group_name) const { std::map<std::string, Array<UInt> *>::const_iterator it = node_groups.find(group_name); AKANTU_DEBUG_ASSERT(it != node_groups.end(), "There is no nodes group named : " << group_name); return *it->second; } const std::vector<Element> & getElementGroup(const std::string & group_name) const { std::map<std::string, std::vector<Element> *>::const_iterator it = element_groups.find(group_name); AKANTU_DEBUG_ASSERT(it != element_groups.end(), "There is no elements group named : " << group_name); return *it->second; } std::vector<std::string> getNodeGroupsNames() const { std::vector<std::string> names; std::map<std::string, Array<UInt> *>::const_iterator it; for(it = node_groups.begin(); it != node_groups.end(); ++it) names.push_back(it->first); return names; } std::vector<std::string> getElementGroupsNames() const { std::vector<std::string> names; std::map<std::string, std::vector<Element> *>::const_iterator it; for(it = element_groups.begin(); it != element_groups.end(); ++it) names.push_back(it->first); return names; } - /* ------------------------------------------------------------------------ */ - /* Mesh Event Handler inherited members */ - /* ------------------------------------------------------------------------ */ -protected: - virtual void onNodesRemoved(const Array<UInt> & element_list, - const Array<UInt> & new_numbering, - const RemovedNodesEvent & event); - + /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: std::map<std::string, ElementType> _diana_to_akantu_element_types; std::map<std::string, std::string> _diana_to_akantu_mat_prop; std::map<std::string, Array<UInt> *> node_groups; std::map<std::string, std::vector<Element> *> element_groups; + + std::map<UInt,Element> diana_element_number_to_elements; + std::map<Element,UInt> akantu_number_to_diana_number; }; __END_AKANTU__ #endif /* __AKANTU_MESH_IO_DIANA_HH__ */ diff --git a/src/io/mesh_io/mesh_io_msh.cc b/src/io/mesh_io/mesh_io_msh.cc index adb970b39..071407a96 100644 --- a/src/io/mesh_io/mesh_io_msh.cc +++ b/src/io/mesh_io/mesh_io_msh.cc @@ -1,572 +1,555 @@ /** * @file mesh_io_msh.cc * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Jul 04 2014 * * @brief Read/Write for MSH files generated by gmsh * * @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 <http://www.gnu.org/licenses/>. * */ /* ----------------------------------------------------------------------------- Version (Legacy) 1.0 $NOD number-of-nodes node-number x-coord y-coord z-coord ... $ENDNOD $ELM number-of-elements elm-number elm-type reg-phys reg-elem number-of-nodes node-number-list ... $ENDELM ----------------------------------------------------------------------------- Version 2.1 $MeshFormat version-number file-type data-size $EndMeshFormat $Nodes number-of-nodes node-number x-coord y-coord z-coord ... $EndNodes $Elements number-of-elements elm-number elm-type number-of-tags < tag > ... node-number-list ... $EndElements $PhysicalNames number-of-names physical-dimension physical-number "physical-name" ... $EndPhysicalNames $NodeData number-of-string-tags < "string-tag" > ... number-of-real-tags < real-tag > ... number-of-integer-tags < integer-tag > ... node-number value ... ... $EndNodeData $ElementData number-of-string-tags < "string-tag" > ... number-of-real-tags < real-tag > ... number-of-integer-tags < integer-tag > ... elm-number value ... ... $EndElementData $ElementNodeData number-of-string-tags < "string-tag" > ... number-of-real-tags < real-tag > ... number-of-integer-tags < integer-tag > ... elm-number number-of-nodes-per-element value ... ... $ElementEndNodeData ----------------------------------------------------------------------------- elem-type 1: 2-node line. 2: 3-node triangle. 3: 4-node quadrangle. 4: 4-node tetrahedron. 5: 8-node hexahedron. 6: 6-node prism. 7: 5-node pyramid. 8: 3-node second order line 9: 6-node second order triangle 10: 9-node second order quadrangle 11: 10-node second order tetrahedron 12: 27-node second order hexahedron 13: 18-node second order prism 14: 14-node second order pyramid 15: 1-node point. 16: 8-node second order quadrangle 17: 20-node second order hexahedron 18: 15-node second order prism 19: 13-node second order pyramid 20: 9-node third order incomplete triangle 21: 10-node third order triangle 22: 12-node fourth order incomplete triangle 23: 15-node fourth order triangle 24: 15-node fifth order incomplete triangle 25: 21-node fifth order complete triangle 26: 4-node third order edge 27: 5-node fourth order edge 28: 6-node fifth order edge 29: 20-node third order tetrahedron 30: 35-node fourth order tetrahedron 31: 56-node fifth order tetrahedron -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ #include "mesh_io.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Methods Implentations */ /* -------------------------------------------------------------------------- */ MeshIOMSH::MeshIOMSH() { canReadSurface = true; canReadExtendedData = true; _msh_nodes_per_elem[_msh_not_defined ] = 0; _msh_nodes_per_elem[_msh_segment_2 ] = 2; _msh_nodes_per_elem[_msh_triangle_3 ] = 3; _msh_nodes_per_elem[_msh_quadrangle_4 ] = 4; _msh_nodes_per_elem[_msh_tetrahedron_4 ] = 4; _msh_nodes_per_elem[_msh_hexahedron_8 ] = 8; _msh_nodes_per_elem[_msh_prism_1 ] = 6; _msh_nodes_per_elem[_msh_pyramid_1 ] = 1; _msh_nodes_per_elem[_msh_segment_3 ] = 3; _msh_nodes_per_elem[_msh_triangle_6 ] = 6; _msh_nodes_per_elem[_msh_quadrangle_9 ] = 9; _msh_nodes_per_elem[_msh_tetrahedron_10] = 10; _msh_nodes_per_elem[_msh_hexahedron_27 ] = 27; _msh_nodes_per_elem[_msh_hexahedron_20 ] = 20; _msh_nodes_per_elem[_msh_prism_18 ] = 18; _msh_nodes_per_elem[_msh_prism_15 ] = 15; _msh_nodes_per_elem[_msh_pyramid_14 ] = 14; _msh_nodes_per_elem[_msh_point ] = 1; _msh_nodes_per_elem[_msh_quadrangle_8 ] = 8; _msh_to_akantu_element_types[_msh_not_defined ] = _not_defined; _msh_to_akantu_element_types[_msh_segment_2 ] = _segment_2; _msh_to_akantu_element_types[_msh_triangle_3 ] = _triangle_3; _msh_to_akantu_element_types[_msh_quadrangle_4 ] = _quadrangle_4; _msh_to_akantu_element_types[_msh_tetrahedron_4 ] = _tetrahedron_4; _msh_to_akantu_element_types[_msh_hexahedron_8 ] = _hexahedron_8; _msh_to_akantu_element_types[_msh_prism_1 ] = _pentahedron_6; _msh_to_akantu_element_types[_msh_pyramid_1 ] = _not_defined; _msh_to_akantu_element_types[_msh_segment_3 ] = _segment_3; _msh_to_akantu_element_types[_msh_triangle_6 ] = _triangle_6; _msh_to_akantu_element_types[_msh_quadrangle_9 ] = _not_defined; _msh_to_akantu_element_types[_msh_tetrahedron_10] = _tetrahedron_10; _msh_to_akantu_element_types[_msh_hexahedron_27 ] = _not_defined; _msh_to_akantu_element_types[_msh_prism_18 ] = _not_defined; _msh_to_akantu_element_types[_msh_hexahedron_20 ] = _hexahedron_20; _msh_to_akantu_element_types[_msh_prism_15 ] = _pentahedron_15; _msh_to_akantu_element_types[_msh_pyramid_14 ] = _not_defined; _msh_to_akantu_element_types[_msh_point ] = _point_1; _msh_to_akantu_element_types[_msh_quadrangle_8 ] = _quadrangle_8; _akantu_to_msh_element_types[_not_defined ] = _msh_not_defined; _akantu_to_msh_element_types[_segment_2 ] = _msh_segment_2; _akantu_to_msh_element_types[_segment_3 ] = _msh_segment_3; _akantu_to_msh_element_types[_triangle_3 ] = _msh_triangle_3; _akantu_to_msh_element_types[_triangle_6 ] = _msh_triangle_6; _akantu_to_msh_element_types[_tetrahedron_4 ] = _msh_tetrahedron_4; _akantu_to_msh_element_types[_tetrahedron_10 ] = _msh_tetrahedron_10; _akantu_to_msh_element_types[_quadrangle_4 ] = _msh_quadrangle_4; _akantu_to_msh_element_types[_quadrangle_8 ] = _msh_quadrangle_8; _akantu_to_msh_element_types[_hexahedron_8 ] = _msh_hexahedron_8; _akantu_to_msh_element_types[_hexahedron_20 ] = _msh_hexahedron_20; _akantu_to_msh_element_types[_pentahedron_6 ] = _msh_prism_1; _akantu_to_msh_element_types[_pentahedron_15 ] = _msh_prism_15; _akantu_to_msh_element_types[_point_1 ] = _msh_point; #if defined(AKANTU_STRUCTURAL_MECHANICS) _akantu_to_msh_element_types[_bernoulli_beam_2] = _msh_segment_2; _akantu_to_msh_element_types[_bernoulli_beam_3] = _msh_segment_2; _akantu_to_msh_element_types[_kirchhoff_shell] = _msh_triangle_3; #endif std::map<ElementType, MSHElementType>::iterator it; for(it = _akantu_to_msh_element_types.begin(); it != _akantu_to_msh_element_types.end(); ++it) { UInt nb_nodes = _msh_nodes_per_elem[it->second]; UInt * tmp = new UInt[nb_nodes]; for (UInt i = 0; i < nb_nodes; ++i) { tmp[i] = i; } switch(it->first) { case _tetrahedron_10: tmp[8] = 9; tmp[9] = 8; break; case _pentahedron_15: tmp[ 0] = 2; tmp[ 1] = 0; tmp[ 2] = 1; tmp[ 3] = 5; tmp[ 4] = 3; tmp[ 5] = 4; tmp[ 6] = 8; tmp[ 8] = 11; tmp[ 9] = 6; tmp[10] = 9; tmp[11] = 10; tmp[12] = 14; tmp[14] = 12; break; case _hexahedron_20: tmp[ 9] = 11; tmp[10] = 12; tmp[11] = 9; tmp[12] = 13; tmp[13] = 10; tmp[17] = 19; tmp[18] = 17; tmp[19] = 18; break; default: //nothing to change break; } _read_order[it->first] = tmp; } } /* -------------------------------------------------------------------------- */ MeshIOMSH::~MeshIOMSH() { std::map<ElementType, MSHElementType>::iterator it; for(it = _akantu_to_msh_element_types.begin(); it != _akantu_to_msh_element_types.end(); ++it) { delete [] _read_order[it->first]; } } /* -------------------------------------------------------------------------- */ void MeshIOMSH::read(const std::string & filename, Mesh & mesh) { std::ifstream infile; infile.open(filename.c_str()); std::string line; UInt first_node_number = std::numeric_limits<UInt>::max(), last_node_number = 0, file_format = 1, current_line = 0; if(!infile.good()) { AKANTU_DEBUG_ERROR("Cannot open file " << filename); } while(infile.good()) { std::getline(infile, line); current_line++; /// read the header if(line == "$MeshFormat") { std::getline(infile, line); /// the format line std::stringstream sstr(line); std::string version; sstr >> version; Int format; sstr >> format; if(format != 0) AKANTU_DEBUG_ERROR("This reader can only read ASCII files."); std::getline(infile, line); /// the end of block line current_line += 2; file_format = 2; } /// read the physical names if(line == "$PhysicalNames") { std::getline(infile, line); /// the format line std::stringstream sstr(line); UInt num_of_phys_names; sstr >> num_of_phys_names; for(UInt k(0); k < num_of_phys_names; k++) { std::getline(infile, line); std::stringstream sstr_phys_name(line); UInt phys_name_id; UInt phys_dim; sstr_phys_name >> phys_dim >> phys_name_id; std::size_t b = line.find("\""); std::size_t e = line.rfind("\""); std::string phys_name = line.substr(b + 1, e - b -1); phys_name_map[phys_name_id] = phys_name; } } /// read all nodes if(line == "$Nodes" || line == "$NOD") { UInt nb_nodes; std::getline(infile, line); std::stringstream sstr(line); sstr >> nb_nodes; current_line++; Array<Real> & nodes = const_cast<Array<Real> &>(mesh.getNodes()); nodes.resize(nb_nodes); mesh.nb_global_nodes = nb_nodes; UInt index; Real coord[3]; UInt spatial_dimension = nodes.getNbComponent(); /// for each node, read the coordinates for(UInt i = 0; i < nb_nodes; ++i) { UInt offset = i * spatial_dimension; std::getline(infile, line); std::stringstream sstr_node(line); sstr_node >> index >> coord[0] >> coord[1] >> coord[2]; current_line++; first_node_number = std::min(first_node_number,index); last_node_number = std::max(last_node_number, index); /// read the coordinates for(UInt j = 0; j < spatial_dimension; ++j) nodes.storage()[offset + j] = coord[j]; } std::getline(infile, line); /// the end of block line } /// read all elements if(line == "$Elements" || line == "$ELM") { UInt nb_elements; UInt * read_order = NULL; std::getline(infile, line); std::stringstream sstr(line); sstr >> nb_elements; current_line++; Int index; UInt msh_type; ElementType akantu_type, akantu_type_old = _not_defined; Array<UInt> *connectivity = NULL; UInt node_per_element = 0; for(UInt i = 0; i < nb_elements; ++i) { std::getline(infile, line); std::stringstream sstr_elem(line); current_line++; sstr_elem >> index; sstr_elem >> msh_type; /// get the connectivity vector depending on the element type akantu_type = _msh_to_akantu_element_types[(MSHElementType) msh_type]; if(akantu_type == _not_defined) { AKANTU_DEBUG_WARNING("Unsuported element kind " << msh_type << " at line " << current_line); continue; } if(akantu_type != akantu_type_old) { connectivity = mesh.getConnectivityPointer(akantu_type); // connectivity->resize(0); node_per_element = connectivity->getNbComponent(); akantu_type_old = akantu_type; read_order = _read_order[akantu_type]; } /// read tags informations if(file_format == 2) { UInt nb_tags; sstr_elem >> nb_tags; for(UInt j = 0; j < nb_tags; ++j) { Int tag; sstr_elem >> tag; std::stringstream sstr_tag_name; sstr_tag_name << "tag_" << j; Array<UInt> * data = mesh.getDataPointer<UInt>(sstr_tag_name.str(), akantu_type, _not_ghost); data->push_back(tag); } } else if (file_format == 1) { Int tag; sstr_elem >> tag; //reg-phys std::string tag_name = "tag_0"; Array<UInt> * data = mesh.getDataPointer<UInt>(tag_name, akantu_type, _not_ghost); data->push_back(tag); sstr_elem >> tag; //reg-elem tag_name = "tag_1"; data = mesh.getDataPointer<UInt>(tag_name, akantu_type, _not_ghost); data->push_back(tag); sstr_elem >> tag; //number-of-nodes } UInt local_connect[node_per_element]; for(UInt j = 0; j < node_per_element; ++j) { UInt node_index; sstr_elem >> node_index; AKANTU_DEBUG_ASSERT(node_index <= last_node_number, "Node number not in range : line " << current_line); node_index -= first_node_number; local_connect[read_order[j]] = node_index; } connectivity->push_back(local_connect); } std::getline(infile, line); /// the end of block line } if((line[0] == '$') && (line.find("End") == std::string::npos)) { AKANTU_DEBUG_WARNING("Unsuported block_kind " << line << " at line " << current_line); } } mesh.updateTypesOffsets(_not_ghost); infile.close(); - if(!phys_name_map.empty()) { - for(Mesh::type_iterator type_it = mesh.firstType(); type_it != mesh.lastType(); ++type_it) { - Array<std::string> * name_vec = mesh.getDataPointer<std::string>("physical_names", *type_it); - const Array<UInt> & tags_vec = mesh.getData<UInt>("tag_0", *type_it); - - for(UInt i(0); i < tags_vec.getSize(); i++) { - std::map<UInt, std::string>::const_iterator map_it = phys_name_map.find(tags_vec(i)); - - if(map_it == phys_name_map.end()) { - std::stringstream sstm; - sstm << tags_vec(i); - name_vec->operator()(i) = sstm.str(); - } else { - name_vec->operator()(i) = map_it->second; - } - } - } - } + this->constructPhysicalNames("tag_0",mesh); MeshUtils::fillElementToSubElementsData(mesh); } /* -------------------------------------------------------------------------- */ void MeshIOMSH::write(const std::string & filename, const Mesh & mesh) { std::ofstream outfile; const Array<Real> & nodes = mesh.getNodes(); outfile.open(filename.c_str()); outfile << "$MeshFormat" << std::endl; outfile << "2.1 0 8" << std::endl;; outfile << "$EndMeshFormat" << std::endl;; outfile << std::setprecision(std::numeric_limits<Real>::digits10); outfile << "$Nodes" << std::endl;; outfile << nodes.getSize() << std::endl;; outfile << std::uppercase; for(UInt i = 0; i < nodes.getSize(); ++i) { Int offset = i * nodes.getNbComponent(); outfile << i+1; for(UInt j = 0; j < nodes.getNbComponent(); ++j) { outfile << " " << nodes.storage()[offset + j]; } for (UInt p = nodes.getNbComponent(); p < 3; ++p) outfile << " " << 0.; outfile << std::endl;; } outfile << std::nouppercase; outfile << "$EndNodes" << std::endl;; outfile << "$Elements" << std::endl;; Mesh::type_iterator it = mesh.firstType(_all_dimensions, _not_ghost, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(_all_dimensions, _not_ghost, _ek_not_defined); Int nb_elements = 0; for(; it != end; ++it) { const Array<UInt> & connectivity = mesh.getConnectivity(*it, _not_ghost); nb_elements += connectivity.getSize(); } outfile << nb_elements << std::endl; UInt element_idx = 1; for(it = mesh.firstType(_all_dimensions, _not_ghost, _ek_not_defined); it != end; ++it) { ElementType type = *it; const Array<UInt> & connectivity = mesh.getConnectivity(type, _not_ghost); UInt * tag[2] = {NULL, NULL}; try { const Array<UInt> & data_tag_0 = mesh.getData<UInt>("tag_0", type, _not_ghost); tag[0] = data_tag_0.storage(); } catch(...) { tag[0] = NULL; } try { const Array<UInt> & data_tag_1 = mesh.getData<UInt>("tag_1", type, _not_ghost); tag[1] = data_tag_1.storage(); } catch(...) { tag[1] = NULL; } for(UInt i = 0; i < connectivity.getSize(); ++i) { UInt offset = i * connectivity.getNbComponent(); outfile << element_idx << " " << _akantu_to_msh_element_types[type] << " 2"; /// \todo write the real data in the file for (UInt t = 0; t < 2; ++t) if(tag[t]) outfile << " " << tag[t][i]; else outfile << " 0"; for(UInt j = 0; j < connectivity.getNbComponent(); ++j) { outfile << " " << connectivity.storage()[offset + j] + 1; } outfile << std::endl; element_idx++; } } outfile << "$EndElements" << std::endl;; outfile.close(); } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/io/mesh_io/mesh_io_msh.hh b/src/io/mesh_io/mesh_io_msh.hh index fa4bceab9..6f766701f 100644 --- a/src/io/mesh_io/mesh_io_msh.hh +++ b/src/io/mesh_io/mesh_io_msh.hh @@ -1,117 +1,115 @@ /** * @file mesh_io_msh.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Jun 13 2014 * * @brief Read/Write for MSH files * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_IO_MSH_HH__ #define __AKANTU_MESH_IO_MSH_HH__ /* -------------------------------------------------------------------------- */ #include "mesh_io.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class MeshIOMSH : public MeshIO { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshIOMSH(); virtual ~MeshIOMSH(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// read a mesh from the file virtual void read(const std::string & filename, Mesh & mesh); /// write a mesh to a file virtual void write(const std::string & filename, const Mesh & mesh); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// MSH element types enum MSHElementType { _msh_not_defined = 0, _msh_segment_2 = 1, // 2-node line. _msh_triangle_3 = 2, // 3-node triangle. _msh_quadrangle_4 = 3, // 4-node quadrangle. _msh_tetrahedron_4 = 4, // 4-node tetrahedron. _msh_hexahedron_8 = 5, // 8-node hexahedron. _msh_prism_1 = 6, // 6-node prism. _msh_pyramid_1 = 7, // 5-node pyramid. _msh_segment_3 = 8, // 3-node second order line _msh_triangle_6 = 9, // 6-node second order triangle _msh_quadrangle_9 = 10, // 9-node second order quadrangle _msh_tetrahedron_10 = 11, // 10-node second order tetrahedron _msh_hexahedron_27 = 12, // 27-node second order hexahedron _msh_prism_18 = 13, // 18-node second order prism _msh_pyramid_14 = 14, // 14-node second order pyramid _msh_point = 15, // 1-node point. _msh_quadrangle_8 = 16, // 8-node second order quadrangle _msh_hexahedron_20 = 17, // 20-node second order hexahedron _msh_prism_15 = 18 // 15-node second order prism }; #define MAX_NUMBER_OF_NODE_PER_ELEMENT 10 // tetrahedron of second order /// order in witch element as to be read std::map<ElementType, UInt*> _read_order; /// number of nodes per msh element std::map<MSHElementType, UInt> _msh_nodes_per_elem; /// correspondence between msh element types and akantu element types std::map<MSHElementType, ElementType> _msh_to_akantu_element_types; /// correspondence between akantu element types and msh element types std::map<ElementType, MSHElementType> _akantu_to_msh_element_types; - /// correspondance between tag_0 and physical name (if applicable) - std::map<UInt, std::string> phys_name_map; }; __END_AKANTU__ #endif /* __AKANTU_MESH_IO_MSH_HH__ */ diff --git a/src/mesh/group_manager.cc b/src/mesh/group_manager.cc index 1b3bd0114..edc078e99 100644 --- a/src/mesh/group_manager.cc +++ b/src/mesh/group_manager.cc @@ -1,1032 +1,1032 @@ /** * @file group_manager.cc * * @author Dana Christen <dana.christen@gmail.com> * @author Marco Vocialta <marco.vocialta@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author David Simon Kammer <david.kammer@epfl.ch> * * @date creation: Fri May 03 2013 * @date last modification: Tue Sep 02 2014 * * @brief Stores information about ElementGroup and NodeGroup * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "group_manager.hh" #include "mesh.hh" #include "aka_csr.hh" #include "mesh_utils.hh" #include "element_group.hh" #include "node_group.hh" #include "data_accessor.hh" #include "distributed_synchronizer.hh" /* -------------------------------------------------------------------------- */ #include <sstream> #include <algorithm> #include <iterator> #include <list> #include <queue> #include <numeric> /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ GroupManager::GroupManager(const Mesh & mesh, const ID & id, const MemoryID & mem_id) : id(id), memory_id(mem_id), mesh(mesh) { AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ GroupManager::~GroupManager() { ElementGroups::iterator eit = element_groups.begin(); ElementGroups::iterator eend = element_groups.end(); for(; eit != eend ; ++eit) delete (eit->second); NodeGroups::iterator nit = node_groups.begin(); NodeGroups::iterator nend = node_groups.end(); for(; nit != nend ; ++nit) delete (nit->second); } /* -------------------------------------------------------------------------- */ NodeGroup & GroupManager::createNodeGroup(const std::string & group_name, bool replace_group) { AKANTU_DEBUG_IN(); NodeGroups::iterator it = node_groups.find(group_name); if(it != node_groups.end()) { if (replace_group) { it->second->empty(); AKANTU_DEBUG_OUT(); return *(it->second); } else - AKANTU_EXCEPTION("Trying to create a node group that already exists:" << group_name << "_nodes"); + AKANTU_EXCEPTION("Trying to create a node group that already exists:" << group_name); } NodeGroup * node_group = new NodeGroup(group_name, id + ":" + group_name + "_node_group", memory_id); node_groups[group_name] = node_group; AKANTU_DEBUG_OUT(); return *node_group; } /* -------------------------------------------------------------------------- */ template<typename T> NodeGroup & GroupManager::createFilteredNodeGroup(const std::string & group_name, const NodeGroup & source_node_group, T & filter) { AKANTU_DEBUG_IN(); NodeGroup & node_group = this->createNodeGroup(group_name); node_group.append(source_node_group); if (T::type == FilterFunctor::_node_filter_functor) { node_group.applyNodeFilter(filter); } else { AKANTU_DEBUG_ERROR("ElementFilter cannot be applied to NodeGroup yet." << " Needs to be implemented."); } AKANTU_DEBUG_OUT(); return node_group; } /* -------------------------------------------------------------------------- */ void GroupManager::destroyNodeGroup(const std::string & group_name) { AKANTU_DEBUG_IN(); NodeGroups::iterator nit = node_groups.find(group_name); NodeGroups::iterator nend = node_groups.end(); if (nit != nend) { delete (nit->second); node_groups.erase(nit); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ElementGroup & GroupManager::createElementGroup(const std::string & group_name, UInt dimension, bool replace_group) { AKANTU_DEBUG_IN(); NodeGroup & new_node_group = createNodeGroup(group_name + "_nodes", replace_group); ElementGroups::iterator it = element_groups.find(group_name); if(it != element_groups.end()) { if (replace_group) { it->second->empty(); AKANTU_DEBUG_OUT(); return *(it->second); } else AKANTU_EXCEPTION("Trying to create a element group that already exists:" << group_name); } ElementGroup * element_group = new ElementGroup(group_name, mesh, new_node_group, dimension, id + ":" + group_name + "_element_group", memory_id); node_groups[group_name + "_nodes"] = &new_node_group; element_groups[group_name] = element_group; AKANTU_DEBUG_OUT(); return *element_group; } /* -------------------------------------------------------------------------- */ void GroupManager::destroyElementGroup(const std::string & group_name, bool destroy_node_group) { AKANTU_DEBUG_IN(); ElementGroups::iterator eit = element_groups.find(group_name); ElementGroups::iterator eend = element_groups.end(); if (eit != eend) { if (destroy_node_group) destroyNodeGroup(eit->second->getNodeGroup().getName()); delete (eit->second); element_groups.erase(eit); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GroupManager::destroyAllElementGroups(bool destroy_node_groups) { AKANTU_DEBUG_IN(); ElementGroups::iterator eit = element_groups.begin(); ElementGroups::iterator eend = element_groups.end(); for(; eit != eend ; ++eit) { if (destroy_node_groups) destroyNodeGroup(eit->second->getNodeGroup().getName()); delete (eit->second); } element_groups.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ElementGroup & GroupManager::createElementGroup(const std::string & group_name, UInt dimension, NodeGroup & node_group) { AKANTU_DEBUG_IN(); if(element_groups.find(group_name) != element_groups.end()) AKANTU_EXCEPTION("Trying to create a element group that already exists:" << group_name); ElementGroup * element_group = new ElementGroup(group_name, mesh, node_group, dimension, id + ":" + group_name + "_element_group", memory_id); element_groups[group_name] = element_group; AKANTU_DEBUG_OUT(); return *element_group; } /* -------------------------------------------------------------------------- */ template <typename T> ElementGroup & GroupManager::createFilteredElementGroup(const std::string & group_name, UInt dimension, const NodeGroup & node_group, T & filter) { AKANTU_DEBUG_IN(); ElementGroup * element_group = NULL; if (T::type == FilterFunctor::_node_filter_functor) { NodeGroup & filtered_node_group = this->createFilteredNodeGroup(group_name + "_nodes", node_group, filter); element_group = &(this->createElementGroup(group_name, dimension, filtered_node_group)); } else if (T::type == FilterFunctor::_element_filter_functor) { AKANTU_DEBUG_ERROR("Cannot handle an ElementFilter yet. Needs to be implemented."); } AKANTU_DEBUG_OUT(); return *element_group; } /* -------------------------------------------------------------------------- */ class ClusterSynchronizer : public DataAccessor { typedef std::set< std::pair<UInt, UInt> > DistantIDs; public: ClusterSynchronizer(GroupManager & group_manager, UInt element_dimension, std::string cluster_name_prefix, ElementTypeMapArray<UInt> & element_to_fragment, DistributedSynchronizer & distributed_synchronizer, UInt nb_cluster) : group_manager(group_manager), element_dimension(element_dimension), cluster_name_prefix(cluster_name_prefix), element_to_fragment(element_to_fragment), distributed_synchronizer(distributed_synchronizer), nb_cluster(nb_cluster) { } UInt synchronize() { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); UInt rank = comm.whoAmI(); UInt nb_proc = comm.getNbProc(); /// find starting index to renumber local clusters Array<UInt> nb_cluster_per_proc(nb_proc); nb_cluster_per_proc(rank) = nb_cluster; comm.allGather(nb_cluster_per_proc.storage(), 1); starting_index = std::accumulate(nb_cluster_per_proc.begin(), nb_cluster_per_proc.begin() + rank, 0); UInt global_nb_fragment = std::accumulate(nb_cluster_per_proc.begin() + rank, nb_cluster_per_proc.end(), starting_index); /// create the local to distant cluster pairs with neighbors distributed_synchronizer.computeBufferSize(*this, _gst_gm_clusters); distributed_synchronizer.asynchronousSynchronize(*this, _gst_gm_clusters); distributed_synchronizer.waitEndSynchronize(*this, _gst_gm_clusters); /// count total number of pairs Array<Int> nb_pairs(nb_proc); nb_pairs(rank) = distant_ids.size(); comm.allGather(nb_pairs.storage(), 1); UInt total_nb_pairs = std::accumulate(nb_pairs.begin(), nb_pairs.end(), 0); /// generate pairs global array UInt local_pair_index = std::accumulate(nb_pairs.storage(), nb_pairs.storage() + rank, 0); Array<UInt> total_pairs(total_nb_pairs, 2); DistantIDs::iterator ids_it = distant_ids.begin(); DistantIDs::iterator ids_end = distant_ids.end(); for (; ids_it != ids_end; ++ids_it, ++local_pair_index) { total_pairs(local_pair_index, 0) = ids_it->first; total_pairs(local_pair_index, 1) = ids_it->second; } /// communicate pairs to all processors nb_pairs *= 2; comm.allGatherV(total_pairs.storage(), nb_pairs.storage()); /// renumber clusters /// generate fragment list std::vector< std::set<UInt> > global_clusters; UInt total_nb_cluster = 0; Array<bool> is_fragment_in_cluster(global_nb_fragment, 1, false); std::queue<UInt> fragment_check_list; while (total_pairs.getSize() != 0) { /// create a new cluster ++total_nb_cluster; global_clusters.resize(total_nb_cluster); std::set<UInt> & current_cluster = global_clusters[total_nb_cluster - 1]; UInt first_fragment = total_pairs(0, 0); UInt second_fragment = total_pairs(0, 1); total_pairs.erase(0); fragment_check_list.push(first_fragment); fragment_check_list.push(second_fragment); while (!fragment_check_list.empty()) { UInt current_fragment = fragment_check_list.front(); UInt * total_pairs_end = total_pairs.storage() + total_pairs.getSize() * 2; UInt * fragment_found = std::find(total_pairs.storage(), total_pairs_end, current_fragment); if (fragment_found != total_pairs_end) { UInt position = fragment_found - total_pairs.storage(); UInt pair = position / 2; UInt other_index = (position + 1) % 2; fragment_check_list.push(total_pairs(pair, other_index)); total_pairs.erase(pair); } else { fragment_check_list.pop(); current_cluster.insert(current_fragment); is_fragment_in_cluster(current_fragment) = true; } } } /// add to FragmentToCluster all local fragments for (UInt c = 0; c < global_nb_fragment; ++c) { if (!is_fragment_in_cluster(c)) { ++total_nb_cluster; global_clusters.resize(total_nb_cluster); std::set<UInt> & current_cluster = global_clusters[total_nb_cluster - 1]; current_cluster.insert(c); } } /// reorganize element groups to match global clusters for (UInt c = 0; c < global_clusters.size(); ++c) { /// create new element group corresponding to current cluster std::stringstream sstr; sstr << cluster_name_prefix << "_" << c; ElementGroup & cluster = group_manager.createElementGroup(sstr.str(), element_dimension, true); std::set<UInt>::iterator it = global_clusters[c].begin(); std::set<UInt>::iterator end = global_clusters[c].end(); /// append to current element group all fragments that belong to /// the same cluster if they exist for (; it != end; ++it) { Int local_index = *it - starting_index; if (local_index < 0 || local_index >= Int(nb_cluster)) continue; std::stringstream tmp_sstr; tmp_sstr << "tmp_" << cluster_name_prefix << "_" << local_index; GroupManager::element_group_iterator eg_it = group_manager.element_group_find(tmp_sstr.str()); AKANTU_DEBUG_ASSERT(eg_it != group_manager.element_group_end(), "Temporary fragment \""<< tmp_sstr.str() << "\" not found"); cluster.append(*(eg_it->second)); group_manager.destroyElementGroup(tmp_sstr.str(), true); } } return total_nb_cluster; } private: /// functions for parallel communications inline UInt getNbDataForElements(const Array<Element> & elements, SynchronizationTag tag) const { if (tag == _gst_gm_clusters) return elements.getSize() * sizeof(UInt); return 0; } inline void packElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) const { if (tag != _gst_gm_clusters) return; Array<Element>::const_iterator<> el_it = elements.begin(); Array<Element>::const_iterator<> el_end = elements.end(); for (; el_it != el_end; ++el_it) { const Element & el = *el_it; /// for each element pack its global cluster index buffer << element_to_fragment(el.type, el.ghost_type)(el.element) + starting_index; } } inline void unpackElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) { if (tag != _gst_gm_clusters) return; Array<Element>::const_iterator<> el_it = elements.begin(); Array<Element>::const_iterator<> el_end = elements.end(); for (; el_it != el_end; ++el_it) { UInt distant_cluster; buffer >> distant_cluster; const Element & el = *el_it; UInt local_cluster = element_to_fragment(el.type, el.ghost_type)(el.element) + starting_index; distant_ids.insert(std::make_pair(local_cluster, distant_cluster)); } } private: GroupManager & group_manager; UInt element_dimension; std::string cluster_name_prefix; ElementTypeMapArray<UInt> & element_to_fragment; DistributedSynchronizer & distributed_synchronizer; UInt nb_cluster; DistantIDs distant_ids; UInt starting_index; }; /* -------------------------------------------------------------------------- */ /// \todo this function doesn't work in 1D UInt GroupManager::createBoundaryGroupFromGeometry() { UInt spatial_dimension = mesh.getSpatialDimension(); return createClusters(spatial_dimension - 1, "boundary"); } /* -------------------------------------------------------------------------- */ //// \todo if needed element list construction can be optimized by //// templating the filter class UInt GroupManager::createClusters(UInt element_dimension, std::string cluster_name_prefix, const GroupManager::ClusteringFilter & filter, DistributedSynchronizer * distributed_synchronizer, Mesh * mesh_facets) { AKANTU_DEBUG_IN(); UInt nb_proc = StaticCommunicator::getStaticCommunicator().getNbProc(); std::string tmp_cluster_name_prefix = cluster_name_prefix; ElementTypeMapArray<UInt> * element_to_fragment = NULL; if (nb_proc > 1 && distributed_synchronizer) { element_to_fragment = new ElementTypeMapArray<UInt>; mesh.initElementTypeMapArray(*element_to_fragment, 1, element_dimension, false, _ek_not_defined, true); tmp_cluster_name_prefix = "tmp_" + tmp_cluster_name_prefix; } /// Get facets bool mesh_facets_created = false; if (!mesh_facets && element_dimension > 0) { mesh_facets = new Mesh(mesh.getSpatialDimension(), mesh.getNodes().getID(), "mesh_facets_for_clusters"); mesh_facets->defineMeshParent(mesh); MeshUtils::buildAllFacets(mesh, *mesh_facets, element_dimension, element_dimension - 1, distributed_synchronizer); } ElementTypeMapArray<bool> seen_elements("seen_elements"); mesh.initElementTypeMapArray(seen_elements, 1, element_dimension, false, _ek_not_defined, true); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Element el; el.ghost_type = ghost_type; Mesh::type_iterator type_it = mesh.firstType(element_dimension, ghost_type, _ek_not_defined); Mesh::type_iterator type_end = mesh.lastType (element_dimension, ghost_type, _ek_not_defined); for (; type_it != type_end; ++type_it) { el.type = *type_it; el.kind = Mesh::getKind(*type_it); UInt nb_element = mesh.getNbElement(*type_it, ghost_type); Array<bool> & seen_elements_array = seen_elements(el.type, ghost_type); for (UInt e = 0; e < nb_element; ++e) { el.element = e; if (!filter(el)) seen_elements_array(e) = true; } } } Array<bool> checked_node(mesh.getNbNodes(), 1, false); UInt nb_cluster = 0; /// keep looping until all elements are seen for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Element uns_el; uns_el.ghost_type = ghost_type; Mesh::type_iterator type_it = mesh.firstType(element_dimension, ghost_type, _ek_not_defined); Mesh::type_iterator type_end = mesh.lastType(element_dimension, ghost_type, _ek_not_defined); for (; type_it != type_end; ++type_it) { uns_el.type = *type_it; Array<bool> & seen_elements_vec = seen_elements(uns_el.type, uns_el.ghost_type); for (UInt e = 0; e < seen_elements_vec.getSize(); ++e) { // skip elements that have been already seen if (seen_elements_vec(e) == true) continue; // set current element uns_el.element = e; seen_elements_vec(e) = true; /// create a new cluster std::stringstream sstr; sstr << tmp_cluster_name_prefix << "_" << nb_cluster; ElementGroup & cluster = createElementGroup(sstr.str(), element_dimension, true); ++nb_cluster; // point element are cluster by themself if(element_dimension == 0) { cluster.add(uns_el); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(uns_el.type); Vector<UInt> connect = mesh.getConnectivity(uns_el.type, uns_el.ghost_type).begin(nb_nodes_per_element)[uns_el.element]; for (UInt n = 0; n < nb_nodes_per_element; ++n) { /// add element's nodes to the cluster UInt node = connect[n]; if (!checked_node(node)) { cluster.addNode(node); checked_node(node) = true; } } continue; } std::queue<Element> element_to_add; element_to_add.push(uns_el); /// keep looping until current cluster is complete (no more /// connected elements) while(!element_to_add.empty()) { /// take first element and erase it in the queue Element el = element_to_add.front(); element_to_add.pop(); /// if parallel, store cluster index per element if (nb_proc > 1 && distributed_synchronizer) (*element_to_fragment)(el.type, el.ghost_type)(el.element) = nb_cluster - 1; /// add current element to the cluster cluster.add(el); const Array<Element> & element_to_facet = mesh_facets->getSubelementToElement(el.type, el.ghost_type); UInt nb_facet_per_element = element_to_facet.getNbComponent(); for (UInt f = 0; f < nb_facet_per_element; ++f) { const Element & facet = element_to_facet(el.element, f); if (facet == ElementNull) continue; const std::vector<Element> & connected_elements = mesh_facets->getElementToSubelement(facet.type, facet.ghost_type)(facet.element); for (UInt elem = 0; elem < connected_elements.size(); ++elem) { const Element & check_el = connected_elements[elem]; // check if this element has to be skipped if (check_el == ElementNull || check_el == el) continue; Array<bool> & seen_elements_vec_current = seen_elements(check_el.type, check_el.ghost_type); if (seen_elements_vec_current(check_el.element) == false) { seen_elements_vec_current(check_el.element) = true; element_to_add.push(check_el); } } } UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(el.type); Vector<UInt> connect = mesh.getConnectivity(el.type, el.ghost_type).begin(nb_nodes_per_element)[el.element]; for (UInt n = 0; n < nb_nodes_per_element; ++n) { /// add element's nodes to the cluster UInt node = connect[n]; if (!checked_node(node)) { cluster.addNode(node, false); checked_node(node) = true; } } } } } } if (nb_proc > 1 && distributed_synchronizer) { ClusterSynchronizer cluster_synchronizer(*this, element_dimension, cluster_name_prefix, *element_to_fragment, *distributed_synchronizer, nb_cluster); nb_cluster = cluster_synchronizer.synchronize(); delete element_to_fragment; } if (mesh_facets_created) delete mesh_facets; if(mesh.isDistributed()) this->synchronizeGroupNames(); AKANTU_DEBUG_OUT(); return nb_cluster; } /* -------------------------------------------------------------------------- */ template<typename T> void GroupManager::createGroupsFromMeshData(const std::string & dataset_name) { std::set<std::string> group_names; const ElementTypeMapArray<T> & datas = mesh.getData<T>(dataset_name); typedef typename ElementTypeMapArray<T>::type_iterator type_iterator; std::map<std::string, UInt> group_dim; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { type_iterator type_it = datas.firstType(_all_dimensions, *gt); type_iterator type_end = datas.lastType(_all_dimensions, *gt); for (; type_it != type_end; ++type_it) { const Array<T> & dataset = datas(*type_it, *gt); UInt nb_element = mesh.getNbElement(*type_it, *gt); AKANTU_DEBUG_ASSERT(dataset.getSize() == nb_element, "Not the same number of elements ("<< *type_it << ":" << *gt << ") in the map from MeshData (" << dataset.getSize() << ") " << dataset_name <<" and in the mesh (" << nb_element << ")!"); for(UInt e(0); e < nb_element; ++e) { std::stringstream sstr; sstr << dataset(e); std::string gname = sstr.str(); group_names.insert(gname); std::map<std::string, UInt>::iterator it = group_dim.find(gname); if(it == group_dim.end()) { group_dim[gname] = mesh.getSpatialDimension(*type_it); } else { it->second = std::max(it->second, mesh.getSpatialDimension(*type_it)); } } } } std::set<std::string>::iterator git = group_names.begin(); std::set<std::string>::iterator gend = group_names.end(); for (;git != gend; ++git) createElementGroup(*git, group_dim[*git]); if(mesh.isDistributed()) this->synchronizeGroupNames(); Element el; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { el.ghost_type = *gt; type_iterator type_it = datas.firstType(_all_dimensions, *gt); type_iterator type_end = datas.lastType(_all_dimensions, *gt); for (; type_it != type_end; ++type_it) { el.type = *type_it; const Array<T> & dataset = datas(*type_it, *gt); UInt nb_element = mesh.getNbElement(*type_it, *gt); AKANTU_DEBUG_ASSERT(dataset.getSize() == nb_element, "Not the same number of elements in the map from MeshData and in the mesh!"); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(el.type); Array<UInt>::const_iterator< Vector<UInt> > cit = mesh.getConnectivity(*type_it, *gt).begin(nb_nodes_per_element); for(UInt e(0); e < nb_element; ++e, ++cit) { el.element = e; std::stringstream sstr; sstr << dataset(e); ElementGroup & group = getElementGroup(sstr.str()); group.add(el, false, false); const Vector<UInt> & connect = *cit; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connect[n]; group.addNode(node, false); } } } } git = group_names.begin(); for (;git != gend; ++git) { getElementGroup(*git).optimize(); } } template void GroupManager::createGroupsFromMeshData<std::string>(const std::string & dataset_name); template void GroupManager::createGroupsFromMeshData<UInt>(const std::string & dataset_name); /* -------------------------------------------------------------------------- */ void GroupManager::createElementGroupFromNodeGroup(const std::string & name, const std::string & node_group_name, UInt dimension) { NodeGroup & node_group = getNodeGroup(node_group_name); ElementGroup & group = createElementGroup(name, dimension, node_group); CSR<Element> node_to_elem; MeshUtils::buildNode2Elements(mesh, node_to_elem, dimension); std::set<Element> seen; Array<UInt>::const_iterator<> itn = node_group.begin(); Array<UInt>::const_iterator<> endn = node_group.end(); for (;itn != endn; ++itn) { CSR<Element>::iterator ite = node_to_elem.begin(*itn); CSR<Element>::iterator ende = node_to_elem.end(*itn); for (;ite != ende; ++ite) { const Element & elem = *ite; if(dimension != _all_dimensions && dimension != Mesh::getSpatialDimension(elem.type)) continue; if(seen.find(elem) != seen.end()) continue; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(elem.type); Array<UInt>::const_iterator< Vector<UInt> > conn_it = mesh.getConnectivity(elem.type, elem.ghost_type).begin(nb_nodes_per_element); const Vector<UInt> & conn = conn_it[elem.element]; UInt count = 0; for (UInt n = 0; n < conn.size(); ++n) { count += (node_group.getNodes().find(conn(n)) != -1 ? 1 : 0); } if(count == nb_nodes_per_element) group.add(elem); seen.insert(elem); } } group.optimize(); } /* -------------------------------------------------------------------------- */ void GroupManager::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "GroupManager [" << std::endl; std::set<std::string> node_group_seen; for(const_element_group_iterator it(element_group_begin()); it != element_group_end(); ++it) { it->second->printself(stream, indent + 1); node_group_seen.insert(it->second->getNodeGroup().getName()); } for(const_node_group_iterator it(node_group_begin()); it != node_group_end(); ++it) { if(node_group_seen.find(it->second->getName()) == node_group_seen.end()) it->second->printself(stream, indent + 1); } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ UInt GroupManager::getNbElementGroups(UInt dimension) const { if(dimension == _all_dimensions) return element_groups.size(); ElementGroups::const_iterator it = element_groups.begin(); ElementGroups::const_iterator end = element_groups.end(); UInt count = 0; for(;it != end; ++it) count += (it->second->getDimension() == dimension); return count; } /* -------------------------------------------------------------------------- */ void GroupManager::checkAndAddGroups(CommunicationBuffer & buffer) { AKANTU_DEBUG_IN(); UInt nb_node_group; buffer >> nb_node_group; AKANTU_DEBUG_INFO("Received " << nb_node_group << " node group names"); for (UInt ng = 0; ng < nb_node_group; ++ng) { std::string node_group_name; buffer >> node_group_name; if(node_groups.find(node_group_name) == node_groups.end()) { this->createNodeGroup(node_group_name); } AKANTU_DEBUG_INFO("Received node goup name: " << node_group_name); } UInt nb_element_group; buffer >> nb_element_group; AKANTU_DEBUG_INFO("Received " << nb_element_group << " element group names"); for (UInt eg = 0; eg < nb_element_group; ++eg) { std::string element_group_name; buffer >> element_group_name; std::string node_group_name; buffer >> node_group_name; UInt dim; buffer >> dim; AKANTU_DEBUG_INFO("Received element group name: " << element_group_name << " corresponding to a " << Int(dim) << "D group with node group " << node_group_name); NodeGroup & node_group = *node_groups[node_group_name]; if(element_groups.find(element_group_name) == element_groups.end()) { this->createElementGroup(element_group_name, dim, node_group); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GroupManager::fillBufferWithGroupNames(DynamicCommunicationBuffer & comm_buffer) const { AKANTU_DEBUG_IN(); // packing node group names; UInt nb_groups = this->node_groups.size(); comm_buffer << nb_groups; AKANTU_DEBUG_INFO("Sending " << nb_groups << " node group names"); NodeGroups::const_iterator nnames_it = node_groups.begin(); NodeGroups::const_iterator nnames_end = node_groups.end(); for (; nnames_it != nnames_end; ++nnames_it) { std::string node_group_name = nnames_it->first; comm_buffer << node_group_name; AKANTU_DEBUG_INFO("Sending node goupe name: " << node_group_name); } // packing element group names with there associated node group name nb_groups = this->element_groups.size(); comm_buffer << nb_groups; AKANTU_DEBUG_INFO("Sending " << nb_groups << " element group names"); ElementGroups::const_iterator gnames_it = this->element_groups.begin(); ElementGroups::const_iterator gnames_end = this->element_groups.end(); for (; gnames_it != gnames_end; ++gnames_it) { ElementGroup & element_group = *(gnames_it->second); std::string element_group_name = gnames_it->first; std::string node_group_name = element_group.getNodeGroup().getName(); UInt dim = element_group.getDimension(); comm_buffer << element_group_name; comm_buffer << node_group_name; comm_buffer << dim; AKANTU_DEBUG_INFO("Sending element group name: " << element_group_name << " corresponding to a " << Int(dim) << "D group with the node group " << node_group_name); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GroupManager::synchronizeGroupNames() { AKANTU_DEBUG_IN(); StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); UInt nb_proc = comm.getNbProc(); UInt my_rank = comm.whoAmI(); if(nb_proc == 1) return; if(my_rank == 0) { for (UInt p = 1; p < nb_proc; ++p) { CommunicationStatus status; comm.probe<char>(p, p, status); AKANTU_DEBUG_INFO("Got " << printMemorySize<char>(status.getSize()) << " from proc " << p); CommunicationBuffer recv_buffer(status.getSize()); comm.receive(recv_buffer.storage(), recv_buffer.getSize(), p, p); this->checkAndAddGroups(recv_buffer); } DynamicCommunicationBuffer comm_buffer; this->fillBufferWithGroupNames(comm_buffer); UInt buffer_size = comm_buffer.getSize(); comm.broadcast(&buffer_size, 1, 0); AKANTU_DEBUG_INFO("Initiating broadcast with " << printMemorySize<char>(comm_buffer.getSize())); comm.broadcast(comm_buffer.storage(), buffer_size, 0); } else { DynamicCommunicationBuffer comm_buffer; this->fillBufferWithGroupNames(comm_buffer); AKANTU_DEBUG_INFO("Sending " << printMemorySize<char>(comm_buffer.getSize()) << " to proc " << 0); comm.send(comm_buffer.storage(), comm_buffer.getSize(), 0, my_rank); UInt buffer_size = 0; comm.broadcast(&buffer_size, 1, 0); AKANTU_DEBUG_INFO("Receiving broadcast with " << printMemorySize<char>(comm_buffer.getSize())); CommunicationBuffer recv_buffer(buffer_size); comm.broadcast(recv_buffer.storage(), recv_buffer.getSize(), 0); this->checkAndAddGroups(recv_buffer); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ const ElementGroup & GroupManager::getElementGroup(const std::string & name) const { const_element_group_iterator it = element_group_find(name); if(it == element_group_end()) { AKANTU_EXCEPTION("There are no element groups named " << name << " associated to the group manager: " << id); } return *(it->second); } /* -------------------------------------------------------------------------- */ ElementGroup & GroupManager::getElementGroup(const std::string & name) { element_group_iterator it = element_group_find(name); if(it == element_group_end()) { AKANTU_EXCEPTION("There are no element groups named " << name << " associated to the group manager: " << id); } return *(it->second); } /* -------------------------------------------------------------------------- */ const NodeGroup & GroupManager::getNodeGroup(const std::string & name) const { const_node_group_iterator it = node_group_find(name); if(it == node_group_end()) { AKANTU_EXCEPTION("There are no node groups named " << name << " associated to the group manager: " << id); } return *(it->second); } /* -------------------------------------------------------------------------- */ NodeGroup & GroupManager::getNodeGroup(const std::string & name) { node_group_iterator it = node_group_find(name); if(it == node_group_end()) { AKANTU_EXCEPTION("There are no node groups named " << name << " associated to the group manager: " << id); } return *(it->second); } __END_AKANTU__ diff --git a/src/mesh/node_group.hh b/src/mesh/node_group.hh index 07fc695ad..348be708d 100644 --- a/src/mesh/node_group.hh +++ b/src/mesh/node_group.hh @@ -1,126 +1,128 @@ /** * @file node_group.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Mon Jun 09 2014 * * @brief Node group definition * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_array.hh" #include "aka_memory.hh" #include "mesh_filter.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NODE_GROUP_HH__ #define __AKANTU_NODE_GROUP_HH__ __BEGIN_AKANTU__ class NodeGroup : Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NodeGroup(const std::string & name, const std::string & id = "node_group", const MemoryID & memory_id = 0); virtual ~NodeGroup(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: typedef Array<UInt>::const_iterator<UInt> const_node_iterator; /// empty the node group void empty(); /// iterator to the beginning of the node group inline const_node_iterator begin() const; /// iterator to the end of the node group inline const_node_iterator end() const; /// add a node and give the local position through an iterator inline const_node_iterator add(UInt node, bool check_for_duplicate = true); /// remove duplicated nodes void optimize(); /// append a group to current one void append(const NodeGroup & other_group); /// apply a filter on current node group template <typename T> void applyNodeFilter(T & filter); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO_NOT_CONST(Nodes, node_group, Array<UInt> &); AKANTU_GET_MACRO(Nodes, node_group, const Array<UInt> &); AKANTU_GET_MACRO(Name, name, const std::string &); /// give the number of nodes in the current group inline UInt getSize() const; + UInt * storage(){return node_group.storage();}; + /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// name of the group std::string name; /// list of nodes in the group Array<UInt> & node_group; }; /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const NodeGroup & _this) { _this.printself(stream); return stream; } __END_AKANTU__ /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "node_group_inline_impl.cc" #endif /* __AKANTU_NODE_GROUP_HH__ */ diff --git a/src/model/solid_mechanics/embedded_interface_model.cc b/src/model/solid_mechanics/embedded_interface_model.cc index b0744fe05..351ec4d15 100644 --- a/src/model/solid_mechanics/embedded_interface_model.cc +++ b/src/model/solid_mechanics/embedded_interface_model.cc @@ -1,185 +1,160 @@ /** * @file embedded_interface_model.cc * * @author Lucas Frérot <lucas.frerot@epfl.ch> * * @date creation: Mon Mar 9 2015 * @date last modification: Mon Mar 9 2015 * * @brief Model of Solid Mechanics with embedded interfaces * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "embedded_interface_model.hh" #include "material_reinforcement.hh" #ifdef AKANTU_USE_IOHELPER # include "dumper_paraview.hh" # include "dumpable_inline_impl.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ -const EmbeddedInterfaceModelOptions default_embedded_interface_model_options(_explicit_lumped_mass, false, false); +const EmbeddedInterfaceModelOptions + default_embedded_interface_model_options(_explicit_lumped_mass, false, false); EmbeddedInterfaceModel::EmbeddedInterfaceModel(Mesh & mesh, Mesh & primitive_mesh, UInt spatial_dimension, const ID & id, const MemoryID & memory_id) : SolidMechanicsModel(mesh, spatial_dimension, id, memory_id), + intersector(mesh, primitive_mesh), interface_mesh(NULL), primitive_mesh(primitive_mesh), - interface_material_selector(NULL), - intersector(mesh, primitive_mesh) + interface_material_selector(NULL) { // This pointer should be deleted by ~SolidMechanicsModel() - MaterialSelector * mat_sel_pointer = new MeshDataMaterialSelector<std::string>("physical_names", *this); + MaterialSelector * mat_sel_pointer = + new MeshDataMaterialSelector<std::string>("physical_names", *this); + this->setMaterialSelector(*mat_sel_pointer); + + interface_mesh = &(intersector.getInterfaceMesh()); + registerFEEngineObject<MyFEEngineType>("EmbeddedInterfaceFEEngine", *interface_mesh, 1); } EmbeddedInterfaceModel::~EmbeddedInterfaceModel() { delete interface_material_selector; } void EmbeddedInterfaceModel::initFull(const ModelOptions & options) { const EmbeddedInterfaceModelOptions & eim_options = dynamic_cast<const EmbeddedInterfaceModelOptions &>(options); // We don't want to initiate materials before shape functions are initialized SolidMechanicsModelOptions dummy_options(eim_options.analysis_method, true); - interface_mesh = &(intersector.getInterfaceMesh()); - registerFEEngineObject<MyFEEngineType>("EmbeddedInterfaceFEEngine", *interface_mesh, 1); - - SolidMechanicsModel::initFull(dummy_options); - if (!eim_options.no_init_intersections) intersector.constructData(); FEEngine & engine = getFEEngine("EmbeddedInterfaceFEEngine"); engine.initShapeFunctions(_not_ghost); engine.initShapeFunctions(_ghost); + SolidMechanicsModel::initFull(dummy_options); + this->initMaterials(); #if defined(AKANTU_USE_IOHELPER) this->mesh.registerDumper<DumperParaview>("reinforcement", id); this->mesh.addDumpMeshToDumper("reinforcement", *interface_mesh, 1, _not_ghost, _ek_regular); #endif } void EmbeddedInterfaceModel::initMaterials() { Element element; delete interface_material_selector; - interface_material_selector = new InterfaceMeshDataMaterialSelector<std::string>("physical_names", *this); + interface_material_selector = + new InterfaceMeshDataMaterialSelector<std::string>("physical_names", *this); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { element.ghost_type = *gt; Mesh::type_iterator it = interface_mesh->firstType(1, *gt); Mesh::type_iterator end = interface_mesh->lastType(1, *gt); for (; it != end ; ++it) { UInt nb_element = interface_mesh->getNbElement(*it, *gt); element.type = *it; Array<UInt> & mat_indexes = material_index.alloc(nb_element, 1, *it, *gt); for (UInt el = 0 ; el < nb_element ; el++) { element.element = el; UInt mat_index = (*interface_material_selector)(element); AKANTU_DEBUG_ASSERT(mat_index < materials.size(), "The material selector returned an index that does not exist"); mat_indexes(element.element) = mat_index; materials.at(mat_index)->addElement(*it, el, *gt); } } } SolidMechanicsModel::initMaterials(); } -ElementTypeMap<UInt> EmbeddedInterfaceModel::getInternalDataPerElem(const std::string & field_name, - const ElementKind & kind) { - if (!(this->isInternal(field_name,kind))) AKANTU_EXCEPTION("unknown internal " << field_name); - - for (UInt m = 0; m < materials.size() ; ++m) { - if (materials[m]->isInternal(field_name, kind)) { - Material * mat = NULL; - - switch(this->spatial_dimension) { - case 1: - mat = dynamic_cast<MaterialReinforcement<1> *>(materials[m]); - break; - - case 2: - mat = dynamic_cast<MaterialReinforcement<2> *>(materials[m]); - break; - - case 3: - mat = dynamic_cast<MaterialReinforcement<3> *>(materials[m]); - break; - } - - if (mat == NULL && field_name != "stress_embedded") - return materials[m]->getInternalDataPerElem(field_name,kind); - else if (mat != NULL && field_name == "stress_embedded") - return mat->getInternalDataPerElem(field_name, kind, "EmbeddedInterfaceFEEngine"); - } - } - - return ElementTypeMap<UInt>(); -} - void EmbeddedInterfaceModel::addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name, const ElementKind & element_kind, bool padding_flag) { #ifdef AKANTU_USE_IOHELPER dumper::Field * field = NULL; - if (field_id == "stress_embedded") + if (dumper_name == "reinforcement" && + (field_id == "stress_embedded" || + field_id == "inelastic_strain" || + field_id == "material_index")) field = this->createElementalField(field_id, group_name, padding_flag, 1, element_kind); else SolidMechanicsModel::addDumpGroupFieldToDumper(dumper_name, field_id, group_name, element_kind, padding_flag); if (field) { DumperIOHelper & dumper = mesh.getGroupDumper(dumper_name,group_name); Model::addDumpGroupFieldToDumper(field_id,field,dumper); } #endif } __END_AKANTU__ diff --git a/src/model/solid_mechanics/embedded_interface_model.hh b/src/model/solid_mechanics/embedded_interface_model.hh index ceafa6ffe..bfaed5e8f 100644 --- a/src/model/solid_mechanics/embedded_interface_model.hh +++ b/src/model/solid_mechanics/embedded_interface_model.hh @@ -1,160 +1,153 @@ /** * @file embedded_interface_model.hh * * @author Lucas Frérot <lucas.frerot@epfl.ch> * * @date creation: Mon Mar 9 2015 * @date last modification: Mon Mar 9 2015 * * @brief Model of Solid Mechanics with embedded interfaces * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_EMBEDDED_INTERFACE_MODEL_HH__ #define __AKANTU_EMBEDDED_INTERFACE_MODEL_HH__ #include "aka_common.hh" #include "solid_mechanics_model.hh" #include "mesh.hh" #include "embedded_interface_intersector.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /// Options for the EmbeddedInterfaceModel struct EmbeddedInterfaceModelOptions : SolidMechanicsModelOptions { EmbeddedInterfaceModelOptions(AnalysisMethod analysis_method = _explicit_lumped_mass, bool no_init_intersections = false, bool no_init_materials = false): SolidMechanicsModelOptions(analysis_method, no_init_materials), no_init_intersections(no_init_intersections) {} bool no_init_intersections; }; extern const EmbeddedInterfaceModelOptions default_embedded_interface_model_options; /** * @brief Solid mechanics model using the embedded model. * * This SolidMechanicsModel subclass implements the embedded model, * a method used to represent 1D elements in a finite elements model * (eg. reinforcements in concrete). * * In addition to the SolidMechanicsModel properties, this model has * a mesh of the 1D elements embedded in the model, and an instance of the * EmbeddedInterfaceIntersector class for the computation of the intersections of the * 1D elements with the background (bulk) mesh. * * @see MaterialReinforcement */ class EmbeddedInterfaceModel : public SolidMechanicsModel { typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_regular> MyFEEngineType; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /** * @brief Constructor * * @param mesh main mesh (concrete) * @param primitive_mesh mesh of the embedded reinforcement */ EmbeddedInterfaceModel(Mesh & mesh, Mesh & primitive_mesh, UInt spatial_dimension = _all_dimensions, const ID & id = "embedded_interface_model", const MemoryID & memory_id = 0); /// Destructor virtual ~EmbeddedInterfaceModel(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// Initialise the model virtual void initFull(const ModelOptions & options = default_embedded_interface_model_options); /// Initialise the materials virtual void initMaterials(); -#ifndef SWIG - /// give the amount of data per element - ElementTypeMap<UInt> getInternalDataPerElem(const std::string & field_name, - const ElementKind & kind); -#endif - virtual void addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name, const ElementKind & element_kind, bool padding_flag); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get interface mesh AKANTU_GET_MACRO(InterfaceMesh, *interface_mesh, Mesh &); /// get associated elements AKANTU_GET_MACRO_BY_ELEMENT_TYPE(InterfaceAssociatedElements, interface_mesh->getData<Element>("associated_element"), Element); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: + /// Intersector object to build the interface mesh + EmbeddedInterfaceIntersector intersector; + /// Interface mesh (weak reference) Mesh * interface_mesh; /// Mesh used to create the CGAL primitives for intersections Mesh & primitive_mesh; /// Material selector for interface MaterialSelector * interface_material_selector; - - /// Intersector object to build the interface mesh - EmbeddedInterfaceIntersector intersector; - }; template<typename T> class InterfaceMeshDataMaterialSelector : public ElementDataMaterialSelector<T> { public: InterfaceMeshDataMaterialSelector(const std::string & name, const EmbeddedInterfaceModel & model, UInt first_index = 1) : ElementDataMaterialSelector<T>(model.getInterfaceMesh().getData<T>(name), model, first_index) {} }; __END_AKANTU__ #endif // __AKANTU_EMBEDDED_INTERFACE_MODEL_HH__ diff --git a/src/model/solid_mechanics/material.cc b/src/model/solid_mechanics/material.cc index 2a3041210..d40ae7712 100644 --- a/src/model/solid_mechanics/material.cc +++ b/src/model/solid_mechanics/material.cc @@ -1,1667 +1,1710 @@ /** * @file material.cc * * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #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), finite_deformation(false), name(""), model(&model), spatial_dimension(this->model->getSpatialDimension()), element_filter("element_filter", id, this->memory_id), stress("stress", *this), eigenstrain("eigenstrain", *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); - registerParam("rho" , rho , 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"); + this->initialize(); + AKANTU_DEBUG_OUT(); +} - /// allocate gradu stress for local elements - eigenstrain.initialize(spatial_dimension * spatial_dimension); - gradu.initialize(spatial_dimension * spatial_dimension); - stress.initialize(spatial_dimension * spatial_dimension); +/* -------------------------------------------------------------------------- */ +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), + 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), + eigenstrain("eignestrain", *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) { - model.registerEventHandler(*this); + 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 , 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 + eigenstrain.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<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->resize(); for (std::map<ID, InternalField<UInt> *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->resize(); is_init = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::savePreviousState() { AKANTU_DEBUG_IN(); for (std::map<ID, InternalField<Real> *>::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<Real> & residual = const_cast<Array<Real> &>(model->getResidual()); Mesh & mesh = model->getFEEngine().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) { const Array<Real> & shapes_derivatives = model->getFEEngine().getShapesDerivatives(*it, ghost_type); Array<UInt> & elem_filter = element_filter(*it, ghost_type); UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); UInt nb_quadrature_points = model->getFEEngine().getNbQuadraturePoints(*it, ghost_type); UInt nb_element = elem_filter.getSize(); /// compute @f$\sigma \frac{\partial \varphi}{\partial X}@f$ by @f$\mathbf{B}^t \mathbf{\sigma}_q@f$ Array<Real> * sigma_dphi_dx = new Array<Real>(nb_element*nb_quadrature_points, size_of_shapes_derivatives, "sigma_x_dphi_/_dX"); Array<Real> * shapesd_filtered = new Array<Real>(0, size_of_shapes_derivatives, "filtered shapesd"); FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered, *it, ghost_type, elem_filter); Array<Real> & stress_vect = stress(*it, ghost_type); Array<Real>::matrix_iterator sigma = stress_vect.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator B = shapesd_filtered->begin(spatial_dimension, nb_nodes_per_element); Array<Real>::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<false,false>(*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<Real> * int_sigma_dphi_dx = new Array<Real>(nb_element, nb_nodes_per_element * spatial_dimension, "int_sigma_x_dphi_/_dX"); model->getFEEngine().integrate(*sigma_dphi_dx, *int_sigma_dphi_dx, size_of_shapes_derivatives, *it, ghost_type, elem_filter); delete sigma_dphi_dx; /// assemble model->getFEEngine().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 = model->getFEEngine().getMesh().firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = model->getFEEngine().getMesh().lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { Array<UInt> & elem_filter = element_filter(*it, ghost_type); Array<Real> & gradu_vect = gradu(*it, ghost_type); /// compute @f$\nabla u@f$ model->getFEEngine().gradientOnQuadraturePoints(model->getDisplacement(), gradu_vect, spatial_dimension, *it, ghost_type, elem_filter); gradu_vect -= eigenstrain(*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 = model->getFEEngine().getMesh().firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = model->getFEEngine().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<UInt dim> void Material::computeCauchyStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real>::matrix_iterator gradu_it = this->gradu(el_type, ghost_type).begin(dim, dim); Array<Real>::matrix_iterator gradu_end = this->gradu(el_type, ghost_type).end(dim, dim); Array<Real>::matrix_iterator piola_it = this->piola_kirchhoff_2(el_type, ghost_type).begin(dim, dim); Array<Real>::matrix_iterator stress_it = this->stress(el_type, ghost_type).begin(dim, dim); Matrix<Real> F_tensor(dim, dim); for (; gradu_it != gradu_end; ++gradu_it, ++piola_it, ++stress_it) { Matrix<Real> & grad_u = *gradu_it; Matrix<Real> & piola = *piola_it; Matrix<Real> & sigma = *stress_it; gradUToF<dim > (grad_u, F_tensor); this->computeCauchyStressOnQuad<dim >(F_tensor, piola, sigma); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::setToSteadyState(GhostType ghost_type) { AKANTU_DEBUG_IN(); const Array<Real> & displacement = model->getDisplacement(); //resizeInternalArray(gradu); UInt spatial_dimension = model->getSpatialDimension(); Mesh::type_iterator it = model->getFEEngine().getMesh().firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = model->getFEEngine().getMesh().lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { Array<UInt> & elem_filter = element_filter(*it, ghost_type); Array<Real> & gradu_vect = gradu(*it, ghost_type); /// compute @f$\nabla u@f$ model->getFEEngine().gradientOnQuadraturePoints(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<UInt dim> void Material::assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); SparseMatrix & K = const_cast<SparseMatrix &>(model->getStiffnessMatrix()); const Array<Real> & shapes_derivatives = model->getFEEngine().getShapesDerivatives(type, ghost_type); Array<UInt> & elem_filter = element_filter(type, ghost_type); Array<Real> & gradu_vect = gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = model->getFEEngine().getNbQuadraturePoints(type, ghost_type); gradu_vect.resize(nb_quadrature_points * nb_element); model->getFEEngine().gradientOnQuadraturePoints(model->getDisplacement(), gradu_vect, dim, type, ghost_type, elem_filter); UInt tangent_size = getTangentStiffnessVoigtSize(dim); Array<Real> * tangent_stiffness_matrix = new Array<Real>(nb_element*nb_quadrature_points, tangent_size * tangent_size, "tangent_stiffness_matrix"); tangent_stiffness_matrix->clear(); computeTangentModuli(type, *tangent_stiffness_matrix, ghost_type); Array<Real> * shapesd_filtered = new Array<Real>(0, dim * nb_nodes_per_element, "filtered shapesd"); FEEngine::filterElementalData(model->getFEEngine().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<Real> * bt_d_b = new Array<Real>(nb_element * nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B"); Matrix<Real> B(tangent_size, dim * nb_nodes_per_element); Matrix<Real> Bt_D(dim * nb_nodes_per_element, tangent_size); Array<Real>::matrix_iterator shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element); Array<Real>::matrix_iterator Bt_D_B_it = bt_d_b->begin(dim*nb_nodes_per_element, dim*nb_nodes_per_element); Array<Real>::matrix_iterator D_it = tangent_stiffness_matrix->begin(tangent_size, tangent_size); Array<Real>::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<Real> & D = *D_it; Matrix<Real> & Bt_D_B = *Bt_D_B_it; VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix( *shapes_derivatives_filtered_it, B, nb_nodes_per_element); Bt_D.mul<true, false>(B, D); Bt_D_B.mul<false, false>(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<Real> * K_e = new Array<Real>(nb_element, bt_d_b_size * bt_d_b_size, "K_e"); model->getFEEngine().integrate(*bt_d_b, *K_e, bt_d_b_size * bt_d_b_size, type, ghost_type, elem_filter); delete bt_d_b; model->getFEEngine().assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, elem_filter); delete K_e; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void Material::assembleStiffnessMatrixNL(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); SparseMatrix & K = const_cast<SparseMatrix &> (model->getStiffnessMatrix()); const Array<Real> & shapes_derivatives = model->getFEEngine().getShapesDerivatives(type, ghost_type); Array<UInt> & elem_filter = element_filter(type, ghost_type); //Array<Real> & 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 = model->getFEEngine().getNbQuadraturePoints(type, ghost_type); //gradu_vect.resize(nb_quadrature_points * nb_element); // model->getFEEngine().gradientOnQuadraturePoints(model->getIncrement(), gradu_vect, // dim, type, ghost_type, &elem_filter); Array<Real> * shapes_derivatives_filtered = new Array<Real > (nb_element * nb_quadrature_points, dim * nb_nodes_per_element, "shapes derivatives filtered"); Array<Real>::const_matrix_iterator shapes_derivatives_it = shapes_derivatives.begin(spatial_dimension, nb_nodes_per_element); Array<Real>::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<Real> * bt_s_b = new Array<Real > (nb_element * nb_quadrature_points, bt_s_b_size * bt_s_b_size, "B^t*D*B"); UInt piola_matrix_size = getCauchyStressMatrixSize(dim); Matrix<Real> B(piola_matrix_size, bt_s_b_size); Matrix<Real> Bt_S(bt_s_b_size, piola_matrix_size); Matrix<Real> S(piola_matrix_size, piola_matrix_size); shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, nb_nodes_per_element); Array<Real>::matrix_iterator Bt_S_B_it = bt_s_b->begin(bt_s_b_size, bt_s_b_size); Array<Real>::matrix_iterator Bt_S_B_end = bt_s_b->end(bt_s_b_size, bt_s_b_size); Array<Real>::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<Real> & Bt_S_B = *Bt_S_B_it; Matrix<Real> & Piola_kirchhoff_matrix = *piola_it; setCauchyStressMatrix< dim >(Piola_kirchhoff_matrix, S); VoigtHelper<dim>::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<Real> * K_e = new Array<Real > (nb_element, bt_s_b_size * bt_s_b_size, "K_e"); model->getFEEngine().integrate(*bt_s_b, *K_e, bt_s_b_size * bt_s_b_size, type, ghost_type, elem_filter); delete bt_s_b; model->getFEEngine().assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, elem_filter); delete K_e; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void Material::assembleStiffnessMatrixL2(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); SparseMatrix & K = const_cast<SparseMatrix &> (model->getStiffnessMatrix()); const Array<Real> & shapes_derivatives = model->getFEEngine().getShapesDerivatives(type, ghost_type); Array<UInt> & elem_filter = element_filter(type, ghost_type); Array<Real> & gradu_vect = gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = model->getFEEngine().getNbQuadraturePoints(type, ghost_type); gradu_vect.resize(nb_quadrature_points * nb_element); model->getFEEngine().gradientOnQuadraturePoints(model->getDisplacement(), gradu_vect, dim, type, ghost_type, elem_filter); UInt tangent_size = getTangentStiffnessVoigtSize(dim); Array<Real> * tangent_stiffness_matrix = new Array<Real > (nb_element*nb_quadrature_points, tangent_size * tangent_size, "tangent_stiffness_matrix"); tangent_stiffness_matrix->clear(); computeTangentModuli(type, *tangent_stiffness_matrix, ghost_type); Array<Real> * shapes_derivatives_filtered = new Array<Real > (nb_element * nb_quadrature_points, dim * nb_nodes_per_element, "shapes derivatives filtered"); Array<Real>::const_matrix_iterator shapes_derivatives_it = shapes_derivatives.begin(spatial_dimension, nb_nodes_per_element); Array<Real>::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<Real> * bt_d_b = new Array<Real > (nb_element * nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B"); Matrix<Real> B(tangent_size, dim * nb_nodes_per_element); Matrix<Real> B2(tangent_size, dim * nb_nodes_per_element); Matrix<Real> Bt_D(dim * nb_nodes_per_element, tangent_size); shapes_derivatives_filtered_it = shapes_derivatives_filtered->begin(spatial_dimension, nb_nodes_per_element); Array<Real>::matrix_iterator Bt_D_B_it = bt_d_b->begin(dim*nb_nodes_per_element, dim * nb_nodes_per_element); Array<Real>::matrix_iterator grad_u_it = gradu_vect.begin(dim, dim); Array<Real>::matrix_iterator D_it = tangent_stiffness_matrix->begin(tangent_size, tangent_size); Array<Real>::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<Real> & grad_u = *grad_u_it; Matrix<Real> & D = *D_it; Matrix<Real> & Bt_D_B = *Bt_D_B_it; //transferBMatrixToBL1<dim > (*shapes_derivatives_filtered_it, B, nb_nodes_per_element); VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(*shapes_derivatives_filtered_it, B, nb_nodes_per_element); VoigtHelper<dim>::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<Real> * K_e = new Array<Real > (nb_element, bt_d_b_size * bt_d_b_size, "K_e"); model->getFEEngine().integrate(*bt_d_b, *K_e, bt_d_b_size * bt_d_b_size, type, ghost_type, elem_filter); delete bt_d_b; model->getFEEngine().assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, elem_filter); delete K_e; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void Material::assembleResidual(GhostType ghost_type){ AKANTU_DEBUG_IN(); Array<Real> & residual = const_cast<Array<Real> &> (model->getResidual()); Mesh & mesh = model->getFEEngine().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<Real> & shapes_derivatives = model->getFEEngine().getShapesDerivatives(*it, ghost_type); Array<UInt> & elem_filter = element_filter(*it, ghost_type); 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 = model->getFEEngine().getNbQuadraturePoints(*it, ghost_type); Array<Real> * shapesd_filtered = new Array<Real>(0, size_of_shapes_derivatives, "filtered shapesd"); FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered, *it, ghost_type, elem_filter); Array<Real>::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<Real> * bt_s = new Array<Real > (nb_element * nb_quadrature_points, bt_s_size, "B^t*S"); Array<Real>::matrix_iterator grad_u_it = this->gradu(*it, ghost_type).begin(dim, dim); Array<Real>::matrix_iterator grad_u_end = this->gradu(*it, ghost_type).end(dim, dim); Array<Real>::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<Real>::matrix_iterator bt_s_it = bt_s->begin(bt_s_size, 1); Matrix<Real> S_vect(stress_size, 1); Matrix<Real> B_tensor(stress_size, bt_s_size); Matrix<Real> 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<Real> & grad_u = *grad_u_it; Matrix<Real> & r_it = *bt_s_it; Matrix<Real> & S_it = *stress_it; SetCauchyStressArray <dim> (S_it, S_vect); VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(*shapes_derivatives_filtered_it, B_tensor, nb_nodes_per_element); VoigtHelper<dim>::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<Real> * r_e = new Array<Real > (nb_element, bt_s_size, "r_e"); model->getFEEngine().integrate(*bt_s, *r_e, bt_s_size, *it, ghost_type, elem_filter); delete bt_s; model->getFEEngine().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<UInt dim> void Material::computeAllStressesFromTangentModuli(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); const Array<Real> & shapes_derivatives = model->getFEEngine().getShapesDerivatives(type, ghost_type); Array<UInt> & elem_filter = element_filter(type, ghost_type); Array<Real> & gradu_vect = gradu(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = model->getFEEngine().getNbQuadraturePoints(type, ghost_type); gradu_vect.resize(nb_quadrature_points * nb_element); Array<Real> & disp = model->getDisplacement(); model->getFEEngine().gradientOnQuadraturePoints(disp, gradu_vect, dim, type, ghost_type, elem_filter); UInt tangent_moduli_size = getTangentStiffnessVoigtSize(dim); Array<Real> * tangent_moduli_tensors = new Array<Real>(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<Real> * shapesd_filtered = new Array<Real>(0, dim* nb_nodes_per_element, "filtered shapesd"); FEEngine::filterElementalData(model->getFEEngine().getMesh(), shapes_derivatives, *shapesd_filtered, type, ghost_type, elem_filter); Array<Real> filtered_u(nb_element, nb_nodes_per_element * spatial_dimension); FEEngine::extractNodalToElementField(model->getFEEngine().getMesh(), disp, filtered_u, type, ghost_type, elem_filter); /// compute @f$\mathbf{D} \mathbf{B} \mathbf{u}@f$ Array<Real>::matrix_iterator shapes_derivatives_filtered_it = shapesd_filtered->begin(dim, nb_nodes_per_element); Array<Real>::matrix_iterator D_it = tangent_moduli_tensors->begin(tangent_moduli_size, tangent_moduli_size); Array<Real>::matrix_iterator sigma_it = stress(type, ghost_type).begin(spatial_dimension, spatial_dimension); Array<Real>::vector_iterator u_it = filtered_u.begin(spatial_dimension * nb_nodes_per_element); Matrix<Real> B(tangent_moduli_size, spatial_dimension * nb_nodes_per_element); Vector<Real> Bu(tangent_moduli_size); Vector<Real> 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<Real> & u = *u_it; Matrix<Real> & sigma = *sigma_it; Matrix<Real> & D = *D_it; VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(*shapes_derivatives_filtered_it, B, nb_nodes_per_element); Bu.mul<false>(B, u); DBu.mul<false>(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 = model->getFEEngine().getNbQuadraturePoints(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 += model->getFEEngine().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<Real> epot_on_quad_points(model->getFEEngine().getNbQuadraturePoints(type)); computePotentialEnergyByElement(type, index, epot_on_quad_points); epot = model->getFEEngine().integrate(epot_on_quad_points, type, element_filter(type)(index)); AKANTU_DEBUG_OUT(); return epot; } /* -------------------------------------------------------------------------- */ Real Material::getEnergy(std::string type) { AKANTU_DEBUG_IN(); if(type == "potential") return getPotentialEnergy(); AKANTU_DEBUG_OUT(); return 0.; } /* -------------------------------------------------------------------------- */ Real Material::getEnergy(std::string energy_id, ElementType type, UInt index) { AKANTU_DEBUG_IN(); if(energy_id == "potential") return getPotentialEnergy(type, index); AKANTU_DEBUG_OUT(); return 0.; } /* -------------------------------------------------------------------------- */ void Material::computeQuadraturePointsCoordinates(ElementTypeMapArray<Real> & quadrature_points_coordinates, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); const Mesh & mesh = this->model->getMesh(); Array<Real> nodes_coordinates(mesh.getNodes(), true); nodes_coordinates += this->model->getDisplacement(); Mesh::type_iterator it = this->element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = this->element_filter.lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { const Array<UInt> & elem_filter = this->element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_tot_quad = this->model->getFEEngine().getNbQuadraturePoints(*it, ghost_type) * nb_element; Array<Real> & quads = quadrature_points_coordinates(*it, ghost_type); quads.resize(nb_tot_quad); this->model->getFEEngine().interpolateOnQuadraturePoints(nodes_coordinates, quads, spatial_dimension, *it, ghost_type, elem_filter); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::initElementalFieldInterpolation(const ElementTypeMapArray<Real> & interpolation_points_coordinates) { AKANTU_DEBUG_IN(); const Mesh & mesh = model->getFEEngine().getMesh(); ElementTypeMapArray<Real> quadrature_points_coordinates("quadrature_points_coordinates_for_interpolation", getID()); mesh.initElementTypeMapArray(quadrature_points_coordinates, spatial_dimension, spatial_dimension); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; computeQuadraturePointsCoordinates(quadrature_points_coordinates, ghost_type); Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last = element_filter.lastType(spatial_dimension, ghost_type); for (; it != last; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type, ghost_type); if (nb_element == 0) continue; const Array<Real> & interp_points_coord = interpolation_points_coordinates(type, ghost_type); UInt nb_interpolation_points_per_elem = interp_points_coord.getSize() / nb_element; AKANTU_DEBUG_ASSERT(interp_points_coord.getSize() % nb_element == 0, "Number of interpolation points is wrong"); #define AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD(type) \ initElementalFieldInterpolation<type>(quadrature_points_coordinates(type, ghost_type), \ interp_points_coord, \ nb_interpolation_points_per_elem, \ ghost_type) \ AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD); #undef AKANTU_INIT_INTERPOLATE_ELEMENTAL_FIELD } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <ElementType type> void Material::initElementalFieldInterpolation(const Array<Real> & quad_coordinates, const Array<Real> & interpolation_points_coordinates, const UInt nb_interpolation_points_per_elem, const GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<UInt> & elem_fil = element_filter(type, ghost_type); UInt nb_element = elem_fil.getSize(); UInt nb_quad_per_element = model->getFEEngine().getNbQuadraturePoints(type, ghost_type); if(!interpolation_inverse_coordinates.exists(type, ghost_type)) interpolation_inverse_coordinates.alloc(nb_element, nb_quad_per_element*nb_quad_per_element, type, ghost_type); else interpolation_inverse_coordinates(type, ghost_type).resize(nb_element); if(!interpolation_points_matrices.exists(type, ghost_type)) interpolation_points_matrices.alloc(nb_element, nb_interpolation_points_per_elem * nb_quad_per_element, type, ghost_type); else interpolation_points_matrices(type, ghost_type).resize(nb_element); Array<Real> & interp_inv_coord = interpolation_inverse_coordinates(type, ghost_type); Array<Real> & interp_points_mat = interpolation_points_matrices(type, ghost_type); Matrix<Real> quad_coord_matrix(nb_quad_per_element, nb_quad_per_element); Array<Real>::const_matrix_iterator quad_coords_it = quad_coordinates.begin_reinterpret(spatial_dimension, nb_quad_per_element, nb_element); Array<Real>::const_matrix_iterator points_coords_begin = interpolation_points_coordinates.begin_reinterpret(spatial_dimension, nb_interpolation_points_per_elem, interpolation_points_coordinates.getSize() / nb_interpolation_points_per_elem); Array<Real>::matrix_iterator inv_quad_coord_it = interp_inv_coord.begin(nb_quad_per_element, nb_quad_per_element); Array<Real>::matrix_iterator inv_points_mat_it = interp_points_mat.begin(nb_interpolation_points_per_elem, nb_quad_per_element); /// loop over the elements of the current material and element type for (UInt el = 0; el < nb_element; ++el, ++inv_quad_coord_it, ++inv_points_mat_it, ++quad_coords_it) { /// matrix containing the quadrature points coordinates const Matrix<Real> & quad_coords = *quad_coords_it; /// matrix to store the matrix inversion result Matrix<Real> & inv_quad_coord_matrix = *inv_quad_coord_it; /// insert the quad coordinates in a matrix compatible with the interpolation buildElementalFieldInterpolationCoodinates<type>(quad_coords, quad_coord_matrix); /// invert the interpolation matrix inv_quad_coord_matrix.inverse(quad_coord_matrix); /// matrix containing the interpolation points coordinates const Matrix<Real> & points_coords = points_coords_begin[elem_fil(el)]; /// matrix to store the interpolation points coordinates /// compatible with these functions Matrix<Real> & inv_points_coord_matrix = *inv_points_mat_it; /// insert the quad coordinates in a matrix compatible with the interpolation buildElementalFieldInterpolationCoodinates<type>(points_coords, inv_points_coord_matrix); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::interpolateStress(ElementTypeMapArray<Real> & result, const GhostType ghost_type) { interpolateElementalField(stress, result, ghost_type); } /* -------------------------------------------------------------------------- */ void Material::interpolateElementalField(const ElementTypeMapArray<Real> & field, ElementTypeMapArray<Real> & result, const GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last = element_filter.lastType(spatial_dimension, ghost_type); for (; it != last; ++it) { ElementType type = *it; Array<UInt> & elem_fil = element_filter(type, ghost_type); UInt nb_element = elem_fil.getSize(); UInt nb_quad_per_element = model->getFEEngine().getNbQuadraturePoints(type, ghost_type); const Array<Real> & field_vec = field(type, ghost_type); Array<Real> & result_vec = result(type, ghost_type); Matrix<Real> coefficients(nb_quad_per_element, field_vec.getNbComponent()); const Array<Real> & interp_inv_coord = interpolation_inverse_coordinates(type, ghost_type); const Array<Real> & interp_points_coord = interpolation_points_matrices(type, ghost_type); UInt nb_interpolation_points_per_elem = interp_points_coord.getNbComponent() / nb_quad_per_element; Array<Real>::const_matrix_iterator field_it = field_vec.begin_reinterpret(field_vec.getNbComponent(), nb_quad_per_element, nb_element); Array<Real>::const_matrix_iterator interpolation_points_coordinates_it = interp_points_coord.begin(nb_interpolation_points_per_elem, nb_quad_per_element); Array<Real>::matrix_iterator result_begin = result_vec.begin_reinterpret(field_vec.getNbComponent(), nb_interpolation_points_per_elem, result_vec.getSize() / nb_interpolation_points_per_elem); Array<Real>::const_matrix_iterator inv_quad_coord_it = interp_inv_coord.begin(nb_quad_per_element, nb_quad_per_element); /// loop over the elements of the current material and element type for (UInt el = 0; el < nb_element; ++el, ++field_it, ++inv_quad_coord_it, ++interpolation_points_coordinates_it) { /** * matrix containing the inversion of the quadrature points' * coordinates */ const Matrix<Real> & inv_quad_coord_matrix = *inv_quad_coord_it; /** * multiply it by the field values over quadrature points to get * the interpolation coefficients */ coefficients.mul<false, true>(inv_quad_coord_matrix, *field_it); /// matrix containing the points' coordinates const Matrix<Real> & coord = *interpolation_points_coordinates_it; /// multiply the coordinates matrix by the coefficients matrix and store the result Matrix<Real> res(result_begin[elem_fil(el)]); res.mul<true, true>(coefficients, coord); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::interpolateStressOnFacets(ElementTypeMapArray<Real> & result, const GhostType ghost_type) { interpolateElementalFieldOnFacets(stress, result, ghost_type); } /* -------------------------------------------------------------------------- */ void Material::interpolateElementalFieldOnFacets(const ElementTypeMapArray<Real> & field, ElementTypeMapArray<Real> & result, const GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt sp2 = spatial_dimension * spatial_dimension; const Mesh & mesh = this->model->getMesh(); const Mesh & mesh_facets = mesh.getMeshFacets(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last = element_filter.lastType(spatial_dimension, ghost_type); for (; it != last; ++it) { ElementType type = *it; Array<UInt> & elem_fil = element_filter(type, ghost_type); UInt nb_element = elem_fil.getSize(); UInt nb_quad_per_element = model->getFEEngine().getNbQuadraturePoints(type, ghost_type); const Array<Real> & field_vec = field(type, ghost_type); Matrix<Real> coefficients(nb_quad_per_element, field_vec.getNbComponent()); const Array<Real> & interp_inv_coord = interpolation_inverse_coordinates(type, ghost_type); const Array<Real> & interp_points_coord = interpolation_points_matrices(type, ghost_type); UInt nb_interpolation_points_per_elem = interp_points_coord.getNbComponent() / nb_quad_per_element; Array<Real>::const_matrix_iterator field_it = field_vec.begin_reinterpret(field_vec.getNbComponent(), nb_quad_per_element, nb_element); Array<Real>::const_matrix_iterator interpolation_points_coordinates_it = interp_points_coord.begin(nb_interpolation_points_per_elem, nb_quad_per_element); Array<Real>::const_matrix_iterator inv_quad_coord_it = interp_inv_coord.begin(nb_quad_per_element, nb_quad_per_element); Matrix<Real> result_tmp(sp2, nb_interpolation_points_per_elem); const Array<Element> & 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> > * element_to_facet = NULL; GhostType current_ghost_type = _casper; Array<Real> * result_vec = NULL; /// loop over the elements of the current material and element type for (UInt el = 0; el < nb_element; ++el, ++field_it, ++inv_quad_coord_it, ++interpolation_points_coordinates_it) { /** * matrix containing the inversion of the quadrature points' * coordinates */ const Matrix<Real> & inv_quad_coord_matrix = *inv_quad_coord_it; /** * multiply it by the field values over quadrature points to get * the interpolation coefficients */ coefficients.mul<false, true>(inv_quad_coord_matrix, *field_it); /// matrix containing the points' coordinates const Matrix<Real> & coord = *interpolation_points_coordinates_it; /// multiply the coordinates matrix by the coefficients matrix and store the result result_tmp.mul<true, true>(coefficients, coord); UInt global_el = elem_fil(el); element_for_comparison.element = global_el; for (UInt f = 0; f < nb_facet_per_elem; ++f) { Element facet_elem = facet_to_element(global_el, f); UInt global_facet = facet_elem.element; if (facet_elem.ghost_type != current_ghost_type) { current_ghost_type = facet_elem.ghost_type; element_to_facet = &mesh_facets.getElementToSubelement(type_facet, current_ghost_type); result_vec = &result(type_facet, current_ghost_type); } bool is_second_element = (*element_to_facet)(global_facet)[0] != element_for_comparison; for (UInt q = 0; q < nb_quad_per_facet; ++q) { Vector<Real> result_local(result_vec->storage() + (global_facet * nb_quad_per_facet + q) * result_vec->getNbComponent() + is_second_element * sp2, sp2); result_local = result_tmp(f * nb_quad_per_facet + q); } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ const Array<Real> & 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<Real>(fvect_id); } catch(debug::Exception & e) { AKANTU_EXCEPTION("The material " << name << "(" <<getID() << ") does not contain a vector " << vect_id << "(" << fvect_id << ") [" << e << "]"); } } /* -------------------------------------------------------------------------- */ Array<Real> & 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<Real>(fvect_id); } catch(debug::Exception & e) { AKANTU_EXCEPTION("The material " << name << "(" << getID() << ") does not contain a vector " << vect_id << "(" << fvect_id << ") [" << e << "]"); } } /* -------------------------------------------------------------------------- */ const InternalField<Real> & Material::getInternal(const ID & int_id) const { std::map<ID, InternalField<Real> *>::const_iterator it = internal_vectors_real.find(getID() + ":" + int_id); if(it == internal_vectors_real.end()) { AKANTU_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ InternalField<Real> & Material::getInternal(const ID & int_id) { std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.find(getID() + ":" + int_id); if(it == internal_vectors_real.end()) { AKANTU_EXCEPTION("The material " << name << "(" << getID() << ") does not contain an internal " << int_id << " (" << (getID() + ":" + int_id) << ")"); } return *it->second; } /* -------------------------------------------------------------------------- */ void Material::addElements(const Array<Element> & elements_to_add) { AKANTU_DEBUG_IN(); UInt mat_id = model->getInternalIndexFromID(getID()); Array<Element>::const_iterator<Element> el_begin = elements_to_add.begin(); Array<Element>::const_iterator<Element> el_end = elements_to_add.end(); for(;el_begin != el_end; ++el_begin) { const Element & element = *el_begin; Array<UInt> & mat_indexes = model->getMaterialByElement (element.type, element.ghost_type); Array<UInt> & 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<Element> & elements_to_remove) { AKANTU_DEBUG_IN(); Array<Element>::const_iterator<Element> el_begin = elements_to_remove.begin(); Array<Element>::const_iterator<Element> el_end = elements_to_remove.end(); if(el_begin==el_end) return; ElementTypeMapArray<UInt> 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<UInt>::type_iterator it = element_filter.firstType(_all_dimensions, ghost_type, _ek_not_defined); ElementTypeMapArray<UInt>::type_iterator end = element_filter.lastType(_all_dimensions, ghost_type, _ek_not_defined); for(; it != end; ++it) { ElementType type = *it; element.type = type; Array<UInt> & elem_filter = this->element_filter(type, ghost_type); Array<UInt> & 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<UInt> & mat_renumbering = material_local_new_numbering(type, ghost_type); UInt nb_element = elem_filter.getSize(); element.kind=(*el_begin).kind; Array<UInt> 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<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->removeQuadraturePoints(material_local_new_numbering); for (std::map<ID, InternalField<UInt> *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->removeQuadraturePoints(material_local_new_numbering); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::resizeInternals() { AKANTU_DEBUG_IN(); for (std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->resize(); for (std::map<ID, InternalField<UInt> *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->resize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::onElementsAdded(__attribute__((unused)) const Array<Element> & element_list, __attribute__((unused)) const NewElementsEvent & event) { this->resizeInternals(); } /* -------------------------------------------------------------------------- */ void Material::onElementsRemoved(const Array<Element> & element_list, const ElementTypeMapArray<UInt> & new_numbering, __attribute__((unused)) const RemovedElementsEvent & event) { UInt my_num = model->getInternalIndexFromID(getID()); ElementTypeMapArray<UInt> material_local_new_numbering("remove mat filter elem", getID()); Array<Element>::const_iterator<Element> el_begin = element_list.begin(); Array<Element>::const_iterator<Element> 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<UInt>::type_iterator it = new_numbering.firstType(_all_dimensions, gt, _ek_not_defined); ElementTypeMapArray<UInt>::type_iterator end = new_numbering.lastType (_all_dimensions, gt, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; if(element_filter.exists(type, gt)){ Array<UInt> & elem_filter = element_filter(type, gt); Array<UInt> & mat_indexes = this->model->getMaterialByElement (*it, gt); Array<UInt> & 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<UInt> & mat_renumbering = material_local_new_numbering(type, gt); const Array<UInt> & renumbering = new_numbering(type, gt); Array<UInt> elem_filter_tmp; UInt ni = 0; Element el; el.type = type; el.ghost_type = gt; 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); } } } for (std::map<ID, InternalField<Real> *>::iterator it = internal_vectors_real.begin(); it != internal_vectors_real.end(); ++it) it->second->removeQuadraturePoints(material_local_new_numbering); for (std::map<ID, InternalField<UInt> *>::iterator it = internal_vectors_uint.begin(); it != internal_vectors_uint.end(); ++it) it->second->removeQuadraturePoints(material_local_new_numbering); } /* -------------------------------------------------------------------------- */ void Material::onBeginningSolveStep(const AnalysisMethod & method) { this->savePreviousState(); } /* -------------------------------------------------------------------------- */ void Material::onEndSolveStep(const AnalysisMethod & method) { ElementTypeMapArray<UInt>::type_iterator it = this->element_filter.firstType(_all_dimensions, _not_ghost, _ek_not_defined); ElementTypeMapArray<UInt>::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<UInt>::type_iterator it = this->element_filter.firstType(_all_dimensions, _not_ghost, _ek_not_defined); ElementTypeMapArray<UInt>::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->model->getFEEngine().getNbQuadraturePoints(*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; } /* -------------------------------------------------------------------------- */ void Material::flattenInternal(const std::string & field_id, ElementTypeMapArray<Real> & internal_flat, const GhostType ghost_type, ElementKind element_kind){ typedef ElementTypeMapArray<UInt>::type_iterator iterator; iterator tit = this->element_filter.firstType(this->spatial_dimension, ghost_type, element_kind); iterator end = this->element_filter.lastType(this->spatial_dimension, ghost_type, element_kind); for (; tit != end; ++tit) { ElementType type = *tit; try { __attribute__((unused)) const Array<Real> & src_vect = this->getArray(field_id,type,ghost_type); } catch(debug::Exception & e) { continue; } const Array<Real> & src_vect = this->getArray(field_id,type,ghost_type); const Array<UInt> & filter = this->element_filter(type,ghost_type); // total number of elements for a given type UInt nb_element = this->model->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<Real> & dst_vect = internal_flat(type,ghost_type); dst_vect.resize(nb_element*nb_quad_per_elem); Array<UInt>::const_scalar_iterator it = filter.begin(); Array<UInt>::const_scalar_iterator end = filter.end(); Array<Real>::const_vector_iterator it_src = src_vect.begin_reinterpret(nb_data,nb_element_src); Array<Real>::vector_iterator it_dst = dst_vect.begin_reinterpret(nb_data,nb_element); for (; it != end ; ++it,++it_src) { it_dst[*it] = *it_src; } } }; /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/model/solid_mechanics/material.hh b/src/model/solid_mechanics/material.hh index c3e3dffb5..e61941c14 100644 --- a/src/model/solid_mechanics/material.hh +++ b/src/model/solid_mechanics/material.hh @@ -1,600 +1,616 @@ /** * @file material.hh * * @author Marco Vocialta <marco.vocialta@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #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<Real> & tangent_matrix, * GhostType ghost_type = _not_ghost); * \endcode * */ class Material : public Memory, public DataAccessor, public Parsable, public MeshEventHandler, protected SolidMechanicsModelEventHandler { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: + /// Initialize material with defaults Material(SolidMechanicsModel & model, const ID & id = ""); + + /// Initialize material with custom mesh & fe_engine + Material(SolidMechanicsModel & model, + UInt dim, + const Mesh & mesh, + FEEngine & fe_engine, + const ID & id = ""); + + /// Destructor virtual ~Material(); +protected: + void initialize(); + /* ------------------------------------------------------------------------ */ /* Function that materials can/should reimplement */ /* ------------------------------------------------------------------------ */ protected: /// constitutive law virtual void computeStress(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the tangent stiffness matrix virtual void computeTangentModuli(__attribute__((unused)) const ElementType & el_type, __attribute__((unused)) Array<Real> & tangent_matrix, __attribute__((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the potential energy virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the potential energy for an element virtual void computePotentialEnergyByElement(__attribute__((unused)) ElementType type, __attribute__((unused)) UInt index, __attribute__((unused)) Vector<Real> & epot_on_quad_points) { AKANTU_DEBUG_TO_IMPLEMENT(); } virtual void updateEnergies(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) { } virtual void updateEnergiesAfterDamage(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) {} /// set the material to steady state (to be implemented for materials that need it) virtual void setToSteadyState(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) { } /// function called to update the internal parameters when the modifiable /// parameters are modified virtual void updateInternalParameters() {} public: /// 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<typename T> void registerInternal(__attribute__((unused)) InternalField<T> & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); } template<typename T> void unregisterInternal(__attribute__((unused)) InternalField<T> & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// initialize the material computed parameter virtual void initMaterial(); /// compute the residual for this material virtual void updateResidual(GhostType ghost_type = _not_ghost); /// assemble the residual for this material virtual void 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<Element> & elements_to_add); /// remove many element at once void removeElements(const Array<Element> & elements_to_remove); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /** * interpolate stress on given positions for each element by means * of a geometrical interpolation on quadrature points */ void interpolateStress(ElementTypeMapArray<Real> & result, const GhostType ghost_type = _not_ghost); /** * interpolate stress on given positions for each element by means * of a geometrical interpolation on quadrature points and store the * results per facet */ void interpolateStressOnFacets(ElementTypeMapArray<Real> & result, const GhostType ghost_type = _not_ghost); /** * function to initialize the elemental field interpolation * function by inverting the quadrature points' coordinates */ void initElementalFieldInterpolation(const ElementTypeMapArray<Real> & interpolation_points_coordinates); /* ------------------------------------------------------------------------ */ /* Common part */ /* ------------------------------------------------------------------------ */ protected: /// assemble the residual template<UInt dim> void assembleResidual(GhostType ghost_type); /// Computation of Cauchy stress tensor in the case of finite deformation template<UInt dim> void computeCauchyStress(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost); template<UInt dim > inline void computeCauchyStressOnQuad(const Matrix<Real> & F, const Matrix<Real> & S, Matrix<Real> & cauchy, const Real & C33 = 1.0 ) const; template<UInt dim> void computeAllStressesFromTangentModuli(const ElementType & type, GhostType ghost_type); template<UInt dim> void assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type); /// assembling in finite deformation template<UInt dim> void assembleStiffnessMatrixNL(const ElementType & type, GhostType ghost_type); template<UInt dim> void assembleStiffnessMatrixL2(const ElementType & type, GhostType ghost_type); /// write the stress tensor in the Voigt notation. template<UInt dim> inline void SetCauchyStressArray(const Matrix<Real> & S_t, Matrix<Real> & Stress_vect); inline UInt getTangentStiffnessVoigtSize(UInt spatial_dimension) const; /// Size of the Stress matrix for the case of finite deformation see: Bathe et al, IJNME, Vol 9, 353-386, 1975 inline UInt getCauchyStressMatrixSize(UInt spatial_dimension) const; /// Sets the stress matrix according to Bathe et al, IJNME, Vol 9, 353-386, 1975 template<UInt dim> inline void setCauchyStressMatrix(const Matrix<Real> & S_t, Matrix<Real> & Stress_matrix); /// compute the potential energy by element void computePotentialEnergyByElements(); /// resize the intenals arrays virtual void resizeInternals(); public: /// compute the coordinates of the quadrature points void computeQuadraturePointsCoordinates(ElementTypeMapArray<Real> & quadrature_points_coordinates, const GhostType & ghost_type) const; protected: /// interpolate an elemental field on given points for each element void interpolateElementalField(const ElementTypeMapArray<Real> & field, ElementTypeMapArray<Real> & result, const GhostType ghost_type); /// interpolate an elemental field and store the results per facet void interpolateElementalFieldOnFacets(const ElementTypeMapArray<Real> & field, ElementTypeMapArray<Real> & result, const GhostType ghost_type); /// template function to initialize the elemental field interpolation template <ElementType type> void initElementalFieldInterpolation(const Array<Real> & quad_coordinates, const Array<Real> & interpolation_points_coordinates, const UInt nb_interpolation_points_per_elem, const GhostType ghost_type); /// build the coordinate matrix for the interpolation on elemental field template <ElementType type> inline void buildElementalFieldInterpolationCoodinates(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix); /// build interpolation coordinates for basic linear elements inline void buildElementalFieldInterpolationCoodinatesLinear(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix); /// build interpolation coordinates for basic quadratic elements inline void buildElementalFieldInterpolationCoodinatesQuadratic(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix); public: /* ------------------------------------------------------------------------ */ /* Conversion functions */ /* ------------------------------------------------------------------------ */ template<UInt dim> static inline void gradUToF (const Matrix<Real> & grad_u, Matrix<Real> & F); static inline void rightCauchy(const Matrix<Real> & F, Matrix<Real> & C); static inline void leftCauchy (const Matrix<Real> & F, Matrix<Real> & B); template<UInt dim> static inline void gradUToEpsilon(const Matrix<Real> & grad_u, Matrix<Real> & epsilon); template<UInt dim> static inline void gradUToGreenStrain(const Matrix<Real> & grad_u, Matrix<Real> & epsilon); static inline Real stressToVonMises(const Matrix<Real> & stress); protected: /// converts global element to local element inline Element convertToLocalElement(const Element & global_element) const; /// converts local element to global element inline Element convertToGlobalElement(const Element & local_element) const; /// converts global quadrature point to local quadrature point inline QuadraturePoint convertToLocalPoint(const QuadraturePoint & global_point) const; /// converts local quadrature point to global quadrature point inline QuadraturePoint convertToGlobalPoint(const QuadraturePoint & local_point) const; /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: virtual inline UInt getNbDataForElements(const Array<Element> & elements, SynchronizationTag tag) const; virtual inline void packElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) const; virtual inline void unpackElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag); template<typename T> inline void packElementDataHelper(const ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer, const Array<Element> & elements, const ID & fem_id = ID()) const; template<typename T> inline void unpackElementDataHelper(ElementTypeMapArray<T> & data_to_unpack, CommunicationBuffer & buffer, const Array<Element> & elements, const ID & fem_id = ID()); /* ------------------------------------------------------------------------ */ /* MeshEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ virtual void onElementsAdded(const Array<Element> & element_list, const NewElementsEvent & event); virtual void onElementsRemoved(const Array<Element> & element_list, const ElementTypeMapArray<UInt> & new_numbering, const RemovedElementsEvent & event); /* ------------------------------------------------------------------------ */ /* 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(Model, *model, const SolidMechanicsModel &) AKANTU_GET_MACRO(ID, Memory::getID(), const ID &); AKANTU_GET_MACRO(Rho, rho, Real); AKANTU_SET_MACRO(Rho, rho, Real); + AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); + /// return the potential energy for the subset of elements contained by the material Real getPotentialEnergy(); /// return the potential energy for the provided element Real getPotentialEnergy(ElementType & type, UInt index); /// return the energy (identified by id) for the subset of elements contained by the material virtual Real getEnergy(std::string energy_id); /// return the energy (identified by id) for the provided element virtual Real getEnergy(std::string energy_id, ElementType type, UInt index); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(GradU, gradu, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PotentialEnergy, potential_energy, Real); AKANTU_GET_MACRO(GradU, gradu, const ElementTypeMapArray<Real> &); AKANTU_GET_MACRO(Stress, stress, const ElementTypeMapArray<Real> &); AKANTU_GET_MACRO(ElementFilter, element_filter, const ElementTypeMapArray<UInt> &); bool isNonLocal() const { return is_non_local; } const Array<Real> & getArray(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost) const; Array<Real> & getArray(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost); const InternalField<Real> & getInternal(const ID & id) const; InternalField<Real> & getInternal(const ID & id); inline bool isInternal(const ID & id, const ElementKind & element_kind) const; - inline ElementTypeMap<UInt> getInternalDataPerElem(const ID & id, const ElementKind & element_kind, const ID & fe_engine_id = "") const; + inline ElementTypeMap<UInt> getInternalDataPerElem(const ID & id, + const ElementKind & element_kind) const; bool isFiniteDeformation() const { return finite_deformation; } bool isInelasticDeformation() const { return inelastic_deformation; } template <typename T> inline void setParam(const ID & param, T value); template <typename T> inline const T & getParam(const ID & param) const; virtual void flattenInternal(const std::string & field_id, ElementTypeMapArray<Real> & internal_flat, const GhostType ghost_type = _not_ghost, ElementKind element_kind = _ek_not_defined); protected: bool isInit() const { return is_init; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// boolean to know if the material has been initialized bool is_init; std::map<ID, InternalField<Real> *> internal_vectors_real; std::map<ID, InternalField<UInt> *> internal_vectors_uint; protected: /// Finite deformation bool finite_deformation; /// Finite deformation bool inelastic_deformation; /// material name std::string name; /// The model to witch the material belong SolidMechanicsModel * model; /// density : rho Real rho; /// spatial dimension UInt spatial_dimension; /// list of element handled by the material ElementTypeMapArray<UInt> element_filter; /// stresses arrays ordered by element types InternalField<Real> stress; /// eigenstrain arrays ordered by element types InternalField<Real> eigenstrain; /// grad_u arrays ordered by element types InternalField<Real> gradu; /// Green Lagrange strain (Finite deformation) InternalField<Real> green_strain; /// Second Piola-Kirchhoff stress tensor arrays ordered by element types (Finite deformation) InternalField<Real> piola_kirchhoff_2; /// potential energy by element InternalField<Real> potential_energy; /// tell if using in non local mode or not bool is_non_local; /// tell if the material need the previous stress state bool use_previous_stress; /// tell if the material need the previous strain state bool use_previous_gradu; /// elemental field interpolation coordinates InternalField<Real> interpolation_inverse_coordinates; /// elemental field interpolation points InternalField<Real> interpolation_points_matrices; }; /* -------------------------------------------------------------------------- */ /* 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 */ /* -------------------------------------------------------------------------- */ #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type) \ Array<Real>::matrix_iterator gradu_it = \ this->gradu(el_type, ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ Array<Real>::matrix_iterator gradu_end = \ this->gradu(el_type, ghost_type).end(this->spatial_dimension, \ this->spatial_dimension); \ \ this->stress(el_type, \ ghost_type).resize(this->gradu(el_type, \ ghost_type).getSize()); \ \ Array<Real>::iterator< Matrix<Real> > stress_it = \ this->stress(el_type, ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ \ if(this->isFiniteDeformation()){ \ this->piola_kirchhoff_2(el_type, \ ghost_type).resize(this->gradu(el_type, \ ghost_type).getSize()); \ stress_it = \ this->piola_kirchhoff_2(el_type, \ ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ } \ \ for(;gradu_it != gradu_end; ++gradu_it, ++stress_it) { \ Matrix<Real> & __attribute__((unused)) grad_u = *gradu_it; \ Matrix<Real> & __attribute__((unused)) sigma = *stress_it #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END \ } \ #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_mat) \ Array<Real>::matrix_iterator gradu_it = \ this->gradu(el_type, ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ Array<Real>::matrix_iterator gradu_end = \ this->gradu(el_type, ghost_type).end(this->spatial_dimension, \ this->spatial_dimension); \ Array<Real>::matrix_iterator sigma_it = \ this->stress(el_type, ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ \ tangent_mat.resize(this->gradu(el_type, ghost_type).getSize()); \ \ UInt tangent_size = \ this->getTangentStiffnessVoigtSize(this->spatial_dimension); \ Array<Real>::matrix_iterator tangent_it = \ tangent_mat.begin(tangent_size, \ tangent_size); \ \ for(;gradu_it != gradu_end; ++gradu_it, ++sigma_it, ++tangent_it) { \ Matrix<Real> & __attribute__((unused)) grad_u = *gradu_it; \ Matrix<Real> & __attribute__((unused)) sigma_tensor = *sigma_it; \ Matrix<Real> & tangent = *tangent_it #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END \ } \ /* -------------------------------------------------------------------------- */ #define INSTANSIATE_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_inline_impl.cc b/src/model/solid_mechanics/material_inline_impl.cc index b00185ba2..bb3551113 100644 --- a/src/model/solid_mechanics/material_inline_impl.cc +++ b/src/model/solid_mechanics/material_inline_impl.cc @@ -1,491 +1,486 @@ /** * @file material_inline_impl.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Sep 16 2014 * * @brief Implementation of the inline functions of the class material * * @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 <http://www.gnu.org/licenses/>. * */ __END_AKANTU__ #include "solid_mechanics_model.hh" #include <iostream> __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ inline UInt Material::addElement(const ElementType & type, UInt element, const GhostType & ghost_type) { Array<UInt> & el_filter = element_filter(type, ghost_type); el_filter.push_back(element); return el_filter.getSize()-1; } /* -------------------------------------------------------------------------- */ inline UInt Material::getTangentStiffnessVoigtSize(UInt dim) const { return (dim * (dim - 1) / 2 + dim); } /* -------------------------------------------------------------------------- */ inline UInt Material::getCauchyStressMatrixSize(UInt dim) const { return (dim * dim); } /* -------------------------------------------------------------------------- */ template<UInt dim> inline void Material::gradUToF(const Matrix<Real> & grad_u, Matrix<Real> & F) { AKANTU_DEBUG_ASSERT(F.size() >= grad_u.size() && grad_u.size() == dim*dim, "The dimension of the tensor F should be greater or equal to the dimension of the tensor grad_u."); F.eye(); for (UInt i = 0; i < dim; ++i) for (UInt j = 0; j < dim; ++j) F(i, j) += grad_u(i, j); } /* -------------------------------------------------------------------------- */ template<UInt dim > inline void Material::computeCauchyStressOnQuad(const Matrix<Real> & F, const Matrix<Real> & piola, Matrix<Real> & sigma, const Real & C33 ) const { Real J = F.det() * sqrt(C33); Matrix<Real> F_S(dim, dim); F_S.mul<false, false>(F, piola); Real constant = J ? 1./J : 0; sigma.mul<false, true>(F_S, F, constant); } /* -------------------------------------------------------------------------- */ inline void Material::rightCauchy(const Matrix<Real> & F, Matrix<Real> & C) { C.mul<true, false>(F, F); } /* -------------------------------------------------------------------------- */ inline void Material::leftCauchy(const Matrix<Real> & F, Matrix<Real> & B) { B.mul<false, true>(F, F); } /* -------------------------------------------------------------------------- */ template<UInt dim> inline void Material::gradUToEpsilon(const Matrix<Real> & grad_u, Matrix<Real> & epsilon) { for (UInt i = 0; i < dim; ++i) for (UInt j = 0; j < dim; ++j) epsilon(i, j) = 0.5*(grad_u(i, j) + grad_u(j, i)); } /* -------------------------------------------------------------------------- */ template<UInt dim> inline void Material::gradUToGreenStrain(const Matrix<Real> & grad_u, Matrix<Real> & epsilon) { epsilon.mul<true, false>(grad_u, grad_u, .5); for (UInt i = 0; i < dim; ++i) for (UInt j = 0; j < dim; ++j) epsilon(i, j) += 0.5 * (grad_u(i, j) + grad_u(j, i)); } /* -------------------------------------------------------------------------- */ inline Real Material::stressToVonMises(const Matrix<Real> & stress) { // compute deviatoric stress UInt dim = stress.cols(); Matrix<Real> deviatoric_stress = Matrix<Real>::eye(dim, -1. * stress.trace() / 3.); for (UInt i = 0; i < dim; ++i) for (UInt j = 0; j < dim; ++j) deviatoric_stress(i,j) += stress(i,j); // return Von Mises stress return std::sqrt(3. * deviatoric_stress.doubleDot(deviatoric_stress) / 2.); } /* ---------------------------------------------------------------------------*/ template<UInt dim> inline void Material::SetCauchyStressArray(const Matrix<Real> & S_t, Matrix<Real> & Stress_vect) { AKANTU_DEBUG_IN(); Stress_vect.clear(); //UInt cauchy_matrix_size = getCauchyStressArraySize(dim); //see Finite ekement formulations for large deformation dynamic analysis, Bathe et al. IJNME vol 9, 1975, page 364 ^t\tau /* * 1d: [ s11 ]' * 2d: [ s11 s22 s12 ]' * 3d: [ s11 s22 s33 s23 s13 s12 ] */ for (UInt i = 0; i < dim; ++i)//diagonal terms Stress_vect(i, 0) = S_t(i, i); for (UInt i = 1; i < dim; ++i)// term s12 in 2D and terms s23 s13 in 3D Stress_vect(dim+i-1, 0) = S_t(dim-i-1, dim-1); for (UInt i = 2; i < dim; ++i)//term s13 in 3D Stress_vect(dim+i, 0) = S_t(0, 1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> inline void Material::setCauchyStressMatrix(const Matrix<Real> & S_t, Matrix<Real> & Stress_matrix) { AKANTU_DEBUG_IN(); Stress_matrix.clear(); /// see Finite ekement formulations for large deformation dynamic analysis, /// Bathe et al. IJNME vol 9, 1975, page 364 ^t\tau for (UInt i = 0; i < dim; ++i) { for (UInt m = 0; m < dim; ++m) { for (UInt n = 0; n < dim; ++n) { Stress_matrix(i * dim + m, i * dim + n) = S_t(m, n); } } } //other terms from the diagonal /*for (UInt i = 0; i < 3 - dim; ++i) { Stress_matrix(dim * dim + i, dim * dim + i) = S_t(dim + i, dim + i); }*/ AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline Element Material::convertToLocalElement(const Element & global_element) const { UInt ge = global_element.element; #ifndef AKANTU_NDEBUG UInt model_mat_index = this->model->getMaterialByElement(global_element.type, global_element.ghost_type)(ge); UInt mat_index = this->model->getMaterialIndex(this->name); AKANTU_DEBUG_ASSERT(model_mat_index == mat_index, "Conversion of a global element in a local element for the wrong material " << this->name << std::endl); #endif UInt le = this->model->getMaterialLocalNumbering(global_element.type, global_element.ghost_type)(ge); Element tmp_quad(global_element.type, le, global_element.ghost_type); return tmp_quad; } /* -------------------------------------------------------------------------- */ inline Element Material::convertToGlobalElement(const Element & local_element) const { UInt le = local_element.element; UInt ge = this->element_filter(local_element.type, local_element.ghost_type)(le); Element tmp_quad(local_element.type, ge, local_element.ghost_type); return tmp_quad; } /* -------------------------------------------------------------------------- */ inline QuadraturePoint Material::convertToLocalPoint(const QuadraturePoint & global_point) const { const FEEngine & fem = this->model->getFEEngine(); UInt nb_quad = fem.getNbQuadraturePoints(global_point.type); Element el = this->convertToLocalElement(static_cast<const Element &>(global_point)); QuadraturePoint tmp_quad(el, global_point.num_point, nb_quad); return tmp_quad; } /* -------------------------------------------------------------------------- */ inline QuadraturePoint Material::convertToGlobalPoint(const QuadraturePoint & local_point) const { const FEEngine & fem = this->model->getFEEngine(); UInt nb_quad = fem.getNbQuadraturePoints(local_point.type); Element el = this->convertToGlobalElement(static_cast<const Element &>(local_point)); QuadraturePoint tmp_quad(el, local_point.num_point, nb_quad); return tmp_quad; } /* -------------------------------------------------------------------------- */ template<ElementType type> inline void Material::buildElementalFieldInterpolationCoodinates(__attribute__((unused)) const Matrix<Real> & coordinates, __attribute__((unused)) Matrix<Real> & coordMatrix) { AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ inline void Material::buildElementalFieldInterpolationCoodinatesLinear(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix) { for (UInt i = 0; i < coordinates.cols(); ++i) coordMatrix(i, 0) = 1; } /* -------------------------------------------------------------------------- */ inline void Material::buildElementalFieldInterpolationCoodinatesQuadratic(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix) { UInt nb_quadrature_points = coordMatrix.cols(); for (UInt i = 0; i < coordinates.cols(); ++i) { coordMatrix(i, 0) = 1; for (UInt j = 1; j < nb_quadrature_points; ++j) coordMatrix(i, j) = coordinates(j-1, i); } } /* -------------------------------------------------------------------------- */ template<> inline void Material::buildElementalFieldInterpolationCoodinates<_segment_2>(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix) { buildElementalFieldInterpolationCoodinatesLinear(coordinates, coordMatrix); } /* -------------------------------------------------------------------------- */ template<> inline void Material::buildElementalFieldInterpolationCoodinates<_segment_3>(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix) { buildElementalFieldInterpolationCoodinatesQuadratic(coordinates, coordMatrix); } /* -------------------------------------------------------------------------- */ template<> inline void Material::buildElementalFieldInterpolationCoodinates<_triangle_3>(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix) { buildElementalFieldInterpolationCoodinatesLinear(coordinates, coordMatrix); } /* -------------------------------------------------------------------------- */ template<> inline void Material::buildElementalFieldInterpolationCoodinates<_triangle_6>(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix) { buildElementalFieldInterpolationCoodinatesQuadratic(coordinates, coordMatrix); } /* -------------------------------------------------------------------------- */ template<> inline void Material::buildElementalFieldInterpolationCoodinates<_tetrahedron_4>(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix) { buildElementalFieldInterpolationCoodinatesLinear(coordinates, coordMatrix); } /* -------------------------------------------------------------------------- */ template<> inline void Material::buildElementalFieldInterpolationCoodinates<_tetrahedron_10>(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix) { buildElementalFieldInterpolationCoodinatesQuadratic(coordinates, coordMatrix); } /** * @todo Write a more efficient interpolation for quadrangles by * dropping unnecessary quadrature points * */ /* -------------------------------------------------------------------------- */ template<> inline void Material::buildElementalFieldInterpolationCoodinates<_quadrangle_4>(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix) { for (UInt i = 0; i < coordinates.cols(); ++i) { Real x = coordinates(0, i); Real y = coordinates(1, i); coordMatrix(i, 0) = 1; coordMatrix(i, 1) = x; coordMatrix(i, 2) = y; coordMatrix(i, 3) = x * y; } } /* -------------------------------------------------------------------------- */ template<> inline void Material::buildElementalFieldInterpolationCoodinates<_quadrangle_8>(const Matrix<Real> & coordinates, Matrix<Real> & coordMatrix) { for (UInt i = 0; i < coordinates.cols(); ++i) { UInt j = 0; Real x = coordinates(0, i); Real y = coordinates(1, i); for (UInt e = 0; e <= 2; ++e) { for (UInt n = 0; n <= 2; ++n) { coordMatrix(i, j) = std::pow(x, e) * std::pow(y, n); ++j; } } } } /* -------------------------------------------------------------------------- */ inline UInt Material::getNbDataForElements(const Array<Element> & elements, SynchronizationTag tag) const { if(tag == _gst_smm_stress) { return (this->isFiniteDeformation() ? 3 : 1) * spatial_dimension * spatial_dimension * sizeof(Real) * this->getModel().getNbQuadraturePoints(elements); } return 0; } /* -------------------------------------------------------------------------- */ inline void Material::packElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) const { if(tag == _gst_smm_stress) { if(this->isFiniteDeformation()) { packElementDataHelper(piola_kirchhoff_2, buffer, elements); packElementDataHelper(gradu, buffer, elements); } packElementDataHelper(stress, buffer, elements); } } /* -------------------------------------------------------------------------- */ inline void Material::unpackElementData(CommunicationBuffer & buffer, const Array<Element> & elements, SynchronizationTag tag) { if(tag == _gst_smm_stress) { if(this->isFiniteDeformation()) { unpackElementDataHelper(piola_kirchhoff_2, buffer, elements); unpackElementDataHelper(gradu, buffer, elements); } unpackElementDataHelper(stress, buffer, elements); } } /* -------------------------------------------------------------------------- */ template <typename T> inline const T & Material::getParam(const ID & param) const { try { return get<T>(param); } catch (...) { AKANTU_EXCEPTION("No parameter " << param << " in the material " << getID()); } } /* -------------------------------------------------------------------------- */ template <typename T> inline void Material::setParam(const ID & param, T value) { try { set<T>(param, value); } catch(...) { AKANTU_EXCEPTION("No parameter " << param << " in the material " << getID()); } updateInternalParameters(); } /* -------------------------------------------------------------------------- */ template<typename T> inline void Material::packElementDataHelper(const ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer, const Array<Element> & elements, const ID & fem_id) const { DataAccessor::packElementalDataHelper<T>(data_to_pack, buffer, elements, true, model->getFEEngine(fem_id)); } /* -------------------------------------------------------------------------- */ template<typename T> inline void Material::unpackElementDataHelper(ElementTypeMapArray<T> & data_to_unpack, CommunicationBuffer & buffer, const Array<Element> & elements, const ID & fem_id) { DataAccessor::unpackElementalDataHelper<T>(data_to_unpack, buffer, elements, true, model->getFEEngine(fem_id)); } /* -------------------------------------------------------------------------- */ template<> inline void Material::registerInternal<Real>(InternalField<Real> & vect) { internal_vectors_real[vect.getID()] = &vect; } template<> inline void Material::registerInternal<UInt>(InternalField<UInt> & vect) { internal_vectors_uint[vect.getID()] = &vect; } /* -------------------------------------------------------------------------- */ template<> inline void Material::unregisterInternal<Real>(InternalField<Real> & vect) { internal_vectors_real.erase(vect.getID()); } template<> inline void Material::unregisterInternal<UInt>(InternalField<UInt> & vect) { internal_vectors_uint.erase(vect.getID()); } /* -------------------------------------------------------------------------- */ inline bool Material::isInternal(const ID & id, const ElementKind & element_kind) const { std::map<ID, InternalField<Real> *>::const_iterator internal_array = internal_vectors_real.find(this->getID()+":"+id); if (internal_array == internal_vectors_real.end()) return false; if (internal_array->second->getElementKind() != element_kind) return false; return true; } /* -------------------------------------------------------------------------- */ -inline ElementTypeMap<UInt> Material::getInternalDataPerElem(const ID & id, const ElementKind & element_kind, - const ID & fe_engine_id) const { +inline ElementTypeMap<UInt> Material::getInternalDataPerElem(const ID & id, + const ElementKind & element_kind) const { std::map<ID, InternalField<Real> *>::const_iterator internal_array = internal_vectors_real.find(this->getID()+":"+id); if (internal_array == internal_vectors_real.end()) AKANTU_EXCEPTION("cannot find internal " << id); if (internal_array->second->getElementKind() != element_kind) AKANTU_EXCEPTION("cannot find internal " << id); InternalField<Real> & internal = *internal_array->second; InternalField<Real>::type_iterator it = internal.firstType(spatial_dimension, _not_ghost,element_kind); InternalField<Real>::type_iterator last_type = internal.lastType(spatial_dimension, _not_ghost,element_kind); ElementTypeMap<UInt> res; for(; it != last_type; ++it) { UInt nb_quadrature_points = 0; - if (element_kind == _ek_regular) - nb_quadrature_points = model->getFEEngine(fe_engine_id).getNbQuadraturePoints(*it); -#if defined(AKANTU_COHESIVE_ELEMENT) - else if (element_kind == _ek_cohesive) - nb_quadrature_points = model->getFEEngine("CohesiveFEEngine").getNbQuadraturePoints(*it); -#endif + nb_quadrature_points = internal.getFEEngine().getNbQuadraturePoints(*it); res(*it) = internal.getNbComponent() * nb_quadrature_points; } return res; } diff --git a/src/model/solid_mechanics/materials/internal_field.hh b/src/model/solid_mechanics/materials/internal_field.hh index 571e68044..49d5e209e 100644 --- a/src/model/solid_mechanics/materials/internal_field.hh +++ b/src/model/solid_mechanics/materials/internal_field.hh @@ -1,194 +1,205 @@ /** * @file internal_field.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Nov 13 2013 * @date last modification: Tue Sep 02 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "element_type_map.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_INTERNAL_FIELD_HH__ #define __AKANTU_INTERNAL_FIELD_HH__ __BEGIN_AKANTU__ class Material; class FEEngine; template<typename T> class InternalField : public ElementTypeMapArray<T> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: InternalField(const ID & id, Material & material); virtual ~InternalField(); -protected: - InternalField(const ID & id, Material & material, FEEngine & fem, + /// This constructor is only here to let cohesive elements compile + InternalField(const ID & id, + Material & material, + FEEngine & fem, + const ElementTypeMapArray<UInt> & element_filter); + + /// More general constructor + InternalField(const ID & id, + Material & material, + UInt dim, + FEEngine & fem, const ElementTypeMapArray<UInt> & element_filter); InternalField(const ID & id, const InternalField<T> & other); private: InternalField operator=(__attribute__((unused)) const InternalField & other) {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the field to a given number of component virtual void initialize(UInt nb_component); /// activate the history of this field virtual void initializeHistory(); /// resize the arrays and set the new element to 0 virtual void resize(); /// set the field to a given value v virtual void setDefaultValue(const T & v); /// reset all the fields to the default value virtual void reset(); /// save the current values in the history virtual void saveCurrentValues(); /// remove the quadrature points corresponding to suppressed elements virtual void removeQuadraturePoints(const ElementTypeMapArray<UInt> & new_numbering); /// print the content virtual void printself(std::ostream & stream, UInt indent = 0) const; /// get the default value inline operator T() const; + AKANTU_GET_MACRO(FEEngine, fem, const FEEngine &); + protected: /// initialize the arrays in the ElementTypeMapArray<T> void internalInitialize(UInt nb_component); /// set the values for new internals virtual void setArrayValues(T * begin, T * end); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the Array corresponding to the type en ghost_type specified virtual Array<T> & operator()(const ElementType & type, const GhostType & ghost_type = _not_ghost) { return ElementTypeMapArray<T>::operator()(type, ghost_type); } virtual const Array<T> & operator()(const ElementType & type, const GhostType & ghost_type = _not_ghost) const { return ElementTypeMapArray<T>::operator()(type, ghost_type); } virtual Array<T> & previous(const ElementType & type, const GhostType & ghost_type = _not_ghost) { AKANTU_DEBUG_ASSERT(previous_values != NULL, "The history of the internal " << this->getID() << " has not been activated"); return this->previous_values->operator()(type, ghost_type); } virtual const Array<T> & previous(const ElementType & type, const GhostType & ghost_type = _not_ghost) const { AKANTU_DEBUG_ASSERT(previous_values != NULL, "The history of the internal " << this->getID() << " has not been activated"); return this->previous_values->operator()(type, ghost_type); } virtual InternalField<T> & previous() { AKANTU_DEBUG_ASSERT(previous_values != NULL, "The history of the internal " << this->getID() << " has not been activated"); return *(this->previous_values); } virtual const InternalField<T> & previous() const { AKANTU_DEBUG_ASSERT(previous_values != NULL, "The history of the internal " << this->getID() << " has not been activated"); return *(this->previous_values); } /// check if the history is used or not bool hasHistory() const { return (previous_values != NULL); } /// get the kind treated by the internal const ElementKind & getElementKind() const {return element_kind;}; /// return the number of components UInt getNbComponent(){return nb_component;} /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the material for which this is an internal parameter Material & material; /// the fem containing the mesh and the element informations FEEngine & fem; /// Element filter if needed const ElementTypeMapArray<UInt> & element_filter; /// default value T default_value; /// spatial dimension of the element to consider UInt spatial_dimension; /// ElementKind of the element to consider ElementKind element_kind; /// Number of component of the internal field UInt nb_component; /// Is the field initialized bool is_init; /// previous values InternalField<T> * previous_values; }; /// standard output stream operator template<typename T> inline std::ostream & operator <<(std::ostream & stream, const InternalField<T> & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_INTERNAL_FIELD_HH__ */ diff --git a/src/model/solid_mechanics/materials/internal_field_tmpl.hh b/src/model/solid_mechanics/materials/internal_field_tmpl.hh index e7d11c241..f0f457b1f 100644 --- a/src/model/solid_mechanics/materials/internal_field_tmpl.hh +++ b/src/model/solid_mechanics/materials/internal_field_tmpl.hh @@ -1,305 +1,326 @@ /** * @file internal_field_tmpl.hh * * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_INTERNAL_FIELD_TMPL_HH__ #define __AKANTU_INTERNAL_FIELD_TMPL_HH__ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template<typename T> InternalField<T>::InternalField(const ID & id, Material & material) : ElementTypeMapArray<T>(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<typename T> -InternalField<T>::InternalField(const ID & id, Material & material, FEEngine & fem, +InternalField<T>::InternalField(const ID & id, + Material & material, + FEEngine & fem, const ElementTypeMapArray<UInt> & element_filter) : ElementTypeMapArray<T>(id, material.getID(), material.getMemoryID()), material(material), fem(fem), element_filter(element_filter), default_value(T()), - spatial_dimension(material.getModel().getSpatialDimension()), + spatial_dimension(material.getSpatialDimension()), + element_kind(_ek_regular), + nb_component(0), + is_init(false), + previous_values(NULL) { +} + +/* -------------------------------------------------------------------------- */ +template<typename T> +InternalField<T>::InternalField(const ID & id, + Material & material, + UInt dim, + FEEngine & fem, + const ElementTypeMapArray<UInt> & element_filter) : + ElementTypeMapArray<T>(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<typename T> InternalField<T>::InternalField(const ID & id, const InternalField<T> & other) : ElementTypeMapArray<T>(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<typename T> InternalField<T>::~InternalField() { if(this->is_init) { this->material.unregisterInternal(*this); } delete previous_values; } /* -------------------------------------------------------------------------- */ template<typename T> void InternalField<T>::initialize(UInt nb_component) { internalInitialize(nb_component); } /* -------------------------------------------------------------------------- */ template<typename T> void InternalField<T>::initializeHistory() { if(!previous_values) previous_values = new InternalField<T>("previous_" + this->getID(), *this); } /* -------------------------------------------------------------------------- */ template<typename T> void InternalField<T>::resize() { if(!this->is_init) return; for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; typename ElementTypeMapArray<UInt>::type_iterator it = element_filter.firstType(spatial_dimension, gt, element_kind); typename ElementTypeMapArray<UInt>::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.getNbQuadraturePoints(*it, gt); UInt new_size = nb_element * nb_quadrature_points; UInt old_size = 0; Array<T> * 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<typename T> void InternalField<T>::setDefaultValue(const T & value) { this->default_value = value; this->reset(); } /* -------------------------------------------------------------------------- */ template<typename T> void InternalField<T>::reset() { for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; typename ElementTypeMapArray<T>::type_iterator it = this->firstType(spatial_dimension, gt, element_kind); typename ElementTypeMapArray<T>::type_iterator end = this->lastType(spatial_dimension, gt, element_kind); for(; it != end; ++it) { Array<T> & vect = this->operator()(*it, gt); vect.clear(); this->setArrayValues(vect.storage(), vect.storage() + vect.getSize() * vect.getNbComponent()); } } } /* -------------------------------------------------------------------------- */ template<typename T> void InternalField<T>::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<UInt>::type_iterator it = element_filter.firstType(spatial_dimension, gt, element_kind); typename ElementTypeMapArray<UInt>::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.getNbQuadraturePoints(*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<typename T> void InternalField<T>::setArrayValues(T * begin, T * end) { for(; begin < end; ++begin) *begin = default_value; } /* -------------------------------------------------------------------------- */ template<typename T> void InternalField<T>::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<T>::type_iterator it = this->firstType(spatial_dimension, gt, element_kind); typename ElementTypeMapArray<T>::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<typename T> void InternalField<T>::removeQuadraturePoints(const ElementTypeMapArray<UInt> & new_numbering) { for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; ElementTypeMapArray<UInt>::type_iterator it = new_numbering.firstType(_all_dimensions, gt, _ek_not_defined); ElementTypeMapArray<UInt>::type_iterator end = new_numbering.lastType(_all_dimensions, gt, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; if(this->exists(type, gt)){ const Array<UInt> & renumbering = new_numbering(type, gt); Array<T> & vect = this->operator()(type, gt); UInt nb_quad_per_elem = fem.getNbQuadraturePoints(type, gt); UInt nb_component = vect.getNbComponent(); Array<T> 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<typename T> void InternalField<T>::printself(std::ostream & stream, unsigned int indent) const { stream << "InternalField [ " << this->getID(); #if !defined(AKANTU_NDEBUG) if(AKANTU_DEBUG_TEST(dblDump)) { stream << std::endl; InternalField<T>::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<Real> >::parseParam(const ParserParameter & in_param) { ParsableParam::parseParam(in_param); Real r = in_param; param.setDefaultValue(r); } /* -------------------------------------------------------------------------- */ template<typename T> inline InternalField<T>::operator T() const { return default_value; } __END_AKANTU__ #endif /* __AKANTU_INTERNAL_FIELD_TMPL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc index 918fd45f2..d85dfba96 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc @@ -1,696 +1,698 @@ /** * @file material_cohesive_linear.cc * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue May 08 2012 * @date last modification: Thu Aug 07 2014 * * @brief Linear irreversible cohesive law of mixed mode loading with * random stress definition for extrinsic type * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <numeric> /* -------------------------------------------------------------------------- */ #include "material_cohesive_linear.hh" #include "solid_mechanics_model_cohesive.hh" #include "sparse_matrix.hh" #include "dof_synchronizer.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialCohesiveLinear<spatial_dimension>::MaterialCohesiveLinear(SolidMechanicsModel & model, const ID & id) : MaterialCohesive(model,id), sigma_c_eff("sigma_c_eff", *this), delta_c_eff("delta_c_eff", *this), insertion_stress("insertion_stress", *this) { AKANTU_DEBUG_IN(); this->registerParam("beta" , beta , 0. , _pat_parsable | _pat_readable, "Beta parameter" ); this->registerParam("G_c" , G_c , 0. , _pat_parsable | _pat_readable, "Mode I fracture energy" ); this->registerParam("penalty", penalty, 0. , _pat_parsable | _pat_readable, "Penalty coefficient" ); this->registerParam("volume_s", volume_s, 0. , _pat_parsable | _pat_readable, "Reference volume for sigma_c scaling"); this->registerParam("m_s", m_s, 1. , _pat_parsable | _pat_readable, "Weibull exponent for sigma_c scaling"); this->registerParam("kappa" , kappa , 1. , _pat_parsable | _pat_readable, "Kappa parameter"); // if (!model->isExplicit()) use_previous_delta_max = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); MaterialCohesive::initMaterial(); /// compute scalars beta2_kappa2 = beta * beta/kappa/kappa; beta2_kappa = beta * beta/kappa; if (Math::are_float_equal(beta, 0)) beta2_inv = 0; else beta2_inv = 1./beta/beta; sigma_c_eff.initialize(1); delta_c_eff.initialize(1); insertion_stress.initialize(spatial_dimension); if (!Math::are_float_equal(delta_c, 0.)) delta_c_eff.setDefaultValue(delta_c); else delta_c_eff.setDefaultValue(2 * G_c / sigma_c); if (model->getIsExtrinsic()) scaleInsertionTraction(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::scaleInsertionTraction() { AKANTU_DEBUG_IN(); // do nothing if volume_s hasn't been specified by the user if (Math::are_float_equal(volume_s, 0.)) return; const Mesh & mesh_facets = model->getMeshFacets(); const FEEngine & fe_engine = model->getFEEngine(); const FEEngine & fe_engine_facet = model->getFEEngine("FacetsFEEngine"); // loop over facet type Mesh::type_iterator first = mesh_facets.firstType(spatial_dimension - 1); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1); Real base_sigma_c = sigma_c; for(;first != last; ++first) { ElementType type_facet = *first; const Array< std::vector<Element> > & facet_to_element = mesh_facets.getElementToSubelement(type_facet); UInt nb_facet = facet_to_element.getSize(); UInt nb_quad_per_facet = fe_engine_facet.getNbQuadraturePoints(type_facet); // iterator to modify sigma_c for all the quadrature points of a facet Array<Real>::vector_iterator sigma_c_iterator = sigma_c(type_facet).begin_reinterpret(nb_quad_per_facet, nb_facet); for (UInt f = 0; f < nb_facet; ++f, ++sigma_c_iterator) { const std::vector<Element> & element_list = facet_to_element(f); // compute bounding volume Real volume = 0; std::vector<Element>::const_iterator elem = element_list.begin(); std::vector<Element>::const_iterator elem_end = element_list.end(); for (; elem != elem_end; ++elem) { if (*elem == ElementNull) continue; // unit vector for integration in order to obtain the volume UInt nb_quadrature_points = fe_engine.getNbQuadraturePoints(elem->type); Vector<Real> unit_vector(nb_quadrature_points, 1); volume += fe_engine.integrate(unit_vector, elem->type, elem->element, elem->ghost_type); } // scale sigma_c *sigma_c_iterator -= base_sigma_c; *sigma_c_iterator *= std::pow(volume_s / volume, 1. / m_s); *sigma_c_iterator += base_sigma_c; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::checkInsertion(bool check_only) { AKANTU_DEBUG_IN(); const Mesh & mesh_facets = model->getMeshFacets(); CohesiveElementInserter & inserter = model->getElementInserter(); Real tolerance = Math::getTolerance(); Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1); for (; it != last; ++it) { ElementType type_facet = *it; ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet); const Array<bool> & facets_check = inserter.getCheckFacets(type_facet); Array<bool> & f_insertion = inserter.getInsertionFacets(type_facet); Array<UInt> & f_filter = facet_filter(type_facet); Array<Real> & sig_c_eff = sigma_c_eff(type_cohesive); Array<Real> & del_c = delta_c_eff(type_cohesive); Array<Real> & ins_stress = insertion_stress(type_cohesive); Array<Real> & trac_old = tractions_old(type_cohesive); const Array<Real> & f_stress = model->getStressOnFacets(type_facet); const Array<Real> & sigma_lim = sigma_c(type_facet); Real max_ratio = 0.; UInt index_f = 0; UInt index_filter = 0; UInt nn = 0; UInt nb_quad_facet = model->getFEEngine("FacetsFEEngine").getNbQuadraturePoints(type_facet); UInt nb_facet = f_filter.getSize(); if (nb_facet == 0) continue; Array<Real>::const_iterator<Real> sigma_lim_it = sigma_lim.begin(); Matrix<Real> stress_tmp(spatial_dimension, spatial_dimension); Matrix<Real> normal_traction(spatial_dimension, nb_quad_facet); Vector<Real> stress_check(nb_quad_facet); UInt sp2 = spatial_dimension * spatial_dimension; const Array<Real> & tangents = model->getTangents(type_facet); const Array<Real> & normals = model->getFEEngine("FacetsFEEngine").getNormalsOnQuadPoints(type_facet); Array<Real>::const_vector_iterator normal_begin = normals.begin(spatial_dimension); Array<Real>::const_vector_iterator tangent_begin = tangents.begin(tangents.getNbComponent()); Array<Real>::const_matrix_iterator facet_stress_begin = f_stress.begin(spatial_dimension, spatial_dimension * 2); std::vector<Real> new_sigmas; std::vector< Vector<Real> > new_normal_traction; std::vector<Real> new_delta_c; // loop over each facet belonging to this material for (UInt f = 0; f < nb_facet; ++f, ++sigma_lim_it) { UInt facet = f_filter(f); // skip facets where check shouldn't be realized if (!facets_check(facet)) continue; // compute the effective norm on each quadrature point of the facet for (UInt q = 0; q < nb_quad_facet; ++q) { UInt current_quad = facet * nb_quad_facet + q; const Vector<Real> & normal = normal_begin[current_quad]; const Vector<Real> & tangent = tangent_begin[current_quad]; const Matrix<Real> & facet_stress_it = facet_stress_begin[current_quad]; // compute average stress on the current quadrature point Matrix<Real> stress_1(facet_stress_it.storage(), spatial_dimension, spatial_dimension); Matrix<Real> stress_2(facet_stress_it.storage() + sp2, spatial_dimension, spatial_dimension); stress_tmp.copy(stress_1); stress_tmp += stress_2; stress_tmp /= 2.; Vector<Real> normal_traction_vec(normal_traction(q)); // compute normal and effective stress stress_check(q) = computeEffectiveNorm(stress_tmp, normal, tangent, normal_traction_vec); } // verify if the effective stress overcomes the threshold if (stress_check.mean() > (*sigma_lim_it - tolerance)) { if (model->isExplicit()){ f_insertion(facet) = true; if (!check_only) { // store the new cohesive material parameters for each quadrature point for (UInt q = 0; q < nb_quad_facet; ++q) { Real new_sigma = stress_check(q); Vector<Real> normal_traction_vec(normal_traction(q)); if (spatial_dimension != 3) normal_traction_vec *= -1.; new_sigmas.push_back(new_sigma); new_normal_traction.push_back(normal_traction_vec); Real new_delta; // set delta_c in function of G_c or a given delta_c value if (Math::are_float_equal(delta_c, 0.)) new_delta = 2 * G_c / new_sigma; else new_delta = (*sigma_lim_it) / new_sigma * delta_c; new_delta_c.push_back(new_delta); } } }else{ Real ratio = stress_check.mean()/(*sigma_lim_it); if (ratio > max_ratio){ + std::cout << "ratio = " << ratio << std::endl; ++nn; max_ratio = ratio; index_f = f; index_filter = f_filter(f); } } } } /// insertion of only 1 cohesive element in case of implicit approach. The one subjected to the highest stress. if (!model->isExplicit()){ StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Array<Real> abs_max(comm.getNbProc()); abs_max(comm.whoAmI()) = max_ratio; comm.allGather(abs_max.storage(), 1); Array<Real>::scalar_iterator it = std::max_element(abs_max.begin(), abs_max.end()); Int pos = it - abs_max.begin(); if (pos != comm.whoAmI()) { AKANTU_DEBUG_OUT(); return; } if (nn) { f_insertion(index_filter) = true; if (!check_only) { // Array<Real>::iterator<Matrix<Real> > normal_traction_it = // normal_traction.begin_reinterpret(nb_quad_facet, spatial_dimension, nb_facet); Array<Real>::const_iterator<Real> sigma_lim_it = sigma_lim.begin(); for (UInt q = 0; q < nb_quad_facet; ++q) { // Vector<Real> ins_s(normal_traction_it[index_f].storage() + q * spatial_dimension, // spatial_dimension); Real new_sigma = (sigma_lim_it[index_f]); + Vector<Real> normal_traction_vec(spatial_dimension, 0.0); new_sigmas.push_back(new_sigma); - new_normal_traction.push_back(0.0); + new_normal_traction.push_back(normal_traction_vec); Real new_delta; //set delta_c in function of G_c or a given delta_c value if (!Math::are_float_equal(delta_c, 0.)) new_delta = delta_c; else new_delta = 2 * G_c / (new_sigma); new_delta_c.push_back(new_delta); } } } } // update material data for the new elements UInt old_nb_quad_points = sig_c_eff.getSize(); UInt new_nb_quad_points = new_sigmas.size(); sig_c_eff.resize(old_nb_quad_points + new_nb_quad_points); ins_stress.resize(old_nb_quad_points + new_nb_quad_points); trac_old.resize(old_nb_quad_points + new_nb_quad_points); del_c.resize(old_nb_quad_points + new_nb_quad_points); for (UInt q = 0; q < new_nb_quad_points; ++q) { sig_c_eff(old_nb_quad_points + q) = new_sigmas[q]; del_c(old_nb_quad_points + q) = new_delta_c[q]; for (UInt dim = 0; dim < spatial_dimension; ++dim) { ins_stress(old_nb_quad_points + q, dim) = new_normal_traction[q](dim); trac_old(old_nb_quad_points + q, dim) = new_normal_traction[q](dim); } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::computeTraction(const Array<Real> & normal, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::iterator< Vector<Real> > traction_it = tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::iterator< Vector<Real> > opening_it = opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::iterator< Vector<Real> > contact_traction_it = contact_tractions(el_type, ghost_type).begin(spatial_dimension); Array<Real>::iterator< Vector<Real> > contact_opening_it = contact_opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::const_iterator< Vector<Real> > normal_it = normal.begin(spatial_dimension); Array<Real>::iterator< Vector<Real> >traction_end = tractions(el_type, ghost_type).end(spatial_dimension); Array<Real>::iterator<Real>sigma_c_it = sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::iterator<Real>delta_max_it = delta_max(el_type, ghost_type).begin(); Array<Real>::iterator<Real>delta_max_prev_it = delta_max.previous(el_type, ghost_type).begin(); Array<Real>::iterator<Real>delta_c_it = delta_c_eff(el_type, ghost_type).begin(); Array<Real>::iterator<Real>damage_it = damage(el_type, ghost_type).begin(); Array<Real>::iterator<Vector<Real> > insertion_stress_it = insertion_stress(el_type, ghost_type).begin(spatial_dimension); Real * memory_space = new Real[2*spatial_dimension]; Vector<Real> normal_opening(memory_space, spatial_dimension); Vector<Real> tangential_opening(memory_space + spatial_dimension, spatial_dimension); /// loop on each quadrature point for (; traction_it != traction_end; ++traction_it, ++opening_it, ++normal_it, ++sigma_c_it, ++delta_max_it, ++delta_c_it, ++damage_it, ++contact_traction_it, ++insertion_stress_it, ++contact_opening_it, ++delta_max_prev_it) { if (!model->isExplicit()) *delta_max_it = *delta_max_prev_it; /// compute normal and tangential opening vectors Real normal_opening_norm = opening_it->dot(*normal_it); normal_opening = (*normal_it); normal_opening *= normal_opening_norm; tangential_opening = *opening_it; tangential_opening -= normal_opening; Real tangential_opening_norm = tangential_opening.norm(); /** * compute effective opening displacement * @f$ \delta = \sqrt{ * \frac{\beta^2}{\kappa^2} \Delta_t^2 + \Delta_n^2 } @f$ */ Real delta = tangential_opening_norm * tangential_opening_norm * beta2_kappa2; bool penetration = normal_opening_norm < -Math::getTolerance(); if (penetration) { /// use penalty coefficient in case of penetration *contact_traction_it = normal_opening; *contact_traction_it *= penalty; *contact_opening_it = normal_opening; /// don't consider penetration contribution for delta *opening_it = tangential_opening; normal_opening.clear(); } else { delta += normal_opening_norm * normal_opening_norm; contact_traction_it->clear(); contact_opening_it->clear(); } delta = std::sqrt(delta); /// update maximum displacement and damage *delta_max_it = std::max(*delta_max_it, delta); *damage_it = std::min(*delta_max_it / *delta_c_it, 1.); /** * Compute traction @f$ \mathbf{T} = \left( * \frac{\beta^2}{\kappa} \Delta_t \mathbf{t} + \Delta_n * \mathbf{n} \right) \frac{\sigma_c}{\delta} \left( 1- * \frac{\delta}{\delta_c} \right)@f$ */ if (Math::are_float_equal(*damage_it, 1.)) traction_it->clear(); else if (Math::are_float_equal(*damage_it, 0.)) { if (penetration) traction_it->clear(); else *traction_it = *insertion_stress_it; } else { *traction_it = tangential_opening; *traction_it *= beta2_kappa; *traction_it += normal_opening; AKANTU_DEBUG_ASSERT(*delta_max_it != 0., "Division by zero, tolerance might be too low"); *traction_it *= *sigma_c_it / *delta_max_it * (1. - *damage_it); } } delete [] memory_space; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::checkDeltaMax(GhostType ghost_type) { AKANTU_DEBUG_IN(); /// This function set a predefined value to the parameter delta_max_prev of the /// elements that have been inserted in the last loading step for which convergence /// has not been reached. This is done before reducing the loading and re-doing the step. /// Otherwise, the updating of delta_max_prev would be done with reference to the /// non-convergent solution. Mesh & mesh = fem_cohesive->getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type, _ek_cohesive); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type, _ek_cohesive); for(; it != last_type; ++it) { Array<UInt> & elem_filter = element_filter(*it, ghost_type); UInt nb_element = elem_filter.getSize(); if (nb_element == 0) continue; ElementType el_type = *it; /// define iterators Array<Real>::iterator<Real>delta_max_it = delta_max(el_type, ghost_type).begin(); Array<Real>::iterator<Real>delta_max_end = delta_max(el_type, ghost_type).end(); Array<Real>::iterator<Real>delta_max_prev_it = delta_max.previous(el_type, ghost_type).begin(); Array<Real>::iterator<Real>delta_c_it = delta_c_eff(el_type, ghost_type).begin(); /// loop on each quadrature point for (; delta_max_it != delta_max_end; ++delta_max_it, ++delta_max_prev_it, ++delta_c_it) { if (*delta_max_prev_it == 0) /// elements inserted in the last step, that has not converged *delta_max_it = *delta_c_it / 1000; else /// elements introduced in previous steps, for which a correct /// value of delta_max_prev already exists *delta_max_it = *delta_max_prev_it; } } } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialCohesiveLinear<spatial_dimension>::computeTangentTraction(const ElementType & el_type, Array<Real> & tangent_matrix, const Array<Real> & normal, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array<Real>::matrix_iterator tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension); Array<Real>::const_vector_iterator normal_it = normal.begin(spatial_dimension); Array<Real>::vector_iterator opening_it = opening(el_type, ghost_type).begin(spatial_dimension); Array<Real>::iterator<Real>delta_max_it = delta_max.previous(el_type, ghost_type).begin(); Array<Real>::iterator<Real>sigma_c_it = sigma_c_eff(el_type, ghost_type).begin(); Array<Real>::iterator<Real>delta_c_it = delta_c_eff(el_type, ghost_type).begin(); Array<Real>::iterator<Real>damage_it = damage(el_type, ghost_type).begin(); Array<Real>::iterator< Vector<Real> > contact_opening_it = contact_opening(el_type, ghost_type).begin(spatial_dimension); Vector<Real> normal_opening(spatial_dimension); Vector<Real> tangential_opening(spatial_dimension); Array<Real> tang_output(spatial_dimension,spatial_dimension); for (; tangent_it != tangent_end; ++tangent_it, ++normal_it, ++opening_it, ++ delta_max_it, ++sigma_c_it, ++delta_c_it, ++damage_it, ++contact_opening_it) { /// compute normal and tangential opening vectors *opening_it += *contact_opening_it; Real normal_opening_norm = opening_it->dot(*normal_it); normal_opening = (*normal_it); normal_opening *= normal_opening_norm; tangential_opening = *opening_it; tangential_opening -= normal_opening; Real tangential_opening_norm = tangential_opening.norm(); bool penetration = normal_opening_norm < -Math::getTolerance(); Real derivative = 0; Real t = 0; Real delta = tangential_opening_norm * tangential_opening_norm * beta2_kappa2; delta += normal_opening_norm * normal_opening_norm; delta = std::sqrt(delta); /// Delta has to be different from 0 to have finite values of tangential stiffness. /// At the element insertion, delta = 0. Therefore, a fictictious value is defined, /// for the evaluation of the first value of K. if (delta < Math::getTolerance()) delta = (*delta_c_it)/1000.; if (normal_opening_norm >= 0.0){ if (delta >= *delta_max_it){ derivative = -*sigma_c_it/(delta * delta); t = *sigma_c_it * (1 - delta / *delta_c_it); } else if (delta < *delta_max_it){ Real tmax = *sigma_c_it * (1 - *delta_max_it / *delta_c_it); t = tmax / *delta_max_it * delta; } } Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension); n_outer_n.outerProduct(*normal_it, *normal_it); if (penetration){ /// don't consider penetration contribution for delta *opening_it = tangential_opening; /// stiffness in compression given by the penalty parameter *tangent_it += n_outer_n; *tangent_it *= penalty; } /// computation of the derivative of the constitutive law (dT/ddelta) Matrix<Real> I(spatial_dimension, spatial_dimension); I.eye(beta2_kappa); Matrix<Real> nn(n_outer_n); nn *= (1 - beta2_kappa); nn += I; nn *= t/delta; Vector<Real> t_tilde(normal_opening); t_tilde *= (1 - beta2_kappa2); Vector<Real> mm(*opening_it); mm *= beta2_kappa2; t_tilde += mm; Vector<Real> t_hat(normal_opening); t_hat += beta2_kappa * tangential_opening; Matrix<Real> prov(spatial_dimension, spatial_dimension); prov.outerProduct(t_hat, t_tilde); prov *= derivative/delta; prov += nn; *tangent_it += prov; /// check if the tangential stiffness matrix is symmetric for (UInt h = 0; h < spatial_dimension; ++h){ for (UInt l = h; l < spatial_dimension; ++l){ if (l > h){ Real k_ls = (*tangent_it)[spatial_dimension*h+l]; Real k_us = (*tangent_it)[spatial_dimension*l+h]; // std::cout << "k_ls = " << k_ls << std::endl; // std::cout << "k_us = " << k_us << std::endl; if (std::abs(k_ls) > 1e-13 && std::abs(k_us) > 1e-13){ Real error = std::abs((k_ls - k_us) / k_us); if (error > 1e-13){ std::cout << "non symmetric cohesive matrix" << std::endl; std::cout << "error " << error << std::endl; } } } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialCohesiveLinear); __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_elastic.cc b/src/model/solid_mechanics/materials/material_elastic.cc index 4787baf68..999bc7e93 100644 --- a/src/model/solid_mechanics/materials/material_elastic.cc +++ b/src/model/solid_mechanics/materials/material_elastic.cc @@ -1,229 +1,248 @@ /** * @file material_elastic.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Marco Vocialta <marco.vocialta@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Sep 16 2014 * * @brief Specialization of the material class for the elastic material * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_elastic.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template<UInt dim> MaterialElastic<dim>::MaterialElastic(SolidMechanicsModel & model, const ID & id) : Material(model, id), Parent(model, id) { AKANTU_DEBUG_IN(); + this->initialize(); + AKANTU_DEBUG_OUT(); +} +/* -------------------------------------------------------------------------- */ +template<UInt dim> +MaterialElastic<dim>::MaterialElastic(SolidMechanicsModel & model, + UInt a_dim, + const Mesh & mesh, + FEEngine & fe_engine, + const ID & id) : + Material(model, dim, mesh, fe_engine, id), + Parent(model, dim, mesh, fe_engine, id) { + AKANTU_DEBUG_IN(); + this->initialize(); + AKANTU_DEBUG_OUT(); +} + +/* -------------------------------------------------------------------------- */ +template<UInt dim> +void MaterialElastic<dim>::initialize() { this->registerParam("lambda" ,lambda , _pat_readable, "First Lamé coefficient" ); this->registerParam("mu" ,mu , _pat_readable, "Second Lamé coefficient"); this->registerParam("kapa" ,kpa , _pat_readable, "Bulk coefficient" ); - - AKANTU_DEBUG_OUT(); } + /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialElastic<dim>::initMaterial() { AKANTU_DEBUG_IN(); Parent::initMaterial(); - if (dim == 1) this->nu = 0.; + if (dim == 1) this->nu = 0.5; this->updateInternalParameters(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialElastic<dim>::updateInternalParameters() { MaterialThermal<dim>::updateInternalParameters(); this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2*this->nu)); this->mu = this->E / (2 * (1 + this->nu)); this->kpa = this->lambda + 2./3. * this->mu; } /* -------------------------------------------------------------------------- */ template<> void MaterialElastic<2>::updateInternalParameters() { MaterialThermal<2>::updateInternalParameters(); this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2*this->nu)); this->mu = this->E / (2 * (1 + this->nu)); if(this->plane_stress) this->lambda = this->nu * this->E / ((1 + this->nu)*(1 - this->nu)); this->kpa = this->lambda + 2./3. * this->mu; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialElastic<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Parent::computeStress(el_type, ghost_type); Array<Real>::const_scalar_iterator sigma_th_it = this->sigma_th(el_type, ghost_type).begin(); if (!this->finite_deformation) { MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); const Real & sigma_th = *sigma_th_it; this->computeStressOnQuad(grad_u, sigma, sigma_th); ++sigma_th_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } else { /// finite gradus Matrix<Real> E(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); /// compute E this->template gradUToGreenStrain<spatial_dimension>(grad_u, E); const Real & sigma_th = *sigma_th_it; /// compute second Piola-Kirchhoff stress tensor this->computeStressOnQuad(E, sigma, sigma_th); ++sigma_th_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialElastic<spatial_dimension>::computeTangentModuli(__attribute__((unused)) const ElementType & el_type, Array<Real> & tangent_matrix, __attribute__((unused)) GhostType ghost_type) { AKANTU_DEBUG_IN(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); this->computeTangentModuliOnQuad(tangent); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialElastic<spatial_dimension>::getPushWaveSpeed(__attribute__((unused)) const Element & element) const { return sqrt((lambda + 2*mu)/this->rho); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialElastic<spatial_dimension>::getShearWaveSpeed(__attribute__((unused)) const Element & element) const { return sqrt(mu/this->rho); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialElastic<spatial_dimension>::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialThermal<spatial_dimension>::computePotentialEnergy(el_type, ghost_type); if(ghost_type != _not_ghost) return; Array<Real>::scalar_iterator epot = this->potential_energy(el_type, ghost_type).begin(); if (!this->finite_deformation) { MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); this->computePotentialEnergyOnQuad(grad_u, sigma, *epot); ++epot; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } else { Matrix<Real> E(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); this->template gradUToGreenStrain<spatial_dimension>(grad_u, E); this->computePotentialEnergyOnQuad(E, sigma, *epot); ++epot; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialElastic<spatial_dimension>::computePotentialEnergyByElement(ElementType type, UInt index, Vector<Real> & epot_on_quad_points) { Array<Real>::matrix_iterator gradu_it = this->gradu(type).begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator gradu_end = this->gradu(type).begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator stress_it = this->stress(type).begin(spatial_dimension, spatial_dimension); if (this->finite_deformation) stress_it = this->piola_kirchhoff_2(type).begin(spatial_dimension, spatial_dimension); UInt nb_quadrature_points = this->model->getFEEngine().getNbQuadraturePoints(type); gradu_it += index*nb_quadrature_points; gradu_end += (index+1)*nb_quadrature_points; stress_it += index*nb_quadrature_points; Real * epot_quad = epot_on_quad_points.storage(); Matrix<Real> grad_u(spatial_dimension, spatial_dimension); for(;gradu_it != gradu_end; ++gradu_it, ++stress_it, ++epot_quad) { if (this->finite_deformation) this->template gradUToGreenStrain<spatial_dimension>(*gradu_it, grad_u); else grad_u.copy(*gradu_it); this->computePotentialEnergyOnQuad(grad_u, *stress_it, *epot_quad); } } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialElastic); __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_elastic.hh b/src/model/solid_mechanics/materials/material_elastic.hh index 5f9f0f810..9b0702649 100644 --- a/src/model/solid_mechanics/materials/material_elastic.hh +++ b/src/model/solid_mechanics/materials/material_elastic.hh @@ -1,140 +1,148 @@ /** * @file material_elastic.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #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<UInt spatial_dimension> class MaterialElastic : public PlaneStressToolbox< spatial_dimension, MaterialThermal<spatial_dimension> > { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ private: typedef PlaneStressToolbox< spatial_dimension, MaterialThermal<spatial_dimension> > 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<Real> & 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<Real> & 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<Real> & grad_u, Matrix<Real> & sigma, const Real sigma_th = 0) const; /// compute the tangent stiffness matrix for an element - inline void computeTangentModuliOnQuad(Matrix<Real> & tangent); + inline void computeTangentModuliOnQuad(Matrix<Real> & tangent) const; /// recompute the lame coefficient if E or nu changes virtual void updateInternalParameters(); static inline void computePotentialEnergyOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & sigma, Real & epot); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* 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_elastic_inline_impl.cc b/src/model/solid_mechanics/materials/material_elastic_inline_impl.cc index 8f3bc379d..829b7ac36 100644 --- a/src/model/solid_mechanics/materials/material_elastic_inline_impl.cc +++ b/src/model/solid_mechanics/materials/material_elastic_inline_impl.cc @@ -1,107 +1,107 @@ /** * @file material_elastic_inline_impl.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Wed Aug 04 2010 * @date last modification: Mon Apr 07 2014 * * @brief Implementation of the inline functions of the material 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> inline void MaterialElastic<spatial_dimension>::computeStressOnQuad(const Matrix<Real> & grad_u, Matrix<Real> & sigma, const Real sigma_th) const { Real trace = grad_u.trace(); // trace = (\nabla u)_{kk} // \sigma_{ij} = \lambda * (\nabla u)_{kk} * \delta_{ij} + \mu * (\nabla u_{ij} + \nabla u_{ji}) for (UInt i = 0; i < spatial_dimension; ++i) { for (UInt j = 0; j < spatial_dimension; ++j) { sigma(i, j) = (i == j)*lambda*trace + mu*(grad_u(i, j) + grad_u(j, i)) + (i == j) * sigma_th; } } } /* -------------------------------------------------------------------------- */ template<> inline void MaterialElastic<1>::computeStressOnQuad(const Matrix<Real> & grad_u, Matrix<Real> & sigma, Real sigma_th) const { sigma(0, 0) = this->E * grad_u(0, 0) + sigma_th; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> -inline void MaterialElastic<spatial_dimension>::computeTangentModuliOnQuad(Matrix<Real> & tangent) { +inline void MaterialElastic<spatial_dimension>::computeTangentModuliOnQuad(Matrix<Real> & tangent) const { UInt n = tangent.cols(); //Real Ep = E/((1+nu)*(1-2*nu)); Real Miiii = lambda + 2*mu; Real Miijj = lambda; Real Mijij = mu; if(spatial_dimension == 1) tangent(0, 0) = this->E; else tangent(0, 0) = Miiii; // test of dimension should by optimized out by the compiler due to the template if(spatial_dimension >= 2) { tangent(1, 1) = Miiii; tangent(0, 1) = Miijj; tangent(1, 0) = Miijj; tangent(n - 1, n - 1) = Mijij; } if(spatial_dimension == 3) { tangent(2, 2) = Miiii; tangent(0, 2) = Miijj; tangent(1, 2) = Miijj; tangent(2, 0) = Miijj; tangent(2, 1) = Miijj; tangent(3, 3) = Mijij; tangent(4, 4) = Mijij; } } /* -------------------------------------------------------------------------- */ template<UInt dim> inline void MaterialElastic<dim>::computePotentialEnergyOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & sigma, Real & epot) { epot = .5 * sigma.doubleDot(grad_u); } /* -------------------------------------------------------------------------- */ template<> -inline void MaterialElastic<1>::computeTangentModuliOnQuad(Matrix<Real> & tangent) { +inline void MaterialElastic<1>::computeTangentModuliOnQuad(Matrix<Real> & tangent) const { tangent(0, 0) = E; } diff --git a/src/model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh b/src/model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh index 6370db542..3c20a1b5e 100644 --- a/src/model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh +++ b/src/model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh @@ -1,43 +1,43 @@ /** * @file material_embedded_includes.hh * * @author Lucas Frérot <lucas.frerot@epfl.ch> * * @date creation: Fri Mar 13 2015 * @date last modification: Fri Mar 13 2015 * * @brief List of includes for embedded elements * * @section LICENSE * * Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef AKANTU_CMAKE_LIST_MATERIALS # include "material_reinforcement.hh" # include "material_reinforcement_template.hh" #endif #define AKANTU_MATERIAL_REINFORCEMENT_LAW_TMPL_LIST \ - ((elastic, (MaterialElastic<1>))) - //((plastic_law, (MaterialLinearIsotropicHardening ))) + ((elastic, (MaterialElastic<1>))) \ + ((plastic, (MaterialLinearIsotropicHardening<1>))) #define AKANTU_EMBEDDED_MATERIAL_LIST \ ((3, (reinforcement, MaterialReinforcementTemplate, \ AKANTU_MATERIAL_REINFORCEMENT_LAW_TMPL_LIST ))) diff --git a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.cc b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.cc index acc78525e..552ba3bd3 100644 --- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.cc +++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.cc @@ -1,744 +1,758 @@ /** * @file material_reinforcement.cc * * @author Lucas Frérot <lucas.frerot@epfl.ch> * * @date creation: Thu Mar 12 2015 * @date last modification: Thu Mar 12 2015 * * @brief Reinforcement material * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_voigthelper.hh" #include "material_reinforcement.hh" __BEGIN_AKANTU__ +/* -------------------------------------------------------------------------- */ template<UInt dim> -MaterialReinforcement<dim>::MaterialReinforcement(SolidMechanicsModel & model, const ID & id): - Material(model, id), +MaterialReinforcement<dim>::MaterialReinforcement(SolidMechanicsModel & model, + UInt spatial_dimension, + const Mesh & mesh, + FEEngine & fe_engine, + const ID & id) : + Material(model, dim, mesh, fe_engine, id), // /!\ dim, not spatial_dimension ! model(NULL), - gradu("gradu_embedded", *this), - stress("stress_embedded", *this), - directing_cosines("directing_cosines", *this), - pre_stress("pre_stress", *this), + stress_embedded("stress_embedded", *this, 1, fe_engine, this->element_filter), + gradu_embedded("gradu_embedded", *this, 1, fe_engine, this->element_filter), + directing_cosines("directing_cosines", *this, 1, fe_engine, this->element_filter), + pre_stress("pre_stress", *this, 1, fe_engine, this->element_filter), area(1.0), - shape_derivatives() -{ - this->model = dynamic_cast<EmbeddedInterfaceModel *>(&model); + shape_derivatives() { + AKANTU_DEBUG_IN(); + this->initialize(model); + AKANTU_DEBUG_OUT(); +} + +/* -------------------------------------------------------------------------- */ +template<UInt dim> +void MaterialReinforcement<dim>::initialize(SolidMechanicsModel & a_model) { + this->model = dynamic_cast<EmbeddedInterfaceModel *>(&a_model); AKANTU_DEBUG_ASSERT(this->model != NULL, "MaterialReinforcement needs an EmbeddedInterfaceModel"); - this->model->getInterfaceMesh().initElementTypeMapArray(element_filter, 1, 1, - false, _ek_regular); + this->registerParam("area", area, _pat_parsable | _pat_modifiable, + "Reinforcement cross-sectional area"); + this->registerParam("pre_stress", pre_stress, _pat_parsable | _pat_modifiable, + "Uniform pre-stress"); - this->registerParam("area", area, _pat_parsable | _pat_modifiable, "Reinforcement cross-sectional area"); - this->registerParam("pre_stress", pre_stress, _pat_parsable | _pat_modifiable, "Uniform pre-stress"); + this->element_filter.free(); + this->model->getInterfaceMesh().initElementTypeMapArray(this->element_filter, + 1, 1, false, _ek_regular); } /* -------------------------------------------------------------------------- */ template<UInt dim> MaterialReinforcement<dim>::~MaterialReinforcement() { AKANTU_DEBUG_IN(); ElementTypeMap<ElementTypeMapArray<Real> *>::type_iterator it = shape_derivatives.firstType(); ElementTypeMap<ElementTypeMapArray<Real> *>::type_iterator end = shape_derivatives.lastType(); for (; it != end ; ++it) { delete shape_derivatives(*it, _not_ghost); delete shape_derivatives(*it, _ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialReinforcement<dim>::initMaterial() { Material::initMaterial(); - gradu.initialize(dim * dim); - stress.initialize(dim * dim); + stress_embedded.initialize(dim * dim); // Check this + gradu_embedded.initialize(dim * dim); pre_stress.initialize(1); - /// We initialise the stuff that is not going to change during the simulation this->allocBackgroundShapeDerivatives(); this->initBackgroundShapeDerivatives(); this->initDirectingCosines(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialReinforcement<dim>::allocBackgroundShapeDerivatives() { AKANTU_DEBUG_IN(); Mesh & interface_mesh = model->getInterfaceMesh(); Mesh & mesh = model->getMesh(); ghost_type_t::iterator int_ghost_it = ghost_type_t::begin(); // Loop over interface ghosts for (; int_ghost_it != ghost_type_t::end() ; ++int_ghost_it) { - Mesh::type_iterator interface_type_it = interface_mesh.firstType(); - Mesh::type_iterator interface_type_end = interface_mesh.lastType(); + Mesh::type_iterator interface_type_it = interface_mesh.firstType(1, *int_ghost_it); + Mesh::type_iterator interface_type_end = interface_mesh.lastType(1, *int_ghost_it); for (; interface_type_it != interface_type_end ; ++interface_type_it) { Mesh::type_iterator background_type_it = mesh.firstType(dim, *int_ghost_it); Mesh::type_iterator background_type_end = mesh.lastType(dim, *int_ghost_it); for (; background_type_it != background_type_end ; ++background_type_it) { const ElementType & int_type = *interface_type_it; const ElementType & back_type = *background_type_it; const GhostType & int_ghost = *int_ghost_it; std::string shaped_id = "embedded_shape_derivatives"; if (int_ghost == _ghost) shaped_id += ":ghost"; ElementTypeMapArray<Real> * shaped_etma = new ElementTypeMapArray<Real>(shaped_id, this->name); UInt nb_points = Mesh::getNbNodesPerElement(back_type); UInt nb_quad_points = model->getFEEngine("EmbeddedInterfaceFEEngine").getNbQuadraturePoints(int_type); UInt nb_elements = element_filter(int_type, int_ghost).getSize(); shaped_etma->alloc(nb_elements * nb_quad_points, dim * nb_points, back_type); shape_derivatives(shaped_etma, int_type, int_ghost); } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialReinforcement<dim>::initBackgroundShapeDerivatives() { AKANTU_DEBUG_IN(); Mesh & mesh = model->getMesh(); Mesh::type_iterator type_it = mesh.firstType(dim, _not_ghost); Mesh::type_iterator type_end = mesh.lastType(dim, _not_ghost); for (; type_it != type_end ; ++type_it) { computeBackgroundShapeDerivatives(*type_it, _not_ghost); //computeBackgroundShapeDerivatives(*type_it, _ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialReinforcement<dim>::initDirectingCosines() { AKANTU_DEBUG_IN(); Mesh & mesh = model->getInterfaceMesh(); Mesh::type_iterator type_it = mesh.firstType(1, _not_ghost); Mesh::type_iterator type_end = mesh.lastType(1, _not_ghost); const UInt voigt_size = getTangentStiffnessVoigtSize(dim); directing_cosines.initialize(voigt_size * voigt_size); for (; type_it != type_end ; ++type_it) { computeDirectingCosines(*type_it, _not_ghost); computeDirectingCosines(*type_it, _ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialReinforcement<dim>::assembleStiffnessMatrix(GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh & interface_mesh = model->getInterfaceMesh(); - Mesh::type_iterator type_it = interface_mesh.firstType(); - Mesh::type_iterator type_end = interface_mesh.lastType(); + Mesh::type_iterator type_it = interface_mesh.firstType(1, _not_ghost); + Mesh::type_iterator type_end = interface_mesh.lastType(1, _not_ghost); for (; type_it != type_end ; ++type_it) { assembleStiffnessMatrix(*type_it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialReinforcement<dim>::updateResidual(GhostType ghost_type) { AKANTU_DEBUG_IN(); computeAllStresses(ghost_type); assembleResidual(ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialReinforcement<dim>::assembleResidual(GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh & interface_mesh = model->getInterfaceMesh(); - Mesh::type_iterator type_it = interface_mesh.firstType(); - Mesh::type_iterator type_end = interface_mesh.lastType(); + Mesh::type_iterator type_it = interface_mesh.firstType(1, _not_ghost); + Mesh::type_iterator type_end = interface_mesh.lastType(1, _not_ghost); for (; type_it != type_end ; ++type_it) { assembleResidual(*type_it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialReinforcement<dim>::computeGradU(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<UInt> & elem_filter = element_filter(type, ghost_type); UInt nb_element = elem_filter.getSize(); UInt nb_quad_points = model->getFEEngine("EmbeddedInterfaceFEEngine").getNbQuadraturePoints(type); - Array<Real> & gradu_vec = gradu(type, ghost_type); + Array<Real> & gradu_vec = gradu_embedded(type, ghost_type); Mesh::type_iterator back_it = model->getMesh().firstType(dim, ghost_type); Mesh::type_iterator back_end = model->getMesh().lastType(dim, ghost_type); for (; back_it != back_end ; ++back_it) { UInt nodes_per_background_e = Mesh::getNbNodesPerElement(*back_it); Array<Real> & shapesd = shape_derivatives(type, ghost_type)->operator()(*back_it, ghost_type); Array<UInt> * background_filter = new Array<UInt>(nb_element, 1, "background_filter"); filterInterfaceBackgroundElements(*background_filter, *back_it, type, ghost_type, ghost_type); Array<Real> * disp_per_element = new Array<Real>(0, dim * nodes_per_background_e, "disp_elem"); FEEngine::extractNodalToElementField(model->getMesh(), model->getDisplacement(), *disp_per_element, *back_it, ghost_type, *background_filter); Array<Real>::matrix_iterator disp_it = disp_per_element->begin(dim, nodes_per_background_e); Array<Real>::matrix_iterator disp_end = disp_per_element->end(dim, nodes_per_background_e); Array<Real>::matrix_iterator shapes_it = shapesd.begin(dim, nodes_per_background_e); Array<Real>::matrix_iterator grad_u_it = gradu_vec.begin(dim, dim); for (; disp_it != disp_end ; ++disp_it) { for (UInt i = 0; i < nb_quad_points; i++, ++shapes_it, ++grad_u_it) { Matrix<Real> & B = *shapes_it; Matrix<Real> & du = *grad_u_it; Matrix<Real> & u = *disp_it; du.mul<false, true>(u, B); } } delete background_filter; delete disp_per_element; } AKANTU_DEBUG_OUT(); } template<UInt dim> void MaterialReinforcement<dim>::computeAllStresses(GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh::type_iterator it = model->getInterfaceMesh().firstType(); Mesh::type_iterator last_type = model->getInterfaceMesh().lastType(); for(; it != last_type; ++it) { computeGradU(*it, ghost_type); computeStress(*it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialReinforcement<dim>::assembleResidual(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh & mesh = model->getMesh(); Mesh::type_iterator type_it = mesh.firstType(dim, ghost_type); Mesh::type_iterator type_end = mesh.lastType(dim, ghost_type); for (; type_it != type_end ; ++type_it) { assembleResidual(type, *type_it, ghost_type, _not_ghost); //assembleResidual(type, *type_it, ghost_type, _ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialReinforcement<dim>::assembleResidual(const ElementType & interface_type, const ElementType & background_type, GhostType interface_ghost, GhostType background_ghost) { AKANTU_DEBUG_IN(); UInt voigt_size = getTangentStiffnessVoigtSize(dim); Array<Real> & residual = const_cast<Array<Real> &>(model->getResidual()); FEEngine & interface_engine = model->getFEEngine("EmbeddedInterfaceFEEngine"); FEEngine & background_engine = model->getFEEngine(); Array<UInt> & elem_filter = element_filter(interface_type, interface_ghost); UInt nodes_per_background_e = Mesh::getNbNodesPerElement(background_type); UInt nb_quadrature_points = interface_engine.getNbQuadraturePoints(interface_type, interface_ghost); UInt nb_element = elem_filter.getSize(); UInt back_dof = dim * nodes_per_background_e; Array<Real> & shapesd = shape_derivatives(interface_type, interface_ghost)->operator()(background_type, background_ghost); Array<Real> * integrant = new Array<Real>(nb_quadrature_points * nb_element, back_dof, "integrant"); Array<Real>::vector_iterator integrant_it = integrant->begin(back_dof); Array<Real>::vector_iterator integrant_end = integrant->end(back_dof); Array<Real>::matrix_iterator B_it = shapesd.begin(dim, nodes_per_background_e); Array<Real>::matrix_iterator C_it = directing_cosines(interface_type, interface_ghost).begin(voigt_size, voigt_size); Array<Real>::matrix_iterator sigma_it = - stress(interface_type, interface_ghost).begin(dim, dim); + stress_embedded(interface_type, interface_ghost).begin(dim, dim); Vector<Real> sigma(voigt_size); Matrix<Real> Bvoigt(voigt_size, back_dof); Vector<Real> Ct_sigma(voigt_size); for (; integrant_it != integrant_end ; ++integrant_it, ++B_it, ++C_it, ++sigma_it) { VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(*B_it, Bvoigt, nodes_per_background_e); Matrix<Real> & C = *C_it; Vector<Real> & BtCt_sigma = *integrant_it; stressTensorToVoigtVector(*sigma_it, sigma); Ct_sigma.mul<true>(C, sigma); BtCt_sigma.mul<true>(Bvoigt, Ct_sigma); BtCt_sigma *= area; } Array<Real> * residual_interface = new Array<Real>(nb_element, back_dof, "residual_interface"); interface_engine.integrate(*integrant, *residual_interface, back_dof, interface_type, interface_ghost, elem_filter); delete integrant; Array<UInt> * background_filter = new Array<UInt>(nb_element, 1, "background_filter"); filterInterfaceBackgroundElements(*background_filter, background_type, interface_type, background_ghost, interface_ghost); background_engine.assembleArray(*residual_interface, residual, model->getDOFSynchronizer().getLocalDOFEquationNumbers(), dim, background_type, background_ghost, *background_filter, -1.0); delete residual_interface; delete background_filter; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialReinforcement<dim>::filterInterfaceBackgroundElements(Array<UInt> & filter, const ElementType & type, const ElementType & interface_type, GhostType ghost_type, GhostType interface_ghost_type) { AKANTU_DEBUG_IN(); filter.resize(0); filter.clear(); Array<Element> & elements = model->getInterfaceAssociatedElements(interface_type, interface_ghost_type); Array<UInt> & elem_filter = element_filter(interface_type, interface_ghost_type); Array<UInt>::scalar_iterator filter_it = elem_filter.begin(), filter_end = elem_filter.end(); for (; filter_it != filter_end ; ++filter_it) { Element & elem = elements(*filter_it); if (elem.type == type) filter.push_back(elem.element); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialReinforcement<dim>::computeDirectingCosines(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh & interface_mesh = this->model->getInterfaceMesh(); const UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); const UInt steel_dof = dim * nb_nodes_per_element; const UInt voigt_size = getTangentStiffnessVoigtSize(dim); const UInt nb_quad_points = model->getFEEngine("EmbeddedInterfaceFEEngine").getNbQuadraturePoints(type, ghost_type); Array<Real> node_coordinates(this->element_filter(type, ghost_type).getSize(), steel_dof); this->model->getFEEngine().template extractNodalToElementField<Real>(interface_mesh, interface_mesh.getNodes(), node_coordinates, type, ghost_type, this->element_filter(type, ghost_type)); Array<Real>::matrix_iterator directing_cosines_it = directing_cosines(type, ghost_type).begin(voigt_size, voigt_size); Array<Real>::matrix_iterator node_coordinates_it = node_coordinates.begin(dim, nb_nodes_per_element); Array<Real>::matrix_iterator node_coordinates_end = node_coordinates.end(dim, nb_nodes_per_element); for (; node_coordinates_it != node_coordinates_end ; ++node_coordinates_it) { for (UInt i = 0 ; i < nb_quad_points ; i++, ++directing_cosines_it) { Matrix<Real> & nodes = *node_coordinates_it; Matrix<Real> & cosines = *directing_cosines_it; computeDirectingCosinesOnQuad(nodes, cosines); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim> void MaterialReinforcement<dim>::assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh & mesh = model->getMesh(); Mesh::type_iterator type_it = mesh.firstType(dim, ghost_type); Mesh::type_iterator type_end = mesh.lastType(dim, ghost_type); for (; type_it != type_end ; ++type_it) { assembleStiffnessMatrix(type, *type_it, ghost_type, _not_ghost); //assembleStiffnessMatrix(type, *type_it, ghost_type, _ghost); } AKANTU_DEBUG_OUT(); } template<UInt dim> void MaterialReinforcement<dim>::assembleStiffnessMatrix(const ElementType & interface_type, const ElementType & background_type, GhostType interface_ghost, GhostType background_ghost) { AKANTU_DEBUG_IN(); UInt voigt_size = getTangentStiffnessVoigtSize(dim); SparseMatrix & K = const_cast<SparseMatrix &>(model->getStiffnessMatrix()); FEEngine & background_engine = model->getFEEngine(); FEEngine & interface_engine = model->getFEEngine("EmbeddedInterfaceFEEngine"); Array<UInt> & elem_filter = element_filter(interface_type, interface_ghost); - Array<Real> & grad_u = gradu(interface_type, interface_ghost); + Array<Real> & grad_u = gradu_embedded(interface_type, interface_ghost); UInt nb_element = elem_filter.getSize(); UInt nodes_per_background_e = Mesh::getNbNodesPerElement(background_type); UInt nb_quadrature_points = interface_engine.getNbQuadraturePoints(interface_type, interface_ghost); UInt back_dof = dim * nodes_per_background_e; UInt integrant_size = back_dof; grad_u.resize(nb_quadrature_points * nb_element); //need function model->getInterfaceDisplacement() /*interface_engine.gradientOnQuadraturePoints(model->getInterfaceDisplacement(), grad_u, dim, interface_type, interface_ghost, elem_filter);*/ Array<Real> * tangent_moduli = new Array<Real>(nb_element * nb_quadrature_points, 1, "interface_tangent_moduli"); tangent_moduli->clear(); computeTangentModuli(interface_type, *tangent_moduli, interface_ghost); Array<Real> & shapesd = shape_derivatives(interface_type, interface_ghost)->operator()(background_type, background_ghost); Array<Real> * integrant = new Array<Real>(nb_element * nb_quadrature_points, integrant_size * integrant_size, "B^t*C^t*D*C*B"); integrant->clear(); /// Temporary matrices for integrant product Matrix<Real> Bvoigt(voigt_size, back_dof); Matrix<Real> DC(voigt_size, voigt_size); Matrix<Real> DCB(voigt_size, back_dof); Matrix<Real> CtDCB(voigt_size, back_dof); Array<Real>::scalar_iterator D_it = tangent_moduli->begin(); Array<Real>::scalar_iterator D_end = tangent_moduli->end(); Array<Real>::matrix_iterator C_it = directing_cosines(interface_type, interface_ghost).begin(voigt_size, voigt_size); Array<Real>::matrix_iterator B_it = shapesd.begin(dim, nodes_per_background_e); Array<Real>::matrix_iterator integrant_it = integrant->begin(integrant_size, integrant_size); for (; D_it != D_end ; ++D_it, ++C_it, ++B_it, ++integrant_it) { Real & D = *D_it; Matrix<Real> & C = *C_it; Matrix<Real> & B = *B_it; Matrix<Real> & BtCtDCB = *integrant_it; VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(B, Bvoigt, nodes_per_background_e); DC.clear(); DC(0, 0) = D * area; DC *= C; DCB.mul<false, false>(DC, Bvoigt); CtDCB.mul<true, false>(C, DCB); BtCtDCB.mul<true, false>(Bvoigt, CtDCB); } delete tangent_moduli; Array<Real> * K_interface = new Array<Real>(nb_element, integrant_size * integrant_size, "K_interface"); interface_engine.integrate(*integrant, *K_interface, integrant_size * integrant_size, interface_type, interface_ghost, elem_filter); delete integrant; Array<UInt> * background_filter = new Array<UInt>(nb_element, 1, "background_filter"); filterInterfaceBackgroundElements(*background_filter, background_type, interface_type, background_ghost, interface_ghost); background_engine.assembleMatrix(*K_interface, K, dim, background_type, background_ghost, *background_filter); delete K_interface; delete background_filter; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /// In this function, type and ghost type refer to background elements template<UInt dim> void MaterialReinforcement<dim>::computeBackgroundShapeDerivatives(const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh & interface_mesh = model->getInterfaceMesh(); FEEngine & engine = model->getFEEngine(); FEEngine & interface_engine = model->getFEEngine("EmbeddedInterfaceFEEngine"); Mesh::type_iterator interface_type = interface_mesh.firstType(); Mesh::type_iterator interface_last = interface_mesh.lastType(); for (; interface_type != interface_last ; ++interface_type) { Array<UInt> & filter = element_filter(*interface_type, ghost_type); const UInt nb_elements = filter.getSize(); const UInt nb_nodes = Mesh::getNbNodesPerElement(type); const UInt nb_quad_per_element = interface_engine.getNbQuadraturePoints(*interface_type); Array<Real> quad_pos(nb_quad_per_element * nb_elements, dim, "interface_quad_points"); quad_pos.resize(nb_quad_per_element * nb_elements); interface_engine.interpolateOnQuadraturePoints(interface_mesh.getNodes(), quad_pos, dim, *interface_type, ghost_type, filter); Array<Real> & background_shapesd = shape_derivatives(*interface_type, ghost_type)->operator()(type, ghost_type); background_shapesd.clear(); Array<UInt> * background_elements = new Array<UInt>(nb_elements, 1, "computeBackgroundShapeDerivatives:background_filter"); filterInterfaceBackgroundElements(*background_elements, type, *interface_type, ghost_type, ghost_type); Array<UInt>::scalar_iterator back_it = background_elements->begin(), back_end = background_elements->end(); Array<Real>::matrix_iterator shapesd_it = background_shapesd.begin(dim, nb_nodes); Array<Real>::vector_iterator quad_pos_it = quad_pos.begin(dim); for (; back_it != back_end ; ++back_it) { for (UInt i = 0 ; i < nb_quad_per_element ; i++, ++shapesd_it, ++quad_pos_it) engine.computeShapeDerivatives(*quad_pos_it, *back_it, type, *shapesd_it, ghost_type); } delete background_elements; } AKANTU_DEBUG_OUT(); } template<UInt dim> Real MaterialReinforcement<dim>::getEnergy(std::string id) { AKANTU_DEBUG_IN(); if (id == "potential") { Real epot = 0.; computePotentialEnergyByElements(); Mesh::type_iterator it = element_filter.firstType(spatial_dimension), end = element_filter.lastType(spatial_dimension); for (; it != end ; ++it) { FEEngine & interface_engine = model->getFEEngine("EmbeddedInterfaceFEEngine"); epot += interface_engine.integrate(potential_energy(*it, _not_ghost), - *it, _not_ghost, - element_filter(*it, _not_ghost)); + *it, _not_ghost, + element_filter(*it, _not_ghost)); epot *= area; } return epot; } AKANTU_DEBUG_OUT(); return 0; } // Author is Nicolas Richart, see material.cc template<UInt dim> void MaterialReinforcement<dim>::flattenInternal(const std::string & field_id, ElementTypeMapArray<Real> & internal_flat, const GhostType ghost_type, ElementKind element_kind) { AKANTU_DEBUG_IN(); typedef ElementTypeMapArray<UInt>::type_iterator iterator; iterator tit = this->element_filter.firstType(1, ghost_type, element_kind); iterator end = this->element_filter.lastType(1, ghost_type, element_kind); for (; tit != end; ++tit) { ElementType type = *tit; try { __attribute__((unused)) const Array<Real> & src_vect = this->getArray(field_id,type,ghost_type); } catch(debug::Exception & e) { continue; } const Array<Real> & src_vect = this->getArray(field_id,type,ghost_type); const Array<UInt> & filter = this->element_filter(type,ghost_type); // total number of elements for a given type UInt nb_element = this->model->getInterfaceMesh().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<Real> & dst_vect = internal_flat(type,ghost_type); dst_vect.resize(nb_element*nb_quad_per_elem); Array<UInt>::const_scalar_iterator it = filter.begin(); Array<UInt>::const_scalar_iterator end = filter.end(); Array<Real>::const_vector_iterator it_src = src_vect.begin_reinterpret(nb_data,nb_element_src); Array<Real>::vector_iterator it_dst = dst_vect.begin_reinterpret(nb_data,nb_element); for (; it != end ; ++it,++it_src) { it_dst[*it] = *it_src; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialReinforcement); /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh index fd77ec62a..ec22703b8 100644 --- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh +++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh @@ -1,212 +1,222 @@ /** * @file material_reinforcement.hh * * @author Lucas Frérot <lucas.frerot@epfl.ch> * * @date creation: Thu Mar 12 2015 * @date last modification: Thu Mar 12 2015 * * @brief Reinforcement material * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_REINFORCEMENT_HH__ #define __AKANTU_MATERIAL_REINFORCEMENT_HH__ #include "aka_common.hh" #include "material.hh" #include "embedded_interface_model.hh" #include "embedded_internal_field.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /** * @brief Material used to represent embedded reinforcements * * This class is used for computing the reinforcement stiffness matrix * along with the reinforcement residual. Room is made for constitutive law, * but actual use of contitutive laws is made in MaterialReinforcementTemplate. + * + * Be careful with the dimensions in this class : + * - this->spatial_dimension is always 1 + * - the template parameter dim is the dimension of the problem */ template<UInt dim> class MaterialReinforcement : virtual public Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /// Constructor - MaterialReinforcement(SolidMechanicsModel & model, const ID & id = ""); + MaterialReinforcement(SolidMechanicsModel & model, + UInt spatial_dimension, + const Mesh & mesh, + FEEngine & fe_engine, + const ID & id = ""); /// Destructor virtual ~MaterialReinforcement(); +protected: + void initialize(SolidMechanicsModel & a_model); + /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// Init the material virtual void initMaterial(); /// Init the background shape derivatives void initBackgroundShapeDerivatives(); /// Init the cosine matrices void initDirectingCosines(); /// Assemble stiffness matrix virtual void assembleStiffnessMatrix(GhostType ghost_type); /// Update the residual virtual void updateResidual(GhostType ghost_type = _not_ghost); /// Assembled the residual virtual void assembleResidual(GhostType ghost_type); /// Compute all the stresses ! virtual void computeAllStresses(GhostType ghost_type); /// Compute the stiffness parameter for elements of a type virtual void computeTangentModuli(const ElementType & type, Array<Real> & tangent, GhostType ghost_type) = 0; virtual Real getEnergy(std::string id); - /// Reimplementation of Material's function to accomodate for interface mesh - virtual void flattenInternal(const std::string & field_id, - ElementTypeMapArray<Real> & internal_flat, - const GhostType ghost_type = _not_ghost, - ElementKind element_kind = _ek_not_defined); + void flattenInternal(const std::string & field_id, + ElementTypeMapArray<Real> & internal_flat, + const GhostType ghost_type, + ElementKind element_kind); /* ------------------------------------------------------------------------ */ /* Protected methods */ /* ------------------------------------------------------------------------ */ protected: /// Allocate the background shape derivatives void allocBackgroundShapeDerivatives(); /// Compute the directing cosines matrix for one element type void computeDirectingCosines(const ElementType & type, GhostType ghost_type); /** * @brief Compute the directing cosines matrix on quadrature points. * * The structure of the directing cosines matrix is : * \f{eqnarray*}{ * C_{1,\cdot} & = & (l^2, m^2, n^2, lm, mn, ln) \\ * C_{i,j} & = & 0 * \f} * * with : * \f[ * (l, m, n) = \frac{1}{\|\frac{\mathrm{d}\vec{r}(s)}{\mathrm{d}s}\|} \cdot \frac{\mathrm{d}\vec{r}(s)}{\mathrm{d}s} * \f] */ inline void computeDirectingCosinesOnQuad(const Matrix<Real> & nodes, Matrix<Real> & cosines); /// Assemble the stiffness matrix for an element type (typically _segment_2) void assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type); /** * @brief Assemble the stiffness matrix for background & interface types * * Computes the reinforcement stiffness matrix (Gomes & Awruch, 2001) * \f[ * \mathbf{K}_e = \sum_{i=1}^R{A_i\int_{S_i}{\mathbf{B}^T * \mathbf{C}_i^T \mathbf{D}_{s, i} \mathbf{C}_i \mathbf{B}\,\mathrm{d}s}} * \f] */ void assembleStiffnessMatrix(const ElementType & interface_type, const ElementType & background_type, GhostType interface_ghost, GhostType background_ghost); /// Compute the background shape derivatives for a type void computeBackgroundShapeDerivatives(const ElementType & type, GhostType ghost_type); /// Filter elements crossed by interface of a type void filterInterfaceBackgroundElements(Array<UInt> & filter, const ElementType & type, const ElementType & interface_type, GhostType ghost_type, GhostType interface_ghost_type); /// Assemble the residual of one type of element (typically _segment_2) void assembleResidual(const ElementType & type, GhostType ghost_type); /** * @brief Assemble the residual for a pair of elements * * Computes and assemble the residual. Residual in reinforcement is computed as : * \f[ * \vec{r} = A_s \int_S{\mathbf{B}^T\mathbf{C}^T \vec{\sigma_s}\,\mathrm{d}s} * \f] */ void assembleResidual(const ElementType & interface_type, const ElementType & background_type, GhostType interface_ghost, GhostType background_ghost); // TODO figure out why voigt size is 4 in 2D inline void stressTensorToVoigtVector(const Matrix<Real> & tensor, Vector<Real> & vector); inline void strainTensorToVoigtVector(const Matrix<Real> & tensor, Vector<Real> & vector); /// Compute gradu on the interface quadrature points virtual void computeGradU(const ElementType & type, GhostType ghost_type); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Embedded model EmbeddedInterfaceModel * model; - /// grad_u - EmbeddedInternalField<Real> gradu; + /// Stress in the reinforcement + InternalField<Real> stress_embedded; - /// stress - EmbeddedInternalField<Real> stress; + /// Gradu of concrete on reinforcement + InternalField<Real> gradu_embedded; /// C matrix on quad - EmbeddedInternalField<Real> directing_cosines; + InternalField<Real> directing_cosines; /// Prestress on quad - EmbeddedInternalField<Real> pre_stress; + InternalField<Real> pre_stress; /// Cross-sectional area Real area; /// Background mesh shape derivatives ElementTypeMap< ElementTypeMapArray<Real> * > shape_derivatives; }; #include "material_reinforcement_inline_impl.cc" __END_AKANTU__ #endif // __AKANTU_MATERIAL_REINFORCEMENT_HH__ diff --git a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh index aeb473d5e..226758880 100644 --- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh +++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh @@ -1,112 +1,117 @@ /** * @file material_reinforcement_template.hh * * @author Lucas Frérot <lucas.frerot@epfl.ch> * * @date creation: Mon Mar 16 2015 * @date last modification: Mon Mar 16 2015 * * @brief Reinforcement material templated with constitutive law * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_REINFORCEMENT_TEMPLATE_HH__ #define __AKANTU_MATERIAL_REINFORCEMENT_TEMPLATE_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_reinforcement.hh" #include "material_elastic.hh" +#include "material_linear_isotropic_hardening.hh" __BEGIN_AKANTU__ /** * @brief Implementation of MaterialReinforcement with 1D constitutive law * @see MaterialReinforcement, MaterialElastic * * This class is a reinforcement featuring a constitutive law. * <strong>Be careful !</strong> Because of multiple inheritance, this class * forms a diamond. */ template<UInt dim, class ConstLaw = MaterialElastic<1> > class MaterialReinforcementTemplate : public MaterialReinforcement<dim>, public ConstLaw { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /// Constructor MaterialReinforcementTemplate(SolidMechanicsModel & a_model, const ID & id = ""); /// Destructor virtual ~MaterialReinforcementTemplate(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// Initialises the material void initMaterial(); /// Compute the stiffness parameter for elements of a type virtual void computeTangentModuli(const ElementType & type, Array<Real> & tangent, GhostType ghost_type); /// Computes stress used by constitutive law virtual void computeStress(ElementType type, GhostType ghost_type); /// Computes gradu to be used by the constitutive law virtual void computeGradU(const ElementType & type, GhostType ghost_type); /// Compute the potential energy of the reinforcement virtual void computePotentialEnergy(ElementType type, GhostType ghost_type = _not_ghost); /// Get energy in reinforcement (currently limited to potential) virtual Real getEnergy(std::string id); virtual void flattenInternal(const std::string & field_id, - ElementTypeMapArray<Real> & internal_flat, + ElementTypeMapArray<Real> & internal_flat, const GhostType ghost_type = _not_ghost, ElementKind element_kind = _ek_not_defined); + /// Save the previous internals + virtual void savePreviousState(); + protected: /** * @brief Compute interface gradu from bulk gradu * \f[ * \varepsilon_s = C \varepsilon_c * \f] */ inline void computeInterfaceGradUOnQuad(const Matrix<Real> & full_gradu, Real & gradu, const Matrix<Real> & C); }; -#include "material_reinforcement_template_inline_impl.cc" +#include "material_reinforcement_template_tmpl.hh" __END_AKANTU__ + #endif // __AKANTU_MATERIAL_REINFORCEMENT_TEMPLATE_HH__ diff --git a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template_inline_impl.cc b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template_tmpl.hh similarity index 74% rename from src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template_inline_impl.cc rename to src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template_tmpl.hh index 7639c9c7b..ef6a80696 100644 --- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template_inline_impl.cc +++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template_tmpl.hh @@ -1,205 +1,194 @@ /** - * @file material_reinforcement_template.cc + * @file material_reinforcement_template_tmpl.hh * * @author Lucas Frérot <lucas.frerot@epfl.ch> * * @date creation: Mon Mar 16 2015 * @date last modification: Mon Mar 16 2015 * * @brief Reinforcement material templated with constitutive law * * @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 <http://www.gnu.org/licenses/>. * */ +// /!\ no namespace here ! + /* -------------------------------------------------------------------------- */ template<UInt dim, class ConstLaw> -MaterialReinforcementTemplate<dim, ConstLaw>::MaterialReinforcementTemplate(SolidMechanicsModel & model, - const ID & id): - Material(model, id), - MaterialReinforcement<dim>(model, id), - ConstLaw(model, id) +MaterialReinforcementTemplate<dim, ConstLaw>::MaterialReinforcementTemplate(SolidMechanicsModel & a_model, + const ID & id): + Material(a_model, 1, + dynamic_cast<EmbeddedInterfaceModel &>(a_model).getInterfaceMesh(), + a_model.getFEEngine("EmbeddedInterfaceFEEngine"), id), + MaterialReinforcement<dim>(a_model, 1, + dynamic_cast<EmbeddedInterfaceModel &>(a_model).getInterfaceMesh(), + a_model.getFEEngine("EmbeddedInterfaceFEEngine"), id), + ConstLaw(a_model, 1, + dynamic_cast<EmbeddedInterfaceModel &>(a_model).getInterfaceMesh(), + a_model.getFEEngine("EmbeddedInterfaceFEEngine"), id) {} /* -------------------------------------------------------------------------- */ template<UInt dim, class ConstLaw> MaterialReinforcementTemplate<dim, ConstLaw>::~MaterialReinforcementTemplate() {} /* -------------------------------------------------------------------------- */ +/// TODO this function is super ugly. Find better way to initialize internals template<UInt dim, class ConstLaw> void MaterialReinforcementTemplate<dim, ConstLaw>::initMaterial() { MaterialReinforcement<dim>::initMaterial(); - - // Gotta change the dimension from here onwards - this->ConstLaw::spatial_dimension = 1; ConstLaw::initMaterial(); - - this->ConstLaw::gradu.free(); - this->ConstLaw::stress.free(); - this->ConstLaw::delta_T.free(); - this->ConstLaw::sigma_th.free(); - this->ConstLaw::potential_energy.free(); - - Mesh::type_iterator type_it = this->MaterialReinforcement<dim>::model->getInterfaceMesh().firstType(); - Mesh::type_iterator type_end = this->MaterialReinforcement<dim>::model->getInterfaceMesh().lastType(); - - - // Reshape the ConstLaw internal fields - for (; type_it != type_end ; ++type_it) { - UInt nb_elements = this->MaterialReinforcement<dim>::element_filter(*type_it).getSize(); - - FEEngine & interface_engine = - this->MaterialReinforcement<dim>::model->getFEEngine("EmbeddedInterfaceFEEngine"); - - UInt nb_quad = interface_engine.getNbQuadraturePoints(*type_it); - - this->ConstLaw::gradu.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); - this->ConstLaw::stress.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); - this->ConstLaw::stress.initialize(1); - this->ConstLaw::delta_T.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); - this->ConstLaw::sigma_th.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); - this->ConstLaw::potential_energy.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); - //this->ConstLaw::gradu.alloc(0, dim * dim, *type_it, _ghost); - } } /* -------------------------------------------------------------------------- */ template<UInt dim, class ConstLaw> void MaterialReinforcementTemplate<dim, ConstLaw>::computeGradU(const ElementType & el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialReinforcement<dim>::computeGradU(el_type, ghost_type); const UInt voigt_size = Material::getTangentStiffnessVoigtSize(dim); Array<Real>::matrix_iterator full_gradu_it = - this->MaterialReinforcement<dim>::gradu(el_type, ghost_type).begin(dim, dim); + this->MaterialReinforcement<dim>::gradu_embedded(el_type, ghost_type).begin(dim, dim); Array<Real>::matrix_iterator full_gradu_end = - this->MaterialReinforcement<dim>::gradu(el_type, ghost_type).end(dim, dim); + this->MaterialReinforcement<dim>::gradu_embedded(el_type, ghost_type).end(dim, dim); Array<Real>::scalar_iterator gradu_it = this->ConstLaw::gradu(el_type, ghost_type).begin(); Array<Real>::matrix_iterator cosines_it = this->directing_cosines(el_type, ghost_type).begin(voigt_size, voigt_size); for (; full_gradu_it != full_gradu_end ; ++full_gradu_it, ++gradu_it, ++cosines_it) { Matrix<Real> & full_gradu = *full_gradu_it; Real & gradu = *gradu_it; Matrix<Real> & C = *cosines_it; computeInterfaceGradUOnQuad(full_gradu, gradu, C); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim, class ConstLaw> void MaterialReinforcementTemplate<dim, ConstLaw>::computeInterfaceGradUOnQuad(const Matrix<Real> & full_gradu, Real & gradu, const Matrix<Real> & C) { const UInt voigt_size = Material::getTangentStiffnessVoigtSize(dim); Matrix<Real> epsilon(dim, dim); Vector<Real> e_voigt(voigt_size); Vector<Real> e_interface_voigt(voigt_size); epsilon = 0.5 * (full_gradu + full_gradu.transpose()); MaterialReinforcement<dim>::strainTensorToVoigtVector(epsilon, e_voigt); e_interface_voigt.mul<false>(C, e_voigt); gradu = e_interface_voigt(0); } /* -------------------------------------------------------------------------- */ template<UInt dim, class ConstLaw> void MaterialReinforcementTemplate<dim, ConstLaw>::computeTangentModuli(const ElementType & el_type, - Array<Real> & tangent, - GhostType ghost_type) { + Array<Real> & tangent, + GhostType ghost_type) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(tangent.getNbComponent() == 1, "Reinforcements only work in 1D"); ConstLaw::computeTangentModuli(el_type, tangent, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim, class ConstLaw> void MaterialReinforcementTemplate<dim, ConstLaw>::computeStress(ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); ConstLaw::computeStress(type, ghost_type); Array<Real>::matrix_iterator full_sigma_it = - this->MaterialReinforcement<dim>::stress(type, ghost_type).begin(dim, dim); + this->MaterialReinforcement<dim>::stress_embedded(type, ghost_type).begin(dim, dim); Array<Real>::matrix_iterator full_sigma_end = - this->MaterialReinforcement<dim>::stress(type, ghost_type).end(dim, dim); + this->MaterialReinforcement<dim>::stress_embedded(type, ghost_type).end(dim, dim); Array<Real>::scalar_iterator sigma_it = this->ConstLaw::stress(type, ghost_type).begin(); Array<Real>::scalar_iterator pre_stress_it = this->MaterialReinforcement<dim>::pre_stress(type, ghost_type).begin(); for (; full_sigma_it != full_sigma_end ; ++full_sigma_it, ++sigma_it, ++pre_stress_it) { Matrix<Real> & sigma = *full_sigma_it; sigma(0, 0) = *sigma_it + *pre_stress_it; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt dim, class ConstLaw> Real MaterialReinforcementTemplate<dim, ConstLaw>::getEnergy(std::string id) { return MaterialReinforcement<dim>::getEnergy(id); } /* -------------------------------------------------------------------------- */ template <UInt dim, class ConstLaw> void MaterialReinforcementTemplate<dim, ConstLaw>::computePotentialEnergy(ElementType type, GhostType ghost_type) { + const UInt nb_elements = this->element_filter(type, ghost_type).getSize(); + const UInt nb_quad = this->model->getFEEngine("EmbeddedInterfaceFEEngine").getNbQuadraturePoints(type); + this->ConstLaw::potential_energy.alloc(nb_quad * nb_elements, 1, type, ghost_type, 0.); + ConstLaw::computePotentialEnergy(type, ghost_type); } +/* -------------------------------------------------------------------------- */ + template <UInt dim, class ConstLaw> void MaterialReinforcementTemplate<dim, ConstLaw>::flattenInternal(const std::string & field_id, ElementTypeMapArray<Real> & internal_flat, const GhostType ghost_type, ElementKind element_kind) { - if (field_id == "stress_embedded") + if (field_id == "stress_embedded" || field_id == "inelastic_strain") MaterialReinforcement<dim>::flattenInternal(field_id, internal_flat, ghost_type, element_kind); } + +template<UInt dim, class ConstLaw> +void MaterialReinforcementTemplate<dim, ConstLaw>::savePreviousState() { + ConstLaw::savePreviousState(); +} diff --git a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc index c55e1d2ec..4e8a818c3 100644 --- a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc +++ b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc @@ -1,201 +1,215 @@ /** * @file material_linear_isotropic_hardening.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch> * @author Benjamin Paccaud <benjamin.paccaud@epfl.ch> * * @date creation: Thu Oct 03 2013 * @date last modification: Fri Jun 13 2014 * * @brief Specialization of the material class for isotropic finite deformation linear hardening plasticity * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_linear_isotropic_hardening.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template<UInt dim> MaterialLinearIsotropicHardening<dim>::MaterialLinearIsotropicHardening(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialPlastic<dim>(model, id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } +/* -------------------------------------------------------------------------- */ +template<UInt spatial_dimension> +MaterialLinearIsotropicHardening<spatial_dimension>::MaterialLinearIsotropicHardening( + SolidMechanicsModel & model, + UInt dim, + const Mesh & mesh, + FEEngine & fe_engine, + const ID & id) : + + Material(model, dim, mesh, fe_engine, id), + MaterialPlastic<spatial_dimension>(model, dim, mesh, fe_engine, id) +{} + + /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialLinearIsotropicHardening<spatial_dimension>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialThermal<spatial_dimension>::computeStress(el_type, ghost_type); // infinitesimal and finite deformation Array<Real>::iterator<> sigma_th_it = this->sigma_th(el_type, ghost_type).begin(); Array<Real>::iterator<> previous_sigma_th_it = this->sigma_th.previous(el_type, ghost_type).begin(); Array<Real>::matrix_iterator previous_gradu_it = this->gradu.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator previous_stress_it = this->stress.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator inelastic_strain_it = this->inelastic_strain(el_type, ghost_type).begin(spatial_dimension,spatial_dimension); Array<Real>::matrix_iterator previous_inelastic_strain_it = this->inelastic_strain.previous(el_type, ghost_type).begin(spatial_dimension,spatial_dimension); Array<Real>::iterator<> iso_hardening_it = this->iso_hardening(el_type, ghost_type).begin(); Array<Real>::iterator<> previous_iso_hardening_it = this->iso_hardening.previous(el_type, ghost_type).begin(); // // Finite Deformations // if (this->finite_deformation) { Array<Real>::matrix_iterator previous_piola_kirchhoff_2_it = this->piola_kirchhoff_2.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator green_strain_it = this->green_strain(el_type, ghost_type).begin(spatial_dimension,spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> & inelastic_strain_tensor = *inelastic_strain_it; Matrix<Real> & previous_inelastic_strain_tensor = *previous_inelastic_strain_it; Matrix<Real> & previous_grad_u = *previous_gradu_it; Matrix<Real> & previous_sigma = *previous_piola_kirchhoff_2_it; Matrix<Real> & green_strain = *green_strain_it; this->template gradUToGreenStrain<spatial_dimension>(grad_u, green_strain); Matrix<Real> previous_green_strain(spatial_dimension,spatial_dimension); this->template gradUToGreenStrain<spatial_dimension>(previous_grad_u, previous_green_strain); Matrix<Real> F_tensor(spatial_dimension,spatial_dimension); this->template gradUToF<spatial_dimension>(grad_u,F_tensor); computeStressOnQuad(green_strain, previous_green_strain, sigma, previous_sigma, inelastic_strain_tensor, previous_inelastic_strain_tensor, *iso_hardening_it, *previous_iso_hardening_it, *sigma_th_it, *previous_sigma_th_it, F_tensor); ++sigma_th_it; ++inelastic_strain_it; ++iso_hardening_it; ++previous_sigma_th_it; //++previous_stress_it; ++previous_gradu_it; ++green_strain_it; ++previous_inelastic_strain_it; ++previous_iso_hardening_it; ++previous_piola_kirchhoff_2_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } // Infinitesimal deformations else { MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> & inelastic_strain_tensor = *inelastic_strain_it; Matrix<Real> & previous_inelastic_strain_tensor = *previous_inelastic_strain_it; Matrix<Real> & previous_grad_u = *previous_gradu_it; Matrix<Real> & previous_sigma = *previous_stress_it; computeStressOnQuad(grad_u, previous_grad_u, sigma, previous_sigma, inelastic_strain_tensor, previous_inelastic_strain_tensor, *iso_hardening_it, *previous_iso_hardening_it, *sigma_th_it, *previous_sigma_th_it); ++sigma_th_it; ++inelastic_strain_it; ++iso_hardening_it; ++previous_sigma_th_it; ++previous_stress_it; ++previous_gradu_it; ++previous_inelastic_strain_it; ++previous_iso_hardening_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialLinearIsotropicHardening<spatial_dimension>::computeTangentModuli(__attribute__((unused)) const ElementType & el_type, Array<Real> & tangent_matrix, __attribute__((unused)) GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real>::const_matrix_iterator previous_gradu_it = this->gradu.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); Array<Real>::const_matrix_iterator previous_stress_it = this->stress.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); Array<Real>::const_scalar_iterator iso_hardening= this->iso_hardening(el_type, ghost_type).begin(); MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); computeTangentModuliOnQuad(tangent, grad_u, *previous_gradu_it, sigma_tensor, *previous_stress_it, *iso_hardening); ++previous_gradu_it; ++previous_stress_it; ++iso_hardening; MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialLinearIsotropicHardening); __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh index 1cc27030a..933bd414a 100644 --- a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh +++ b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh @@ -1,113 +1,118 @@ /** * @file material_linear_isotropic_hardening.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch> * * @date creation: Thu Oct 03 2013 * @date last modification: Mon Apr 07 2014 * * @brief Specialization of the material class for isotropic finite deformation linear hardening plasticity * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_voigthelper.hh" #include "material_plastic.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_LINEAR_ISOTROPIC_HARDENING_HH__ #define __AKANTU_MATERIAL_LINEAR_ISOTROPIC_HARDENING_HH__ __BEGIN_AKANTU__ /** * Material plastic with a linear evolution of the yielding stress */ template <UInt spatial_dimension> class MaterialLinearIsotropicHardening : public MaterialPlastic<spatial_dimension> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialLinearIsotropicHardening(SolidMechanicsModel & model, const ID & id = ""); + MaterialLinearIsotropicHardening(SolidMechanicsModel & model, + UInt dim, + const Mesh & mesh, + FEEngine & fe_engine, + const ID & id = ""); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// constitutive law for all element of a type virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the tangent stiffness matrix for an element type void computeTangentModuli(const ElementType & el_type, Array<Real> & tangent_matrix, GhostType ghost_type = _not_ghost); protected: /// Infinitesimal deformations inline void computeStressOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u, Matrix<Real> & sigma, const Matrix<Real> & previous_sigma, Matrix<Real> & inelas_strain, const Matrix<Real> & previous_inelas_strain, Real & iso_hardening, const Real & previous_iso_hardening, const Real & sigma_th, const Real & previous_sigma_th); /// Finite deformations inline void computeStressOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u, Matrix<Real> & sigma, const Matrix<Real> & previous_sigma, Matrix<Real> & inelas_strain, const Matrix<Real> & previous_inelas_strain, Real & iso_hardening, const Real & previous_iso_hardening, const Real & sigma_th, const Real & previous_sigma_th, const Matrix<Real> & F_tensor); inline void computeTangentModuliOnQuad(Matrix<Real> & tangent, const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u, const Matrix<Real> & sigma_tensor, const Matrix<Real> & previous_sigma_tensor, const Real & iso_hardening) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_linear_isotropic_hardening_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_MATERIAL_LINEAR_ISOTROPIC_HARDENING_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.cc b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.cc index 0477f4fca..609e3b199 100644 --- a/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.cc +++ b/src/model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.cc @@ -1,301 +1,307 @@ /** * @file material_linear_isotropic_hardening_inline_impl.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Ramin Aghababaei <ramin.aghababaei@epfl.ch> * @author Benjamin Paccaud <benjamin.paccaud@epfl.ch> * * @date creation: Thu Oct 03 2013 * @date last modification: Mon Jun 09 2014 * * @brief Implementation of the inline functions of the material plasticity * * @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 <http://www.gnu.org/licenses/>. * */ #include "material_linear_isotropic_hardening.hh" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ ///Infinitesimal deformations template<UInt dim> inline void MaterialLinearIsotropicHardening<dim>::computeStressOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u, Matrix<Real> & sigma, const Matrix<Real> & previous_sigma, Matrix<Real> & inelastic_strain, const Matrix<Real> & previous_inelastic_strain, Real & iso_hardening, const Real & previous_iso_hardening, const Real & sigma_th, const Real & previous_sigma_th) { //Infinitesimal plasticity - //Real r=iso_hardening; - Real dp=0.0; - Real d_dp=0.0; - UInt n=0; + Real dp = 0.0; + Real d_dp = 0.0; + UInt n = 0; Real delta_sigma_th = sigma_th - previous_sigma_th; Matrix<Real> grad_delta_u(grad_u); grad_delta_u -= previous_grad_u; //Compute trial stress, sigma_tr Matrix<Real> sigma_tr(dim, dim); MaterialElastic<dim>::computeStressOnQuad(grad_delta_u, sigma_tr, delta_sigma_th); sigma_tr += previous_sigma; // Compute deviatoric trial stress, sigma_tr_dev Matrix<Real> sigma_tr_dev(sigma_tr); sigma_tr_dev -= Matrix<Real>::eye(dim, sigma_tr.trace() / 3.0); // Compute effective deviatoric trial stress Real s = sigma_tr_dev.doubleDot(sigma_tr_dev); Real sigma_tr_dev_eff = std::sqrt(3./2. * s); + // In 1D Von-Mises stress is the stress + if (dim == 1) sigma_tr_dev_eff = sigma_tr(0, 0); + const Real iso_hardening_t = previous_iso_hardening; iso_hardening = iso_hardening_t; //Loop for correcting stress based on yield function bool initial_yielding = ( (sigma_tr_dev_eff - iso_hardening - this->sigma_y) > 0) ; - while ( initial_yielding && std::abs(sigma_tr_dev_eff - iso_hardening - this->sigma_y) > Math::getTolerance() ) { + while (initial_yielding && std::abs(sigma_tr_dev_eff - iso_hardening - this->sigma_y) > Math::getTolerance()) { d_dp = (sigma_tr_dev_eff - 3. * this->mu *dp - iso_hardening - this->sigma_y) / (3. * this->mu + this->h); - //r = r + h * dp; dp = dp + d_dp; iso_hardening = iso_hardening_t + this->h * dp; - ++n; - - /// TODO : explicit this criterion with an error message - if ((d_dp < 1e-5) || (n>50)) - { - break; - } + + if (d_dp < 1e-5) { + break; + } else if (n > 50) { + AKANTU_DEBUG_WARNING("Isotropic hardening convergence failed"); + break; + } } //Update internal variable Matrix<Real> delta_inelastic_strain(dim, dim, 0.); if (std::abs(sigma_tr_dev_eff) > sigma_tr_dev.norm<L_inf>() * Math::getTolerance()) { delta_inelastic_strain.copy(sigma_tr_dev); delta_inelastic_strain *= 3./2. * dp / sigma_tr_dev_eff; } MaterialPlastic<dim>::computeStressAndInelasticStrainOnQuad(grad_delta_u, sigma, previous_sigma, inelastic_strain, previous_inelastic_strain, delta_inelastic_strain); } /* -------------------------------------------------------------------------- */ ///Finite deformations template<UInt dim> inline void MaterialLinearIsotropicHardening<dim>::computeStressOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u, Matrix<Real> & sigma, const Matrix<Real> & previous_sigma, Matrix<Real> & inelastic_strain, const Matrix<Real> & previous_inelastic_strain, Real & iso_hardening, const Real & previous_iso_hardening, const Real & sigma_th, const Real & previous_sigma_th, const Matrix<Real> & F_tensor) { //Finite plasticity Real dp=0.0; Real d_dp=0.0; UInt n=0; Real delta_sigma_th = sigma_th - previous_sigma_th; Matrix<Real> grad_delta_u(grad_u); grad_delta_u -= previous_grad_u; //Compute trial stress, sigma_tr Matrix<Real> sigma_tr(dim, dim); MaterialElastic<dim>::computeStressOnQuad(grad_delta_u, sigma_tr, delta_sigma_th); sigma_tr += previous_sigma; // Compute deviatoric trial stress, sigma_tr_dev Matrix<Real> sigma_tr_dev(sigma_tr); sigma_tr_dev -= Matrix<Real>::eye(dim, sigma_tr.trace() / 3.0); // Compute effective deviatoric trial stress Real s = sigma_tr_dev.doubleDot(sigma_tr_dev); Real sigma_tr_dev_eff = std::sqrt(3./2. * s); // compute the cauchy stress to apply the Von-Mises criterion Matrix<Real> cauchy_stress(dim,dim); Material::computeCauchyStressOnQuad<dim>(F_tensor,sigma_tr,cauchy_stress); Matrix<Real> cauchy_stress_dev(cauchy_stress); cauchy_stress_dev -= Matrix<Real>::eye(dim, cauchy_stress.trace() / 3.0); Real c = cauchy_stress_dev.doubleDot(cauchy_stress_dev); Real cauchy_stress_dev_eff = std::sqrt(3./2. * c); const Real iso_hardening_t = previous_iso_hardening; iso_hardening = iso_hardening_t; //Loop for correcting stress based on yield function // F is written in terms of S // bool initial_yielding = ( (sigma_tr_dev_eff - iso_hardening - this->sigma_y) > 0) ; // while ( initial_yielding && std::abs(sigma_tr_dev_eff - iso_hardening - this->sigma_y) > Math::getTolerance() ) { // d_dp = (sigma_tr_dev_eff - 3. * this->mu *dp - iso_hardening - this->sigma_y) // / (3. * this->mu + this->h); // //r = r + h * dp; // dp = dp + d_dp; // iso_hardening = iso_hardening_t + this->h * dp; // ++n; // /// TODO : explicit this criterion with an error message // if ((std::abs(d_dp) < 1e-9) || (n>50)){ // AKANTU_DEBUG_INFO("convergence of increment of plastic strain. d_dp:" << d_dp << "\tNumber of iteration:"<<n); // break; // } // } // F is written in terms of cauchy stress bool initial_yielding = ( (cauchy_stress_dev_eff - iso_hardening - this->sigma_y) > 0) ; while ( initial_yielding && std::abs(cauchy_stress_dev_eff - iso_hardening - this->sigma_y) > Math::getTolerance() ) { d_dp = ( cauchy_stress_dev_eff - 3. * this->mu *dp - iso_hardening - this->sigma_y) / (3. * this->mu + this->h); //r = r + h * dp; dp = dp + d_dp; iso_hardening = iso_hardening_t + this->h * dp; ++n; /// TODO : explicit this criterion with an error message if ((d_dp < 1e-5) || (n>50)){ AKANTU_DEBUG_INFO("convergence of increment of plastic strain. d_dp:" << d_dp << "\tNumber of iteration:"<<n); break; } } //Update internal variable Matrix<Real> delta_inelastic_strain(dim, dim, 0.); if (std::abs(sigma_tr_dev_eff) > sigma_tr_dev.norm<L_inf>() * Math::getTolerance()) { // /// compute the direction of the plastic strain as \frac{\partial F}{\partial S} = \frac{3}{2J\sigma_{effective}}} Ft \sigma_{dev} F Matrix<Real> cauchy_dev_F(dim,dim); cauchy_dev_F.mul<false,false>(F_tensor,cauchy_stress_dev); Real J = F_tensor.det(); Real constant = J ? 1./J : 0; constant *= 3. * dp / (2. * cauchy_stress_dev_eff); delta_inelastic_strain.mul<true,false>(F_tensor,cauchy_dev_F,constant); //Direction given by the piola kirchhoff deviatoric tensor \frac{\partial F}{\partial S} = \frac{3}{2\sigma_{effective}}}S_{dev} // delta_inelastic_strain.copy(sigma_tr_dev); // delta_inelastic_strain *= 3./2. * dp / sigma_tr_dev_eff; } MaterialPlastic<dim>::computeStressAndInelasticStrainOnQuad(grad_delta_u, sigma, previous_sigma, inelastic_strain, previous_inelastic_strain, delta_inelastic_strain); } /* -------------------------------------------------------------------------- */ template<UInt dim> inline void MaterialLinearIsotropicHardening<dim>::computeTangentModuliOnQuad(Matrix<Real> & tangent, const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u, const Matrix<Real> & sigma_tensor, const Matrix<Real> & previous_sigma_tensor, const Real & iso_hardening) const { // Real r=iso_hardening; // Matrix<Real> grad_delta_u(grad_u); // grad_delta_u -= previous_grad_u; // //Compute trial stress, sigma_tr // Matrix<Real> sigma_tr(dim, dim); // MaterialElastic<dim>::computeStressOnQuad(grad_delta_u, sigma_tr); // sigma_tr += previous_sigma_tensor; // // Compute deviatoric trial stress, sigma_tr_dev // Matrix<Real> sigma_tr_dev(sigma_tr); // sigma_tr_dev -= Matrix<Real>::eye(dim, sigma_tr.trace() / 3.0); // // Compute effective deviatoric trial stress // Real s = sigma_tr_dev.doubleDot(sigma_tr_dev); // Real sigma_tr_dev_eff=std::sqrt(3./2. * s); // // Compute deviatoric stress, sigma_dev // Matrix<Real> sigma_dev(sigma_tensor); // sigma_dev -= Matrix<Real>::eye(dim, sigma_tensor.trace() / 3.0); // // Compute effective deviatoric stress // s = sigma_dev.doubleDot(sigma_dev); // Real sigma_dev_eff = std::sqrt(3./2. * s); // Real xr = 0.0; // if(sigma_tr_dev_eff > sigma_dev_eff * Math::getTolerance()) // xr = sigma_dev_eff / sigma_tr_dev_eff; // Real __attribute__((unused)) q = 1.5 * (1. / (1. + 3. * this->mu / this->h) - xr); + /* UInt cols = tangent.cols(); UInt rows = tangent.rows(); for (UInt m = 0; m < rows; ++m) { UInt i = VoigtHelper<dim>::vec[m][0]; UInt j = VoigtHelper<dim>::vec[m][1]; for (UInt n = 0; n < cols; ++n) { UInt k = VoigtHelper<dim>::vec[n][0]; UInt l = VoigtHelper<dim>::vec[n][1]; + */ // This section of the code is commented // There were some problems with the convergence of plastic-coupled simulations with thermal expansion // XXX: DO NOT REMOVE /*if (((sigma_tr_dev_eff-iso_hardening-sigmay) > 0) && (xr > 0)) { tangent(m,n) = 2. * this->mu * q * (sigma_tr_dev (i,j) / sigma_tr_dev_eff) * (sigma_tr_dev (k,l) / sigma_tr_dev_eff) + (i==k) * (j==l) * 2. * this->mu * xr + (i==j) * (k==l) * (this->kpa - 2./3. * this->mu * xr); if ((m == n) && (m>=dim)) tangent(m, n) = tangent(m, n) - this->mu * xr; } else {*/ + /* tangent(m,n) = (i==k) * (j==l) * 2. * this->mu + (i==j) * (k==l) * this->lambda; tangent(m,n) -= (m==n) * (m>=dim) * this->mu; + */ //} //correct tangent stiffness for shear component - } - } + //} + //} + MaterialElastic<dim>::computeTangentModuliOnQuad(tangent); } diff --git a/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc b/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc index 5bd012b8a..4b7e97329 100644 --- a/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc +++ b/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc @@ -1,184 +1,206 @@ /** * @file material_plastic.cc * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Mon Apr 07 2014 * @date last modification: Fri Jun 13 2014 * * @brief Implemantation of the akantu::MaterialPlastic 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_plastic.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialPlastic<spatial_dimension>::MaterialPlastic(SolidMechanicsModel & model, const ID & id) : Material(model, id), MaterialElastic<spatial_dimension>(model, id), iso_hardening("iso_hardening", *this), inelastic_strain("inelastic_strain", *this), plastic_energy("plastic_energy", *this), d_plastic_energy("d_plastic_energy", *this) { AKANTU_DEBUG_IN(); + this->initialize(); + AKANTU_DEBUG_OUT(); +} +template<UInt spatial_dimension> +MaterialPlastic<spatial_dimension>::MaterialPlastic(SolidMechanicsModel & model, + UInt dim, + const Mesh & mesh, + FEEngine & fe_engine, + const ID & id) : + Material(model, dim, mesh, fe_engine, id), + MaterialElastic<spatial_dimension>(model, dim, mesh, fe_engine, id), + iso_hardening("iso_hardening", *this, dim, fe_engine, this->element_filter), + inelastic_strain("inelastic_strain", *this, dim, fe_engine, this->element_filter), + plastic_energy("plastic_energy", *this, dim, fe_engine, this->element_filter), + d_plastic_energy("d_plastic_energy", *this, dim, fe_engine, this->element_filter) { + AKANTU_DEBUG_IN(); + this->initialize(); + AKANTU_DEBUG_OUT(); +} + +/* -------------------------------------------------------------------------- */ +template<UInt spatial_dimension> +void MaterialPlastic<spatial_dimension>::initialize() { this->registerParam("h", h, 0., _pat_parsable | _pat_modifiable, "Hardening modulus"); this->registerParam("sigma_y", sigma_y, 0., _pat_parsable | _pat_modifiable, "Yield stress"); //already registered in material // this->registerParam("finite_deformation",finite_deformation, false, _pat_parsable | _pat_modifiable, "Flag for large deformation"); this->iso_hardening.initialize(1); this->iso_hardening.initializeHistory(); this->plastic_energy.initialize(1); this->d_plastic_energy.initialize(1); this->use_previous_stress = true; this->use_previous_gradu = true; this->use_previous_stress_thermal = true; this->inelastic_strain.initialize(spatial_dimension * spatial_dimension); this->inelastic_strain.initializeHistory(); - - AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialPlastic<spatial_dimension>::getEnergy(std::string type) { if (type == "plastic") return getPlasticEnergy(); else return MaterialElastic<spatial_dimension>::getEnergy(type); return 0.; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> Real MaterialPlastic<spatial_dimension>::getPlasticEnergy() { AKANTU_DEBUG_IN(); Real penergy = 0.; const Mesh & mesh = this->model->getFEEngine().getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, _not_ghost); Mesh::type_iterator end = mesh.lastType(spatial_dimension, _not_ghost); for(; it != end; ++it) { penergy += this->model->getFEEngine().integrate(plastic_energy(*it, _not_ghost), - *it, _not_ghost, - this->element_filter(*it, _not_ghost)); + *it, _not_ghost, + this->element_filter(*it, _not_ghost)); } AKANTU_DEBUG_OUT(); return penergy; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> -void MaterialPlastic<spatial_dimension>::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { +void MaterialPlastic<spatial_dimension>::computePotentialEnergy(ElementType el_type, + GhostType ghost_type) { AKANTU_DEBUG_IN(); if(ghost_type != _not_ghost) return; Array<Real>::scalar_iterator epot = this->potential_energy(el_type, ghost_type).begin(); Array<Real>::const_iterator< Matrix<Real> > inelastic_strain_it = this->inelastic_strain(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> elastic_strain(spatial_dimension, spatial_dimension); elastic_strain.copy(grad_u); elastic_strain -= *inelastic_strain_it; MaterialElastic<spatial_dimension>::computePotentialEnergyOnQuad(elastic_strain, sigma, *epot); ++epot; ++inelastic_strain_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialPlastic<spatial_dimension>::updateEnergies(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialElastic<spatial_dimension>::updateEnergies(el_type, ghost_type); Array<Real>::iterator<> pe_it = this->plastic_energy(el_type, ghost_type).begin(); Array<Real>::iterator<> wp_it = this->d_plastic_energy(el_type, ghost_type).begin(); Array<Real>::iterator< Matrix<Real> > inelastic_strain_it = this->inelastic_strain(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); Array<Real>::iterator< Matrix<Real> > previous_inelastic_strain_it = this->inelastic_strain.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); Array<Real>::matrix_iterator previous_sigma = this->stress.previous(el_type, ghost_type).begin(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); Matrix<Real> delta_strain_it(*inelastic_strain_it); delta_strain_it -= *previous_inelastic_strain_it; Matrix<Real> sigma_h(sigma); sigma_h += *previous_sigma; *wp_it = .5 * sigma_h.doubleDot(delta_strain_it); *pe_it += *wp_it; ++pe_it; ++wp_it; ++inelastic_strain_it; ++previous_inelastic_strain_it; ++previous_sigma; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialPlastic); __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh b/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh index abcd54021..dc06edb44 100644 --- a/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh +++ b/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh @@ -1,129 +1,137 @@ /** * @file material_plastic.hh * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * * @date creation: Mon Apr 07 2014 * @date last modification: Mon Apr 07 2014 * * @brief Common interface for plastic materials * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_elastic.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_PLASTIC_HH__ #define __AKANTU_MATERIAL_PLASTIC_HH__ __BEGIN_AKANTU__ /** * Parent class for the plastic constitutive laws * parameters in the material files : * - h : Hardening parameter (default: 0) * - sigmay : Yield stress */ template<UInt dim> class MaterialPlastic : public MaterialElastic<dim> { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialPlastic(SolidMechanicsModel & model, const ID & id = ""); + MaterialPlastic(SolidMechanicsModel & model, + UInt a_dim, + const Mesh & mesh, + FEEngine & fe_engine, + const ID & id = ""); + +protected: + void initialize(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual Real getEnergy(std::string type); /// Compute the plastic energy virtual void updateEnergies(ElementType el_type, GhostType ghost_type = _not_ghost); /// Compute the true potential energy virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type); protected: inline void computeStressAndInelasticStrainOnQuad(const Matrix<Real> & grad_u, const Matrix<Real> & previous_grad_u, Matrix<Real> & sigma, const Matrix<Real> & previous_sigma, Matrix<Real> & inelas_strain, const Matrix<Real> & previous_inelas_strain, const Matrix<Real> & delta_inelastic_strain) const; inline void computeStressAndInelasticStrainOnQuad(const Matrix<Real> & delta_grad_u, Matrix<Real> & sigma, const Matrix<Real> & previous_sigma, Matrix<Real> & inelas_strain, const Matrix<Real> & previous_inelas_strain, const Matrix<Real> & delta_inelastic_strain) const; Real getPlasticEnergy(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Yield stresss Real sigma_y; /// hardening modulus Real h; /// isotropic hardening, r InternalField<Real> iso_hardening; /// inelastic strain arrays ordered by element types (inelastic deformation) InternalField<Real> inelastic_strain; /// Plastic energy InternalField<Real> plastic_energy; /// @todo : add a coefficient beta that will multiply the plastic energy increment /// to compute the energy converted to heat /// Plastic energy increment InternalField<Real> d_plastic_energy; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_plastic_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_MATERIAL_PLASTIC_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_thermal.cc b/src/model/solid_mechanics/materials/material_thermal.cc index 50001d6aa..d37508f7e 100644 --- a/src/model/solid_mechanics/materials/material_thermal.cc +++ b/src/model/solid_mechanics/materials/material_thermal.cc @@ -1,101 +1,122 @@ /** * @file material_thermal.cc * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Thu Oct 17 2013 * @date last modification: Thu Apr 03 2014 * * @brief Specialization of the material class for the thermal material * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_thermal.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> MaterialThermal<spatial_dimension>::MaterialThermal(SolidMechanicsModel & model, const ID & id) : Material(model, id), delta_T("delta_T", *this), sigma_th("sigma_th", *this), use_previous_stress_thermal(false) { AKANTU_DEBUG_IN(); + this->initialize(); + AKANTU_DEBUG_OUT(); +} + +/* -------------------------------------------------------------------------- */ +template<UInt spatial_dimension> +MaterialThermal<spatial_dimension>::MaterialThermal(SolidMechanicsModel & model, + UInt dim, + const Mesh & mesh, + FEEngine & fe_engine, + const ID & id) : + Material(model, dim, mesh, fe_engine, id), + delta_T("delta_T", *this, dim, fe_engine, this->element_filter), + sigma_th("sigma_th", *this, dim, fe_engine, this->element_filter), + use_previous_stress_thermal(false) { + AKANTU_DEBUG_IN(); + this->initialize(); + AKANTU_DEBUG_OUT(); +} +template<UInt spatial_dimension> +void MaterialThermal<spatial_dimension>::initialize() { this->registerParam("E" , E , 0. , _pat_parsable | _pat_modifiable, "Young's modulus" ); this->registerParam("nu" , nu , 0.5 , _pat_parsable | _pat_modifiable, "Poisson's ratio" ); this->registerParam("alpha" , alpha , 0. , _pat_parsable | _pat_modifiable, "Thermal expansion coefficient"); this->registerParam("delta_T", delta_T, _pat_parsable | _pat_modifiable, "Uniform temperature field"); delta_T.initialize(1); - AKANTU_DEBUG_OUT(); } + /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void MaterialThermal<spatial_dimension>::initMaterial() { AKANTU_DEBUG_IN(); sigma_th.initialize(1); if(use_previous_stress_thermal) { sigma_th.initializeHistory(); } Material::initMaterial(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <UInt dim> void MaterialThermal<dim>::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Array<Real>::iterator<> delta_t_it = this->delta_T(el_type, ghost_type).begin(); Array<Real>::iterator<> sigma_th_it = this->sigma_th(el_type, ghost_type).begin(); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); /// TODO : implement with the matrix alpha if (dim == 1) { *sigma_th_it = - this->E * this->alpha * *delta_t_it; } else { *sigma_th_it = - this->E/(1.-2.*this->nu) * this->alpha * *delta_t_it; } ++delta_t_it; ++sigma_th_it; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ INSTANSIATE_MATERIAL(MaterialThermal); __END_AKANTU__ diff --git a/src/model/solid_mechanics/materials/material_thermal.hh b/src/model/solid_mechanics/materials/material_thermal.hh index a15c04f06..9e120c0d2 100644 --- a/src/model/solid_mechanics/materials/material_thermal.hh +++ b/src/model/solid_mechanics/materials/material_thermal.hh @@ -1,96 +1,104 @@ /** * @file material_thermal.hh * * @author Lucas Frerot <lucas.frerot@epfl.ch> * * @date creation: Thu Oct 17 2013 * @date last modification: Thu Apr 03 2014 * * @brief Material isotropic thermo-elastic * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_THERMAL_HH__ #define __AKANTU_MATERIAL_THERMAL_HH__ __BEGIN_AKANTU__ template<UInt spatial_dimension> class MaterialThermal : public virtual Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialThermal(SolidMechanicsModel & model, const ID & id = ""); + MaterialThermal(SolidMechanicsModel & model, + UInt dim, + const Mesh & mesh, + FEEngine & fe_engine, + const ID & id = ""); virtual ~MaterialThermal() {}; +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); /* ------------------------------------------------------------------------ */ /* DataAccessor inherited members */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// Young modulus Real E; /// Poisson ratio Real nu; /// Thermal expansion coefficient /// TODO : implement alpha as a matrix Real alpha; /// Temperature field InternalField<Real> delta_T; /// Current thermal stress InternalField<Real> sigma_th; /// Tell if we need to use the previous thermal stress bool use_previous_stress_thermal; }; __END_AKANTU__ #endif /* __AKANTU_MATERIAL_THERMAL_HH__ */ diff --git a/src/model/solid_mechanics/materials/plane_stress_toolbox.hh b/src/model/solid_mechanics/materials/plane_stress_toolbox.hh index 840ae01de..aca90d1ed 100644 --- a/src/model/solid_mechanics/materials/plane_stress_toolbox.hh +++ b/src/model/solid_mechanics/materials/plane_stress_toolbox.hh @@ -1,87 +1,98 @@ /** * @file plane_stress_toolbox.hh * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * * @date creation: Tue Sep 16 2014 * @date last modification: Tue Sep 16 2014 * * @brief Tools to implement the plane stress behavior in a material * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_PLANE_STRESS_TOOLBOX_HH__ #define __AKANTU_PLANE_STRESS_TOOLBOX_HH__ __BEGIN_AKANTU__ /** * Empty class in dimensions different from 2 * This class is only specialized for 2D in the tmpl file */ template<UInt dim, class ParentMaterial = Material> class PlaneStressToolbox : public ParentMaterial { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: PlaneStressToolbox(SolidMechanicsModel & model, const ID & id = "") : Material(model, id), ParentMaterial(model, id) {} + PlaneStressToolbox(SolidMechanicsModel & model, + UInt spatial_dimension, + const Mesh & mesh, + FEEngine & fe_engine, + const ID & id = "") : Material(model, spatial_dimension, mesh, fe_engine, id), + ParentMaterial(model, spatial_dimension, mesh, fe_engine, id) {} + virtual ~PlaneStressToolbox() {} +protected: + void initialize(); + +public: virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost){ AKANTU_DEBUG_IN(); ParentMaterial::computeAllCauchyStresses(ghost_type); AKANTU_DEBUG_OUT(); } virtual void computeCauchyStressPlaneStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ERROR("The function \"computeCauchyStressPlaneStress\" can only be used in 2D Plane stress problems, which means that you made a mistake somewhere!! "); AKANTU_DEBUG_OUT(); } protected: bool initialize_third_axis_deformation; }; #define AKANTU_PLANE_STRESS_TOOL_SPEC(dim)\ template<> \ inline PlaneStressToolbox<dim, Material>::PlaneStressToolbox(SolidMechanicsModel & model, \ const ID & id) : \ Material(model, id) {} \ AKANTU_PLANE_STRESS_TOOL_SPEC(1) AKANTU_PLANE_STRESS_TOOL_SPEC(3) __END_AKANTU__ #include "plane_stress_toolbox_tmpl.hh" #endif /* __AKANTU_PLANE_STRESS_TOOLBOX_HH__ */ diff --git a/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh b/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh index dc3e57a78..5b20c9eda 100644 --- a/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh +++ b/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh @@ -1,147 +1,171 @@ /** * @file plane_stress_toolbox_tmpl.hh * * @author Daniel Pino Muñoz <daniel.pinomunoz@epfl.ch> * * @date creation: Tue Sep 16 2014 * @date last modification: Tue Sep 16 2014 * * @brief 2D specialization of the akantu::PlaneStressToolbox 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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_PLANE_STRESS_TOOLBOX_TMPL_HH__ #define __AKANTU_PLANE_STRESS_TOOLBOX_TMPL_HH__ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template<class ParentMaterial> class PlaneStressToolbox<2, ParentMaterial> : public ParentMaterial { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: PlaneStressToolbox(SolidMechanicsModel & model, const ID & id = ""); + PlaneStressToolbox(SolidMechanicsModel & model, + UInt dim, + const Mesh & mesh, + FEEngine & fe_engine, + const ID & id = ""); virtual ~PlaneStressToolbox() {} AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ThirdAxisDeformation, third_axis_deformation, Real); +protected: + void initialize() { + this->registerParam("Plane_Stress", plane_stress, false, _pat_parsmod, "Is plane stress"); + } + /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ virtual void initMaterial() { ParentMaterial::initMaterial(); if(this->plane_stress && this->initialize_third_axis_deformation){ this->third_axis_deformation.initialize(1); this->third_axis_deformation.resize(); } } /* ------------------------------------------------------------------------ */ virtual void computeStress(ElementType el_type, GhostType ghost_type) { ParentMaterial::computeStress(el_type, ghost_type); if(this->plane_stress) computeThirdAxisDeformation(el_type, ghost_type); } /* ------------------------------------------------------------------------ */ virtual void computeThirdAxisDeformation(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type) { } /// Computation of Cauchy stress tensor in the case of finite deformation virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost){ AKANTU_DEBUG_IN(); if(this->plane_stress){ AKANTU_DEBUG_ASSERT(this->finite_deformation,"The Cauchy stress can only be computed if you are working in finite deformation."); //resizeInternalArray(stress); Mesh::type_iterator it = this->model->getFEEngine().getMesh().firstType(2, ghost_type); Mesh::type_iterator last_type = this->model->getFEEngine().getMesh().lastType(2, ghost_type); for(; it != last_type; ++it) this->computeCauchyStressPlaneStress(*it, ghost_type); } else ParentMaterial::computeAllCauchyStresses(ghost_type); AKANTU_DEBUG_OUT(); } virtual void computeCauchyStressPlaneStress(ElementType el_type, GhostType ghost_type = _not_ghost){}; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// third axis strain measure value InternalField<Real> third_axis_deformation; /// Plane stress or plane strain bool plane_stress; /// For non linear materials, the \epsilon_{zz} might be required bool initialize_third_axis_deformation; }; template<class ParentMaterial> inline PlaneStressToolbox<2, ParentMaterial>::PlaneStressToolbox(SolidMechanicsModel & model, const ID & id) : Material(model, id), ParentMaterial(model, id), third_axis_deformation("third_axis_deformation", *this), plane_stress(false), initialize_third_axis_deformation(false) { /// @todo Plane_Stress should not be possible to be modified after initMaterial (but before) - this->registerParam("Plane_Stress", plane_stress, false, _pat_parsmod, "Is plane stress"); + this->initialize(); +} + +template<class ParentMaterial> +inline PlaneStressToolbox<2, ParentMaterial>::PlaneStressToolbox(SolidMechanicsModel & model, + UInt dim, + const Mesh & mesh, + FEEngine & fe_engine, + const ID & id): + Material(model, dim, mesh, fe_engine, id), + ParentMaterial(model, dim, mesh, fe_engine, id), + third_axis_deformation("third_axis_deformation", *this, dim, fe_engine, this->element_filter), + plane_stress(false), + initialize_third_axis_deformation(false) { + this->initialize(); } template<> inline PlaneStressToolbox<2, Material>::PlaneStressToolbox(SolidMechanicsModel & model, const ID & id) : Material(model, id), third_axis_deformation("third_axis_deformation", *this), plane_stress(false), initialize_third_axis_deformation(false) { /// @todo Plane_Stress should not be possible to be modified after initMaterial (but before) this->registerParam("Plane_Stress", plane_stress, false, _pat_parsmod, "Is plane stress"); } __END_AKANTU__ #endif /* __AKANTU_PLANE_STRESS_TOOLBOX_TMPL_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh index daba20874..90d6356a5 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive.hh @@ -1,290 +1,290 @@ /** * @file solid_mechanics_model_cohesive.hh * * @author Marco Vocialta <marco.vocialta@epfl.ch> * * @date creation: Tue May 08 2012 * @date last modification: Tue Sep 02 2014 * * @brief Solid mechanics model for cohesive elements * * @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 <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ #define __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ #include "solid_mechanics_model.hh" #include "solid_mechanics_model_event_handler.hh" #include "cohesive_element_inserter.hh" #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) # include "facet_synchronizer.hh" # include "facet_stress_synchronizer.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ struct SolidMechanicsModelCohesiveOptions : public SolidMechanicsModelOptions { SolidMechanicsModelCohesiveOptions(AnalysisMethod analysis_method = _explicit_lumped_mass, bool extrinsic = false, bool no_init_materials = false) : SolidMechanicsModelOptions(analysis_method, no_init_materials), extrinsic(extrinsic) {} bool extrinsic; }; extern const SolidMechanicsModelCohesiveOptions default_solid_mechanics_model_cohesive_options; /* -------------------------------------------------------------------------- */ /* Solid Mechanics Model for Cohesive elements */ /* -------------------------------------------------------------------------- */ class SolidMechanicsModelCohesive : public SolidMechanicsModel, public SolidMechanicsModelEventHandler{ /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: class NewCohesiveNodesEvent : public NewNodesEvent { public: AKANTU_GET_MACRO_NOT_CONST(OldNodesList, old_nodes, Array<UInt> &); AKANTU_GET_MACRO(OldNodesList, old_nodes, const Array<UInt> &); protected: Array<UInt> old_nodes; }; typedef FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive> MyFEEngineCohesiveType; SolidMechanicsModelCohesive(Mesh & mesh, UInt spatial_dimension = _all_dimensions, const ID & id = "solid_mechanics_model_cohesive", const MemoryID & memory_id = 0); virtual ~SolidMechanicsModelCohesive(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// set the value of the time step void setTimeStep(Real time_step); /// assemble the residual for the explicit scheme virtual void updateResidual(bool need_initialize = true); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /// function to perform a stress check on each facet and insert /// cohesive elements if needed (returns the number of new cohesive /// elements) UInt checkCohesiveStress(); /// interpolate stress on facets void interpolateStress(); /// initialize the cohesive model void initFull(const ModelOptions & options = default_solid_mechanics_model_cohesive_options); /// initialize the model void initModel(); /// initialize cohesive material void initMaterials(); /// init facet filters for cohesive materials void initFacetFilter(); /// limit the cohesive element insertion to a given area void limitInsertion(BC::Axis axis, Real first_limit, Real second_limit); /// update automatic insertion after a change in the element inserter void updateAutomaticInsertion(); /// insert intrinsic cohesive elements void insertIntrinsicElements(); template<SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria> bool solveStepCohesive(Real tolerance, Real & error, UInt max_iteration = 100, - UInt cont = 1, + bool load_reduction = false, bool do_not_factorize = false); /// initialize stress interpolation void initStressInterpolation(); private: /// initialize completely the model for extrinsic elements void initAutomaticInsertion(); /// compute facets' normals void computeNormals(); /// resize facet stress void resizeFacetStress(); /// init facets_check array void initFacetsCheck(); /* ------------------------------------------------------------------------ */ /* Mesh Event Handler inherited members */ /* ------------------------------------------------------------------------ */ protected: virtual void onNodesAdded (const Array<UInt> & nodes_list, const NewNodesEvent & event); virtual void onElementsAdded (const Array<Element> & nodes_list, const NewElementsEvent & event); /* ------------------------------------------------------------------------ */ /* SolidMechanicsModelEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: virtual void onEndSolveStep(const AnalysisMethod & method); /* ------------------------------------------------------------------------ */ /* Dumpable interface */ /* ------------------------------------------------------------------------ */ public: virtual void onDump(); virtual void addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name, const ElementKind & element_kind, bool padding_flag); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get facet mesh AKANTU_GET_MACRO(MeshFacets, mesh.getMeshFacets(), const Mesh &); /// get stress on facets vector AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(StressOnFacets, facet_stress, Real); /// get facet material AKANTU_GET_MACRO_BY_ELEMENT_TYPE(FacetMaterial, facet_material, UInt); /// get facet material AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(FacetMaterial, facet_material, UInt); /// get facet material AKANTU_GET_MACRO(FacetMaterial, facet_material, const ElementTypeMapArray<UInt> &); /// @todo THIS HAS TO BE CHANGED AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Tangents, tangents, Real); /// get element inserter AKANTU_GET_MACRO_NOT_CONST(ElementInserter, *inserter, CohesiveElementInserter &); /// get is_extrinsic boolean AKANTU_GET_MACRO(IsExtrinsic, is_extrinsic, bool); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// @todo store tangents when normals are computed: ElementTypeMapArray<Real> tangents; /// stress on facets on the two sides by quadrature point ElementTypeMapArray<Real> facet_stress; /// material to use if a cohesive element is created on a facet ElementTypeMapArray<UInt> facet_material; bool is_extrinsic; /// cohesive element inserter CohesiveElementInserter * inserter; #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) #include "solid_mechanics_model_cohesive_parallel.hh" #endif }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ class DefaultMaterialCohesiveSelector : public DefaultMaterialSelector { public: DefaultMaterialCohesiveSelector(const SolidMechanicsModelCohesive & model) : DefaultMaterialSelector(model.getMaterialByElement()), facet_material(model.getFacetMaterial()), mesh(model.getMesh()) { } inline virtual UInt operator()(const Element & element) { if(Mesh::getKind(element.type) == _ek_cohesive) { try { const Array<Element> & cohesive_el_to_facet = mesh.getMeshFacets().getSubelementToElement(element.type, element.ghost_type); bool third_dimension = (mesh.getSpatialDimension() == 3); const Element & facet = cohesive_el_to_facet(element.element, third_dimension); if(facet_material.exists(facet.type, facet.ghost_type)) { return facet_material(facet.type, facet.ghost_type)(facet.element); } else { return MaterialSelector::operator()(element); } } catch (...) { return MaterialSelector::operator()(element); } } else if (Mesh::getSpatialDimension(element.type) == mesh.getSpatialDimension() - 1) { return facet_material(element.type, element.ghost_type)(element.element); } else { return DefaultMaterialSelector::operator()(element); } } private: const ElementTypeMapArray<UInt> & facet_material; const Mesh & mesh; }; /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const SolidMechanicsModelCohesive & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #if defined (AKANTU_INCLUDE_INLINE_IMPL) # include "solid_mechanics_model_cohesive_inline_impl.cc" #endif #endif /* __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_HH__ */ diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive_inline_impl.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive_inline_impl.cc index 384f50e4c..d538d5e68 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive_inline_impl.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive_inline_impl.cc @@ -1,255 +1,261 @@ /** * @file solid_mechanics_model_cohesive_inline_impl.cc * * @author Mauro Corrado <mauro.corrado@epfl.ch> * * @date Thu Feb 26 14:23:45 2015 * * @brief Implementation of inline functions for the Cohesive element model * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include <algorithm> #include "material_cohesive.hh" #ifndef __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_INLINE_IMPL_CC__ #define __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_INLINE_IMPL_CC__ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template<SolveConvergenceMethod cmethod, SolveConvergenceCriteria criteria> bool SolidMechanicsModelCohesive::solveStepCohesive(Real tolerance, Real & error, UInt max_iteration, - UInt cont, + bool load_reduction, bool do_not_factorize) { EventManager::sendEvent(SolidMechanicsModelEvent::BeforeSolveStepEvent(method)); this->implicitPred(); bool insertion_new_element = true; bool converged = false; Array<Real> * displacement_tmp = NULL; Array<Real> * velocity_tmp = NULL; Array<Real> * acceleration_tmp = NULL; StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Int prank = comm.whoAmI(); while (insertion_new_element) { //loop for insertion of new cohesive elements if (is_extrinsic) { // If in extrinsic saves the current displacements, velocities and accelerations Array<Real> * tmp_swap; if(!displacement_tmp) { displacement_tmp = new Array<Real>(*(this->displacement)); } else { (*displacement_tmp).resize(this->displacement->getSize()); //displacement_tmp->resize(this->displacement->getSize()); (*displacement_tmp).copy(*(this->displacement)); //displacement_tmp->copy(*(this->displacement)); } tmp_swap = displacement_tmp; displacement_tmp = this->displacement; this->displacement = tmp_swap; if(!velocity_tmp) { velocity_tmp = new Array<Real>(*(this->velocity)); } else { velocity_tmp->resize(this->velocity->getSize()); velocity_tmp->copy(*(this->velocity)); } tmp_swap = velocity_tmp; velocity_tmp = this->velocity; this->velocity = tmp_swap; if(!acceleration_tmp) { acceleration_tmp = new Array<Real>(*(this->acceleration)); } else { acceleration_tmp->resize(this->acceleration->getSize()); acceleration_tmp->copy(*(this->acceleration)); } tmp_swap = acceleration_tmp; acceleration_tmp = this->acceleration; this->acceleration = tmp_swap; } this->updateResidual(); AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, "You should first initialize the implicit solver and assemble the stiffness matrix"); bool need_factorize = !do_not_factorize; if (method ==_implicit_dynamic) { AKANTU_DEBUG_ASSERT(mass_matrix != NULL, "You should first initialize the implicit solver and assemble the mass matrix"); } switch (cmethod) { case _scm_newton_raphson_tangent: case _scm_newton_raphson_tangent_not_computed: break; case _scm_newton_raphson_tangent_modified: this->assembleStiffnessMatrix(); break; default: AKANTU_DEBUG_ERROR("The resolution method " << cmethod << " has not been implemented!"); } UInt iter = 0; converged = false; error = 0.; if(criteria == _scc_residual) { converged = this->testConvergence<criteria> (tolerance, error); if(converged) return converged; } do { if (cmethod == _scm_newton_raphson_tangent) this->assembleStiffnessMatrix(); solve<NewmarkBeta::_displacement_corrector> (*increment, 1., need_factorize); this->implicitCorr(); this->updateResidual(); converged = this->testConvergence<criteria> (tolerance, error); iter++; AKANTU_DEBUG_INFO("[" << criteria << "] Convergence iteration " << std::setw(std::log10(max_iteration)) << iter << ": error " << error << (converged ? " < " : " > ") << tolerance); switch (cmethod) { case _scm_newton_raphson_tangent: need_factorize = true; break; case _scm_newton_raphson_tangent_not_computed: case _scm_newton_raphson_tangent_modified: need_factorize = false; break; default: AKANTU_DEBUG_ERROR("The resolution method " << cmethod << " has not been implemented!"); } } while (!converged && iter < max_iteration); + // dump(); + // dump("cohesive elements"); + + if (load_reduction && (error < tolerance * 1000)) converged = true; if (converged) { //// EventManager::sendEvent(SolidMechanicsModelEvent::AfterSolveStepEvent(method)); // !!! add sendEvent to call computeCauchyStress !!!! if (prank==0){ std::cout << "Error after convergence: " << error << std::endl; std::cout << "no. of iterations: " << iter << std::endl; } } else if(iter == max_iteration) { if (prank==0){ AKANTU_DEBUG_WARNING("[" << criteria << "] Convergence not reached after " << std::setw(std::log10(max_iteration)) << iter << " iteration" << (iter == 1 ? "" : "s") << "!" << std::endl); std::cout << "Error after NON convergence: " << error << std::endl; } } if (is_extrinsic) { Array<Real> * tmp_swap; tmp_swap = displacement_tmp; displacement_tmp = this->displacement; this->displacement = tmp_swap; tmp_swap = velocity_tmp; velocity_tmp = this->velocity; this->velocity = tmp_swap; tmp_swap = acceleration_tmp; acceleration_tmp = this->acceleration; this->acceleration = tmp_swap; - if (converged || cont == 2){ - UInt nb_cohesive_elements = this->mesh.getNbElement(this->spatial_dimension, _not_ghost, _ek_cohesive); - this->checkCohesiveStress(); + if (converged){ // || load_reduction){ + // UInt nb_cohesive_elements = this->mesh.getNbElement(this->spatial_dimension, _not_ghost, _ek_cohesive); + // this->checkCohesiveStress(); + // UInt new_nb_cohesive_elements = this->mesh.getNbElement(this->spatial_dimension, _not_ghost, _ek_cohesive); - UInt new_nb_cohesive_elements = this->mesh.getNbElement(this->spatial_dimension, _not_ghost, _ek_cohesive); + UInt new_cohesive_elements = checkCohesiveStress(); - UInt nb_cohe[2]; - nb_cohe[0] = nb_cohesive_elements; - nb_cohe[1] = new_nb_cohesive_elements; + // UInt nb_cohe[2]; + //nb_cohe[0] = nb_cohesive_elements; + //nb_cohe[1] = new_nb_cohesive_elements; - StaticCommunicator::getStaticCommunicator().allReduce(nb_cohe, 2, _so_sum); + // StaticCommunicator::getStaticCommunicator().allReduce(nb_cohe, 2, _so_sum); - if(nb_cohe[0] == nb_cohe[1]) { + // if(nb_cohe[0] == nb_cohe[1]) { + if(new_cohesive_elements == 0){ insertion_new_element = false; } else { insertion_new_element = true; if (prank==0) - std::cout << "1 cohesive element has been inserted" << std::endl; + std::cout << "No. cohesive elements inserted = " << new_cohesive_elements << std::endl; } } } - if (!converged && cont != 2){ + if (!converged){ // && !load_reduction){ insertion_new_element = false; for (UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat = dynamic_cast<MaterialCohesive &>(*materials[m]); mat.checkDeltaMax(_not_ghost); } catch(std::bad_cast&) { } } } } //end while insertion_new_element - if ((is_extrinsic && converged) || (is_extrinsic && cont == 2)) { + if ((is_extrinsic && converged)){ // || (is_extrinsic && load_reduction)) { EventManager::sendEvent(SolidMechanicsModelEvent::AfterSolveStepEvent(method)); this->displacement->copy(*displacement_tmp); this->velocity ->copy(*velocity_tmp); this->acceleration->copy(*acceleration_tmp); delete displacement_tmp; delete velocity_tmp; delete acceleration_tmp; } return insertion_new_element; } __END_AKANTU__ #if defined (AKANTU_PARALLEL_COHESIVE_ELEMENT) # include "solid_mechanics_model_cohesive_parallel_inline_impl.cc" #endif #endif /* __AKANTU_SOLID_MECHANICS_MODEL_COHESIVE_INLINE_IMPL_CC__ */ diff --git a/test/test_model/test_solid_mechanics_model/test_embedded_interface/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_embedded_interface/CMakeLists.txt index 84a2ddabf..31ac629ff 100644 --- a/test/test_model/test_solid_mechanics_model/test_embedded_interface/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_embedded_interface/CMakeLists.txt @@ -1,49 +1,49 @@ #=============================================================================== # @file CMakeLists.txt # # @author Lucas Frérot <lucas.frerot@epfl.ch> # # @date creation: Wed Mar 25 2015 # @date last modification: Wed Mar 25 2015 # # @brief configuration for embedded interface tests # # @section LICENSE # # Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== register_test(test_embedded_element_matrix SOURCES test_embedded_element_matrix.cc FILES_TO_COPY triangle.msh embedded_element.dat - PACKAGE embedded + PACKAGE embedded implicit ) register_test(test_embedded_interface_model SOURCES test_embedded_interface_model.cc FILES_TO_COPY embedded_mesh.msh material.dat matrix - PACKAGE embedded + PACKAGE embedded implicit ) register_test(test_embedded_interface_model_prestress SOURCES test_embedded_interface_model_prestress.cc FILES_TO_COPY embedded_mesh_prestress.msh embedded_mesh_prestress_reinforcement.msh prestress.dat - PACKAGE embedded + PACKAGE embedded implicit ) diff --git a/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt index 4f9679296..245621a12 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt @@ -1,61 +1,61 @@ #=============================================================================== # @file CMakeLists.txt # # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # # @date creation: Fri Nov 26 2010 # @date last modification: Fri Feb 14 2014 # # @brief configuration for materials tests # # @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 <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== add_mesh(test_local_material_barre_trou_mesh barre_trou.geo 2 2) register_test(test_local_material SOURCES test_local_material.cc local_material_damage.cc EXTRA_FILES local_material_damage.hh local_material_damage_inline_impl.cc DEPENDENCIES test_local_material_barre_trou_mesh FILES_TO_COPY material.dat DIRECTORIES_TO_CREATE paraview PACKAGE core ) add_mesh(test_material_thermal_mesh square.geo 2 1) register_test(test_material_thermal SOURCES test_material_thermal.cc DEPENDENCIES test_material_thermal_mesh FILES_TO_COPY material_thermal.dat PACKAGE core ) # ============================================================================== add_mesh(test_interpolate_stress_mesh interpolation.geo 3 2) register_test(test_interpolate_stress test_interpolate_stress.cc FILES_TO_COPY material.dat DEPENDENCIES test_interpolate_stress_mesh DIRECTORIES_TO_CREATE paraview - PACKAGE core + PACKAGE lapack core ) # ============================================================================== add_akantu_test(test_material_viscoelastic "test the visco elastic materials") add_akantu_test(test_material_non_local "test the non-local materials")