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 # @author Nicolas Richart # # @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 . # # @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 # @author Guillaume Anciaux # # @date creation: Thu Dec 20 2012 # @date last modification: Wed Sep 10 2014 # # @brief Set of macros used by akantu to handle the package system # # @section DESCRIPTION # # This package defines multiple function to handle packages. This packages can # be of two kinds regular ones and extra_packages (ex: in akantu the LGPL part # is regular packages and extra packages are on Propetary license) # # Package are loaded with the help of the command: # package_list_packages( # [ EXTRA_PACKAGE_FOLDER ] # [ SOURCE_FOLDER ] # [ TEST_FOLDER ] # [ MANUAL_FOLDER ] # ) # # This command will look for packages name like # /.cmake # OR //package.cmake # # A package is a cmake script that should contain at list the declaration of a # package # # package_declare( # [EXTERNAL] [META] [ADVANCED] [NOT_OPTIONAL] # [DESCRIPTION ] [DEFAULT ] # [DEPENDS ...] # [BOOST_COMPONENTS ...] # [EXTRA_PACKAGE_OPTIONS ...] # [COMPILE_FLAGS ] # [SYSTEM [ ]]) # # It can also declare multiple informations: # source files: # package_declare_sources( # ... ) # # a LaTeX documentation: # package_declare_documentation( # ...) # # LaTeX documentation files # package_declare_documentation_files( # ... ) # # Different function can also be retrieved from the package system by using the # different accessors # package_get_name( ) # package_get_real_name( ) # # package_get_option_name( ) # # package_use_system( ) # # package_get_nature( ) # # package_get_description( ) # # package_get_filename( ) # # package_get_sources_folder( ) # package_get_tests_folder( ) # package_get_manual_folder( ) # # package_get_find_package_extra_options( ) # # package_get_compile_flags( ) # # package_get_include_dir( ) # package_set_include_dir( ... ) # # package_get_libraries( ) # package_set_libraries( ... ) # # package_add_extra_dependency(pkg ... ) # package_rm_extra_dependency( ) # package_get_extra_dependencies( ) # # package_is_activated( ) # package_is_deactivated( ) # # package_get_dependencies( ) # package_add_dependencies( ... ) # # package_get_all_source_files( ) # package_get_all_include_directories() # package_get_all_external_informations( ) # package_get_all_definitions() # package_get_all_extra_dependencies() # package_get_all_test_folders() # package_get_all_documentation_files() # package_get_all_activated_packages() # package_get_all_packages() # # # @section LICENSE # # Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # #=============================================================================== include(CMakeParseArguments) #=============================================================================== # Package Management #=============================================================================== if(__CMAKE_PACKAGES_SYSTEM) return() endif() set(__CMAKE_PACKAGES_SYSTEM TRUE) +if(CMAKE_VERSION VERSION_GREATER 3.1.2) + cmake_policy(SET CMP0054 NEW) +endif() 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 # /.cmake # # Extra packages folder structure # //package.cmake # /src # /test # /manual # # ------------------------------------------------------------------------------ function(package_list_packages PACKAGE_FOLDER) cmake_parse_arguments(_opt_pkg "" "SOURCE_FOLDER;EXTRA_PACKAGES_FOLDER;TEST_FOLDER;MANUAL_FOLDER" "" ${ARGN}) string(TOUPPER ${PROJECT_NAME} _project) # Cleaning some states to start correctly package_get_all_packages(_already_loaded_pkg) foreach(_pkg_name ${_already_loaded_pkg}) _package_unset_extra_dependencies(${_pkg_name}) _package_unset_dependencies(${_pkg_name}) _package_unset_activated(${_pkg_name}) endforeach() if(_opt_pkg_SOURCE_FOLDER) set(_src_folder "${_opt_pkg_SOURCE_FOLDER}") else() set(_src_folder "src/") endif() get_filename_component(_abs_src_folder ${_src_folder} ABSOLUTE) if(_opt_pkg_TEST_FOLDER) set(_test_folder "${_opt_pkg_TEST_FOLDER}") else() set(_test_folder "test/") endif() if(_opt_pkg_MANUAL_FOLDER) set(_manual_folder "${_opt_pkg_MANUAL_FOLDER}") else() set(_manual_folder "doc/manual") endif() get_filename_component(_abs_test_folder ${_test_folder} ABSOLUTE) get_filename_component(_abs_manual_folder ${_manual_folder} ABSOLUTE) # check all the packages in the file(GLOB _package_list "${PACKAGE_FOLDER}/*.cmake") set(_package_files) foreach(_pkg ${_package_list}) get_filename_component(_basename ${_pkg} NAME) if(NOT _basename MATCHES "^\\.#.*") list(APPEND _package_files ${_basename}) endif() endforeach() if(_package_files) list(SORT _package_files) endif() # check all packages set(_packages_list_all) foreach(_pkg_file ${_package_files}) string(REGEX REPLACE "[0-9]+_" "" _pkg_file_stripped ${_pkg_file}) string(REGEX REPLACE "\\.cmake" "" _pkg ${_pkg_file_stripped}) package_get_name(${_pkg} _pkg_name) _package_set_filename(${_pkg_name} "${PACKAGE_FOLDER}/${_pkg_file}") _package_set_sources_folder(${_pkg_name} "${_abs_src_folder}") _package_set_tests_folder(${_pkg_name} "${_abs_test_folder}") _package_set_manual_folder(${_pkg_name} "${_abs_manual_folder}") list(APPEND _packages_list_all ${_pkg_name}) include("${PACKAGE_FOLDER}/${_pkg_file}") endforeach() # check the extra_packages if they exists if(_opt_pkg_EXTRA_PACKAGES_FOLDER) file(GLOB _extra_package_list RELATIVE "${_opt_pkg_EXTRA_PACKAGES_FOLDER}" "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/*") foreach(_pkg ${_extra_package_list}) if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake") package_get_name(${_pkg} _pkg_name) _package_set_filename(${_pkg_name} "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake") _package_set_sources_folder(${_pkg_name} "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/src") if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/test") _package_set_tests_folder(${_pkg_name} "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/test") endif() if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/manual") _package_set_manual_folder(${_pkg_name} "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/manual") endif() list(APPEND _extra_pkg_src_folders "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/src") list(APPEND _packages_list_all ${_pkg_name}) include("${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake") endif() endforeach() endif() # Store the list of packages string(TOUPPER ${PROJECT_NAME} _project) set(${_project}_ALL_PACKAGES_LIST ${_packages_list_all} CACHE INTERNAL "List of available packages" FORCE) _package_build_rdependencies() _package_load_packages() _package_check_files_exists() _package_check_files_registered(${_abs_src_folder} ${_extra_pkg_src_folders}) # Load boost components if boost was loaded package_is_activated(Boost _ret) if(_ret) _package_load_boost_components() endif() endfunction() # ------------------------------------------------------------------------------ # macro to include internal/external packages packages # package_declare( # [EXTERNAL] [META] [ADVANCED] [NOT_OPTIONAL] # [DESCRIPTION ] [DEFAULT ] # [DEPENDS ...] # [BOOST_COMPONENTS ...] # [EXTRA_PACKAGE_OPTIONS ...] # [COMPILE_FLAGS ] # [SYSTEM [ ]]) # ------------------------------------------------------------------------------ function(package_declare pkg) package_get_name(${pkg} _pkg_name) _package_set_real_name(${_pkg_name} ${pkg}) cmake_parse_arguments(_opt_pkg "EXTERNAL;NOT_OPTIONAL;META;ADVANCED" "DEFAULT;DESCRIPTION" "DEPENDS;EXTRA_PACKAGE_OPTIONS;COMPILE_FLAGS;BOOST_COMPONENTS;SYSTEM" ${ARGN}) if(_opt_pkg_UNPARSED_ARGUMENTS) message("You gave to many arguments while registering the package ${pkg} \"${_opt_pkg_UNPARSED_ARGUMENTS}\"") endif() # set 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( # SOURCES ... # PUBLIC_HEADER
... # PRIVATE_HEADER
...) # ------------------------------------------------------------------------------ function(package_declare_sources pkg) package_get_name(${pkg} _pkg_name) # get 3 lists, if none of the options given try to distinguish the different lists cmake_parse_arguments(_opt_pkg "" "" "SOURCES;PUBLIC_HEADERS;PRIVATE_HEADERS" ${ARGN}) set(_tmp_srcs ${_opt_pkg_SOURCES}) set(_tmp_pub_hdrs ${_opt_pkg_PUBLIC_HEADER}) set(_tmp_pri_hdrs ${_opt_pkg_PRIVATE_HEADERS}) foreach(_file ${_opt_pkg_UNPARSED_ARGUMENTS}) if(${_file} MATCHES ".*inline.*\\.cc") list(APPEND _tmp_pub_hdrs ${_file}) elseif(${_file} MATCHES ".*\\.h+") list(APPEND _tmp_pub_hdrs ${_file}) else() list(APPEND _tmp_srcs ${_file}) endif() endforeach() _package_get_sources_folder(${_pkg_name} _src_folder) foreach(_type _srcs _pub_hdrs _pri_hdrs) set(${_type}) foreach(_file ${_tmp${_type}}) # get the full name list(APPEND ${_type} "${_src_folder}/${_file}") endforeach() endforeach() set(${_pkg_name}_SRCS "${_srcs}" CACHE INTERNAL "List of sources files" FORCE) set(${_pkg_name}_PUBLIC_HEADERS "${_pub_hdrs}" CACHE INTERNAL "List of public header files" FORCE) set(${_pkg_name}_PRIVATE_HEADERS "${_pri_hdrs}" CACHE INTERNAL "List of private header files" FORCE) endfunction() # ============================================================================== # "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/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 # # @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 . # #=============================================================================== 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/python/swig/aka_common.i b/python/swig/aka_common.i index fd9c3b4ec..65fe15e9f 100644 --- a/python/swig/aka_common.i +++ b/python/swig/aka_common.i @@ -1,30 +1,61 @@ %{ #include "aka_common.hh" %} namespace akantu { %ignore getStaticParser; %ignore getUserParser; %ignore initialize(int & argc, char ** & argv); - %ignore initialize(const std::string & input_file, int & argc, char ** & argv); } +%typemap(in) (int argc, char *argv[]) { + int i; + if (!PyList_Check($input)) { + PyErr_SetString(PyExc_ValueError, "Expecting a list"); + return NULL; + } + $1 = PyList_Size($input); + $2 = (char **) malloc(($1+1)*sizeof(char *)); + for (i = 0; i < $1; i++) { + PyObject *s = PyList_GetItem($input,i); + if (!PyString_Check(s)) { + free($2); + PyErr_SetString(PyExc_ValueError, "List items must be strings"); + return NULL; + } + $2[i] = PyString_AsString(s); + } + $2[i] = 0; +} + +%typemap(freearg) (int argc, char *argv[]) { + if ($2) free($2); +} %inline %{ namespace akantu { void initialize(const std::string & input_file) { int argc = 0; char ** argv = NULL; initialize(input_file, argc, argv); } void initialize() { int argc = 0; char ** argv = NULL; initialize(argc, argv); - } - } - %} + } + void _initializeWithArgv(const std::string & input_file, int argc, char *argv[]) { + initialize(input_file, argc, argv); + } + + } +%} +%pythoncode %{ + import sys as _aka_sys + def initializeWithArgv(input_file): + _initializeWithArgv(input_file, _aka_sys.argv) +%} %include "aka_common.hh" diff --git a/python/swig/mesh.i b/python/swig/mesh.i index d5740a174..7935a2daa 100644 --- a/python/swig/mesh.i +++ b/python/swig/mesh.i @@ -1,113 +1,114 @@ %{ #include "mesh.hh" #include "node_group.hh" #include "solid_mechanics_model.hh" using akantu::Vector; using akantu::ElementTypeMapArray; using akantu::MatrixProxy; using akantu::Matrix; using akantu::UInt; using akantu::Real; using akantu::Array; using akantu::SolidMechanicsModel; %} namespace akantu { %ignore NewNodesEvent; %ignore RemovedNodesEvent; %ignore NewElementsEvent; %ignore RemovedElementsEvent; %ignore MeshEventHandler; %ignore MeshEvent< UInt >; %ignore MeshEvent< Element >; %ignore Mesh::extractNodalCoordinatesFromPBCElement; %ignore Mesh::getGroupDumer; + %ignore Mesh::getFacetLocalConnectivity; } print_self(Mesh) %extend akantu::Mesh { void resizeMesh(UInt nb_nodes, UInt nb_element, const ElementType & type) { Array & nodes = const_cast &>($self->getNodes()); nodes.resize(nb_nodes); $self->addConnectivityType(type); Array & connectivity = const_cast &>($self->getConnectivity(type)); connectivity.resize(nb_element); } } %extend akantu::GroupManager { void createGroupsFromStringMeshData(const std::string & dataset_name) { $self->createGroupsFromMeshData(dataset_name); } void createGroupsFromUIntMeshData(const std::string & dataset_name) { $self->createGroupsFromMeshData(dataset_name); } } %extend akantu::NodeGroup { akantu::Array & getGroupedNodes(akantu::Array & surface_array, Mesh & mesh) { akantu::Array group_node = $self->getNodes(); akantu::Array & full_array = mesh.getNodes(); surface_array.resize(group_node.getSize()); for (UInt i = 0; i < group_node.getSize(); ++i) { for (UInt cmp = 0; cmp < full_array.getNbComponent(); ++cmp) { surface_array(i,cmp) = full_array(group_node(i),cmp); } } akantu::Array & res(surface_array); return res; } akantu::Array & getGroupedArray(akantu::Array & surface_array, akantu::SolidMechanicsModel & model, int type) { akantu::Array * full_array; switch (type) { case 0 : full_array = new akantu::Array(model.getDisplacement()); break; case 1 : full_array = new akantu::Array(model.getVelocity()); break; case 2 : full_array = new akantu::Array(model.getForce()); break; } akantu::Array group_node = $self->getNodes(); surface_array.resize(group_node.getSize()); for (UInt i = 0; i < group_node.getSize(); ++i) { for (UInt cmp = 0; cmp < full_array->getNbComponent(); ++cmp) { surface_array(i,cmp) = (*full_array)(group_node(i),cmp); } } akantu::Array & res(surface_array); return res; } } %include "group_manager.hh" %include "element_group.hh" %include "node_group.hh" %include "mesh.hh" diff --git a/src/common/aka_config.hh.in b/src/common/aka_config.hh.in index 8f94135aa..f5bc4c401 100644 --- a/src/common/aka_config.hh.in +++ b/src/common/aka_config.hh.in @@ -1,93 +1,95 @@ /** * @file aka_config.hh.in * * @author Nicolas Richart * * @date Fri Jan 13 12:34:54 2012 * * @brief Compilation time configuration of Akantu * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_CONFIG_HH__ #define __AKANTU_AKA_CONFIG_HH__ -#define AKANTU_VERSION @AKANTU_VERSION@ #define AKANTU_VERSION_MAJOR @AKANTU_MAJOR_VERSION@ #define AKANTU_VERSION_MINOR @AKANTU_MINOR_VERSION@ #define AKANTU_VERSION_PATCH @AKANTU_PATCH_VERSION@ +#define AKANTU_VERSION (AKANTU_VERSION_MAJOR * 100000 \ + + AKANTU_VERSION_MINOR * 1000 \ + + AKANTU_VERSION_PATCH) #cmakedefine AKANTU_USE_BLAS #cmakedefine AKANTU_USE_LAPACK #cmakedefine AKANTU_PARALLEL #cmakedefine AKANTU_USE_MPI #cmakedefine AKANTU_USE_SCOTCH #cmakedefine AKANTU_USE_PTSCOTCH #cmakedefine AKANTU_SCOTCH_NO_EXTERN #cmakedefine AKANTU_USE_MUMPS #cmakedefine AKANTU_USE_PETSC #cmakedefine AKANTU_USE_IOHELPER #cmakedefine AKANTU_USE_QVIEW #cmakedefine AKANTU_USE_BLACKDYNAMITE #cmakedefine AKANTU_USE_NLOPT #cmakedefine AKANTU_USE_CPPARRAY #cmakedefine AKANTU_USE_OBSOLETE_GETTIMEOFDAY #cmakedefine AKANTU_EXTRA_MATERIALS #cmakedefine AKANTU_STUDENTS_EXTRA_PACKAGE #cmakedefine AKANTU_DAMAGE_NON_LOCAL #cmakedefine AKANTU_STRUCTURAL_MECHANICS #cmakedefine AKANTU_HEAT_TRANSFER #cmakedefine AKANTU_COHESIVE_ELEMENT #cmakedefine AKANTU_PARALLEL_COHESIVE_ELEMENT #cmakedefine AKANTU_IGFEM #cmakedefine AKANTU_USE_CGAL #cmakedefine AKANTU_EMBEDDED // BOOST Section #cmakedefine AKANTU_BOOST_CHRONO #cmakedefine AKANTU_BOOST_SYSTEM // Experimental part #cmakedefine AKANTU_CORE_CXX11 // Debug tools //#cmakedefine AKANTU_NDEBUG #cmakedefine AKANTU_DEBUG_TOOLS #cmakedefine READLINK_COMMAND @READLINK_COMMAND@ #cmakedefine ADDR2LINE_COMMAND @ADDR2LINE_COMMAND@ #define __aka_inline__ inline #endif /* __AKANTU_AKA_CONFIG_HH__ */ diff --git a/src/common/aka_math.cc b/src/common/aka_math.cc index 51342067f..71aedd3de 100644 --- a/src/common/aka_math.cc +++ b/src/common/aka_math.cc @@ -1,189 +1,233 @@ /** * @file aka_math.cc * * @author Leonardo Snozzi * @author Marion Estelle Chambart * @author Peter Spijker * @author Nicolas Richart * @author Guillaume Anciaux * @author Marco Vocialta * @author David Simon Kammer * * @date creation: Wed Aug 04 2010 * @date last modification: Thu Mar 27 2014 * * @brief Implementation of the math toolbox * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_math.hh" #include "aka_array.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void Math::matrix_vector(UInt m, UInt n, const Array & A, const Array & x, Array & y, Real alpha) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(A.getSize() == x.getSize(), "The vector A(" << A.getID() << ") and the vector x(" << x.getID() << ") must have the same size"); AKANTU_DEBUG_ASSERT(A.getNbComponent() == m * n, "The vector A(" << A.getID() << ") has the good number of component."); AKANTU_DEBUG_ASSERT(x.getNbComponent() == n, "The vector x(" << x.getID() << ") do not the good number of component."); AKANTU_DEBUG_ASSERT(y.getNbComponent() == n, "The vector y(" << y.getID() << ") do not the good number of component."); UInt nb_element = A.getSize(); UInt offset_A = A.getNbComponent(); UInt offset_x = x.getNbComponent(); y.resize(nb_element); Real * A_val = A.storage(); Real * x_val = x.storage(); Real * y_val = y.storage(); for (UInt el = 0; el < nb_element; ++el) { matrix_vector(m, n, A_val, x_val, y_val, alpha); A_val += offset_A; x_val += offset_x; y_val += offset_x; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Math::matrix_matrix(UInt m, UInt n, UInt k, const Array & A, const Array & B, Array & C, Real alpha) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(A.getSize() == B.getSize(), "The vector A(" << A.getID() << ") and the vector B(" << B.getID() << ") must have the same size"); AKANTU_DEBUG_ASSERT(A.getNbComponent() == m * k, "The vector A(" << A.getID() << ") has the good number of component."); AKANTU_DEBUG_ASSERT(B.getNbComponent() == k * n , "The vector B(" << B.getID() << ") do not the good number of component."); AKANTU_DEBUG_ASSERT(C.getNbComponent() == m * n, "The vector C(" << C.getID() << ") do not the good number of component."); UInt nb_element = A.getSize(); UInt offset_A = A.getNbComponent(); UInt offset_B = B.getNbComponent(); UInt offset_C = C.getNbComponent(); C.resize(nb_element); Real * A_val = A.storage(); Real * B_val = B.storage(); Real * C_val = C.storage(); for (UInt el = 0; el < nb_element; ++el) { matrix_matrix(m, n, k, A_val, B_val, C_val, alpha); A_val += offset_A; B_val += offset_B; C_val += offset_C; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Math::matrix_matrixt(UInt m, UInt n, UInt k, const Array & A, const Array & B, Array & C, Real alpha) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(A.getSize() == B.getSize(), "The vector A(" << A.getID() << ") and the vector B(" << B.getID() << ") must have the same size"); AKANTU_DEBUG_ASSERT(A.getNbComponent() == m * k, "The vector A(" << A.getID() << ") has the good number of component."); AKANTU_DEBUG_ASSERT(B.getNbComponent() == k * n , "The vector B(" << B.getID() << ") do not the good number of component."); AKANTU_DEBUG_ASSERT(C.getNbComponent() == m * n, "The vector C(" << C.getID() << ") do not the good number of component."); UInt nb_element = A.getSize(); UInt offset_A = A.getNbComponent(); UInt offset_B = B.getNbComponent(); UInt offset_C = C.getNbComponent(); C.resize(nb_element); Real * A_val = A.storage(); Real * B_val = B.storage(); Real * C_val = C.storage(); for (UInt el = 0; el < nb_element; ++el) { matrix_matrixt(m, n, k, A_val, B_val, C_val, alpha); A_val += offset_A; B_val += offset_B; C_val += offset_C; } AKANTU_DEBUG_OUT(); } +/* -------------------------------------------------------------------------- */ +void Math::compute_tangents(const Array & normals, Array & tangents) { + AKANTU_DEBUG_IN(); + + UInt spatial_dimension = normals.getNbComponent(); + UInt tangent_components = spatial_dimension * (spatial_dimension - 1); + + AKANTU_DEBUG_ASSERT(tangent_components == tangents.getNbComponent(), + "Cannot compute the tangents, the storage array for tangents" + << " does not have the good amount of components."); + + UInt nb_normals = normals.getSize(); + tangents.resize(nb_normals); + + Real * normal_it = normals .storage(); + Real * tangent_it = tangents.storage(); + + /// compute first tangent + for (UInt q = 0; q < nb_normals; ++q) { + /// if normal is orthogonal to xy plane, arbitrarly define tangent + if ( Math::are_float_equal(Math::norm2(normal_it), 0) ) + tangent_it[0] = 1; + else + Math::normal2(normal_it, tangent_it); + + normal_it += spatial_dimension; + tangent_it += tangent_components; + } + + /// compute second tangent (3D case) + if (spatial_dimension == 3) { + normal_it = normals .storage(); + tangent_it = tangents.storage(); + + for (UInt q = 0; q < nb_normals; ++q) { + Math::normal3(normal_it, tangent_it, tangent_it + spatial_dimension); + normal_it += spatial_dimension; + tangent_it += tangent_components; + } + } + + AKANTU_DEBUG_OUT(); +} + __END_AKANTU__ diff --git a/src/common/aka_math.hh b/src/common/aka_math.hh index 806f2ec80..2b73f641a 100644 --- a/src/common/aka_math.hh +++ b/src/common/aka_math.hh @@ -1,303 +1,301 @@ /** * @file aka_math.hh * * @author Guillaume Anciaux * @author Leonardo Snozzi * @author Marion Estelle Chambart * @author David Simon Kammer * @author Peter Spijker * @author Ramin Aghababaei * @author Nicolas Richart * @author Marco Vocialta * @author Daniel Pino Muñoz * * @date creation: Wed Aug 04 2010 * @date last modification: Tue Sep 16 2014 * * @brief mathematical operations * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_MATH_H__ #define __AKANTU_AKA_MATH_H__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template class Array; class Math { - /* ------------------------------------------------------------------------ */ - /* Constructors/Destructors */ - /* ------------------------------------------------------------------------ */ -public: - /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Matrix algebra */ /* ------------------------------------------------------------------------ */ /// @f$ y = A*x @f$ static void matrix_vector(UInt m, UInt n, const Array & A, const Array & x, Array & y, Real alpha = 1.); /// @f$ y = A*x @f$ static inline void matrix_vector(UInt m, UInt n, Real * A, Real * x, Real * y, Real alpha = 1.); /// @f$ y = A^t*x @f$ static inline void matrixt_vector(UInt m, UInt n, Real * A, Real * x, Real * y, Real alpha = 1.); /// @f$ C = A*B @f$ static void matrix_matrix(UInt m, UInt n, UInt k, const Array & A, const Array & B, Array & C, Real alpha = 1.); /// @f$ C = A*B^t @f$ static void matrix_matrixt(UInt m, UInt n, UInt k, const Array & A, const Array & B, Array & C, Real alpha = 1.); /// @f$ C = A*B @f$ static inline void matrix_matrix(UInt m, UInt n, UInt k, Real * A, Real * B, Real * C, Real alpha = 1.); /// @f$ C = A^t*B @f$ static inline void matrixt_matrix(UInt m, UInt n, UInt k, Real * A, Real * B, Real * C, Real alpha = 1.); /// @f$ C = A*B^t @f$ static inline void matrix_matrixt(UInt m, UInt n, UInt k, Real * A, Real * B, Real * C, Real alpha = 1.); /// @f$ C = A^t*B^t @f$ static inline void matrixt_matrixt(UInt m, UInt n, UInt k, Real * A, Real * B, Real * C, Real alpha = 1.); template static inline void matMul(UInt m, UInt n, UInt k, Real alpha, Real * A, Real * B, Real beta, Real * C); template static inline void matVectMul(UInt m, UInt n, Real alpha, Real * A, Real * x, Real beta, Real * y); static inline void matrix33_eigenvalues(Real * A, Real * Adiag); static inline void matrix22_eigenvalues(Real * A, Real * Adiag); template static inline void eigenvalues(Real * A, Real * d); /// solve @f$ A x = \Lambda x @f$ and return d and V such as @f$ A V[i:] = d[i] V[i:]@f$ template static void matrixEig(UInt n, T * A, T * d, T * V = NULL); /// determinent of a 2x2 matrix static inline Real det2(const Real * mat); /// determinent of a 3x3 matrix static inline Real det3(const Real * mat); /// determinent of a nxn matrix template static inline Real det(const Real * mat); /// determinent of a nxn matrix template static inline T det(UInt n, const T * mat); /// inverse a nxn matrix template static inline void inv(const Real * mat, Real * inv); /// inverse a nxn matrix template static inline void inv(UInt n, const T * mat, T * inv); /// inverse a 3x3 matrix static inline void inv3(const Real * mat, Real * inv); /// inverse a 2x2 matrix static inline void inv2(const Real * mat, Real * inv); /// solve A x = b using a LU factorization template static inline void solve(UInt n, const T * A, T * x, const T * b); /// return the double dot product between 2 tensors in 2d static inline Real matrixDoubleDot22(Real * A, Real * B); /// return the double dot product between 2 tensors in 3d static inline Real matrixDoubleDot33(Real * A, Real * B); /// extension of the double dot product to two 2nd order tensor in dimension n static inline Real matrixDoubleDot(UInt n, Real * A, Real * B); /* ------------------------------------------------------------------------ */ /* Array algebra */ /* ------------------------------------------------------------------------ */ /// vector cross product static inline void vectorProduct3(const Real * v1, const Real * v2, Real * res); - /// compute normal a normal to a vector - static inline void normal2(const Real * v1, Real * res); - - /// compute normal a normal to a vector - static inline void normal3(const Real * v1,const Real * v2, Real * res); - /// normalize a vector static inline void normalize2(Real * v); /// normalize a vector static inline void normalize3(Real * v); /// return norm of a 2-vector static inline Real norm2(const Real * v); /// return norm of a 3-vector static inline Real norm3(const Real * v); /// return norm of a vector static inline Real norm(UInt n, const Real * v); /// return the dot product between 2 vectors in 2d static inline Real vectorDot2(const Real * v1, const Real * v2); /// return the dot product between 2 vectors in 3d static inline Real vectorDot3(const Real * v1, const Real * v2); /// return the dot product between 2 vectors static inline Real vectorDot(Real * v1, Real * v2, UInt n); /* ------------------------------------------------------------------------ */ /* Geometry */ /* ------------------------------------------------------------------------ */ + /// compute normal a normal to a vector + static inline void normal2(const Real * v1, Real * res); + + /// compute normal a normal to a vector + static inline void normal3(const Real * v1,const Real * v2, Real * res); + + /// compute the tangents to an array of normal vectors + static void compute_tangents(const Array & normals, Array & tangents); + /// distance in 2D between x and y static inline Real distance_2d(const Real * x, const Real * y); /// distance in 3D between x and y static inline Real distance_3d(const Real * x, const Real * y); /// radius of the in-circle of a triangle static inline Real triangle_inradius(const Real * coord1, const Real * coord2, const Real * coord3); /// radius of the in-circle of a tetrahedron static inline Real tetrahedron_inradius(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4); /// volume of a tetrahedron static inline Real tetrahedron_volume(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4); /// compute the barycenter of n points static inline void barycenter(const Real * coord, UInt nb_points, UInt spatial_dimension, Real * barycenter); /// vector between x and y static inline void vector_2d(const Real * x, const Real * y, Real * vec); /// vector pointing from x to y in 3 spatial dimension static inline void vector_3d(const Real * x, const Real * y, Real * vec); /// test if two scalar are equal within a given tolerance static inline bool are_float_equal(Real x, Real y); /// test if two vectors are equal within a given tolerance static inline bool are_vector_equal(UInt n, Real * x, Real * y); #ifdef isnan # error "You probably included which is incompatible with aka_math please use\ or add a \"#undef isnan\" before akantu includes" #endif /// test if a real is a NaN static inline bool isnan(Real x); /// test if the line x and y intersects each other static inline bool intersects(Real x_min, Real x_max, Real y_min, Real y_max); /// test if a is in the range [x_min, x_max] static inline bool is_in_range(Real a, Real x_min, Real x_max); static inline Real getTolerance() { return tolerance; }; static inline void setTolerance(Real tol) { tolerance = tol; }; template static inline T pow(T x); class NewtonRaphson { public: NewtonRaphson(Real tolerance, Real max_iteration) : tolerance(tolerance), max_iteration(max_iteration) { } template Real solve(const Functor & funct, Real x_0); private: Real tolerance; Real max_iteration; }; struct NewtonRaphsonFunctor { NewtonRaphsonFunctor(const std::string & name) : name(name) {} virtual Real f(Real x) const = 0; virtual Real f_prime(Real x) const = 0; std::string name; }; private: /// tolerance for functions that need one static Real tolerance; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "aka_math_tmpl.hh" __END_AKANTU__ #endif /* __AKANTU_AKA_MATH_H__ */ diff --git a/src/common/aka_types.hh b/src/common/aka_types.hh index d92deb104..0bc0ed8e9 100644 --- a/src/common/aka_types.hh +++ b/src/common/aka_types.hh @@ -1,1012 +1,1076 @@ /** * @file aka_types.hh * * @author Nicolas Richart * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_error.hh" #include "aka_fwd.hh" #include "aka_math.hh" #include "aka_array.hh" /* -------------------------------------------------------------------------- */ #include #ifndef __INTEL_COMPILER #include #else #include #endif /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_TYPES_HH__ #define __AKANTU_AKA_TYPES_HH__ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* maps */ /* -------------------------------------------------------------------------- */ #ifndef __INTEL_COMPILER template struct unordered_map { typedef typename std::tr1::unordered_map type; }; #else template struct unordered_map { typedef typename std::map type; }; #endif 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 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 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::iterator they can return a + * TensorProxy that will be automatically transformed as a TensorStorage wrapped + * on the same data + */ template class TensorProxy { protected: TensorProxy(T * data, UInt m, UInt n, UInt p) { DimHelper::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 & 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; } - void copyExternalMemory(T * data, UInt nb_values) { - AKANTU_DEBUG_ASSERT(nb_values == this->size(), - "You are trying to copy two tensors with differents sizes"); - memcpy(this->values, data, nb_values * sizeof(T)); + 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 class VectorProxy : public TensorProxy > { typedef TensorProxy > parent; + typedef Vector type; public: - VectorProxy(T * data = NULL, UInt n = 0) : parent(data, n, 0, 0) { } + VectorProxy(T * data, UInt n) : parent(data, n, 0, 0) { } VectorProxy(const VectorProxy & src) : parent(src) { } VectorProxy(const Vector & src) : parent(src) { } - - VectorProxy & operator=(const Vector & src) { - this->copyExternalMemory(src.storage(), src.size()); + 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 class MatrixProxy : public TensorProxy > { typedef TensorProxy > parent; + typedef Matrix type; public: - MatrixProxy(T * data = NULL, UInt m = 0, UInt n = 0) : parent(data, m, n, 0) { } + MatrixProxy(T * data, UInt m, UInt n) : parent(data, m, n, 0) { } MatrixProxy(const MatrixProxy & src) : parent(src) { } - MatrixProxy(const Matrix & src) : parent(src) { } - - MatrixProxy & operator=(const Matrix & src) { - this->copyExternalMemory(src.storage(), src.size()); + 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 class Tensor3Proxy : public TensorProxy > { typedef TensorProxy > parent; + typedef Tensor3 type; public: - Tensor3Proxy(T * data = NULL, UInt m = 0, UInt n = 0, UInt k = 0) : + Tensor3Proxy(T * data, UInt m, UInt n, UInt k) : parent(data, m, n, k) { } Tensor3Proxy(const Tensor3Proxy & src) : parent(src) { } Tensor3Proxy(const Tensor3 & src) : parent(src) { } - - Tensor3Proxy & operator=(const Tensor3 & src) { - this->copyExternalMemory(src.storage(), src.size()); + Tensor3Proxy & operator=(const type & src) { + parent::operator=(src); + return *this; + } + Tensor3Proxy & operator=(const Tensor3Proxy & src) { + parent::operator=(src); return *this; } }; /* -------------------------------------------------------------------------- */ /* Tensor base class */ /* -------------------------------------------------------------------------- */ template class TensorStorage { public: typedef T value_type; protected: template 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 & 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::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::setDims(m, n, p, this->n); this->computeSize(); this->values = data; this->wrapped = true; } public: /* ------------------------------------------------------------------------ */ template inline void shallowCopy(const TensorType & src) { this->copySize(src); if(!this->wrapped) delete[] this->values; this->values = src.storage(); this->wrapped = true; } /* ------------------------------------------------------------------------ */ template 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) { - AKANTU_DEBUG_ASSERT(this->_size == src.size(), "vectors of different size"); + // 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 inline RetType & operator+=(const TensorStorage & 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(this)); } /* ------------------------------------------------------------------------ */ template inline RetType & operator-=(const TensorStorage & 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(this)); } /* ------------------------------------------------------------------------ */ inline RetType & operator+=(const T & x) { T * a = this->values; for (UInt i = 0; i < _size; ++i) *(a++) += x; return *(static_cast(this)); } /* ------------------------------------------------------------------------ */ inline RetType & operator-=(const T & x) { T * a = this->values; for (UInt i = 0; i < _size; ++i) *(a++) -= x; return *(static_cast(this)); } /* ------------------------------------------------------------------------ */ inline RetType & operator*=(const T & x) { T * a = this->storage(); for (UInt i = 0; i < _size; ++i) *(a++) *= x; return *(static_cast(this)); } /* ---------------------------------------------------------------------- */ inline RetType & operator/=(const T & x) { T * a = this->values; for (UInt i = 0; i < _size; ++i) *(a++) /= x; return *(static_cast(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 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; inline void computeSize() { _size = 1; for (UInt d = 0; d < ndim; ++d) _size *= this->n[d]; } protected: template struct NormHelper { template 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 struct NormHelper { template 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 struct NormHelper { template 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 struct NormHelper { template 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 @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 inline T norm() const { return NormHelper::norm(*this); } protected: UInt n[ndim]; UInt _size; T * values; bool wrapped; }; template inline TensorProxy::TensorProxy(const TensorStorage & other) { this->values = other.storage(); for (UInt i = 0; i < ndim; ++i) this->n[i] = other.size(i); } /* -------------------------------------------------------------------------- */ /* Vector */ /* -------------------------------------------------------------------------- */ template class Vector : public TensorStorage< T, 1, Vector > { typedef TensorStorage< T, 1, Vector > parent; public: typedef typename parent::value_type value_type; typedef VectorProxy 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 & 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 & operator*=(Real x) { return parent::operator*=(x); } inline Vector & operator/=(Real x) { return parent::operator/=(x); } + /* ------------------------------------------------------------------------ */ inline Vector & operator*=(const Vector & 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 & 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 & v1, const Vector & 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 & A, const Vector & b) { AKANTU_DEBUG_ASSERT(this->size() == A.rows() && this->_size = A.cols(), - "The solution vector as a mismatch in size with the matrix"); - AKANTU_DEBUG_ASSERT(this->_size == b._size, "The rhs vector as a mismatch in size with the matrix"); + "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 inline void mul(const Matrix & A, const Vector & x, Real alpha = 1.0); /* ------------------------------------------------------------------------ */ inline Real norm() const { return parent::template norm(); } template inline Real norm() const { return parent::template norm(); } /* ------------------------------------------------------------------------ */ inline void normalize() { Real n = norm(); operator/=(n); } /* ------------------------------------------------------------------------ */ /// norm of (*this - x) inline Real distance(const Vector & 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 & 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 & 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 (((*a - *b) > tolerance) ? 1 : -1); } return 0; } /* ------------------------------------------------------------------------ */ inline bool operator==(const Vector & v) const { return equal(v); } inline bool operator<(const Vector & v) const { return compare(v) == -1; } inline bool operator>(const Vector & 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 << space << "Vector<" << debug::demangle(typeid(T).name()) << ">(" << this->_size <<") : ["; + stream << "["; for (UInt i = 0; i < this->_size; ++i) { if(i != 0) stream << ", "; stream << this->values[i]; } stream << "]"; } friend class ::akantu::Array; }; typedef Vector RVector; -/* -------------------------------------------------------------------------- */ -// support operations for the creation of other vectors -template Vector operator*(T scalar, const Vector & a); -template Vector operator+(const Vector & a, const Vector & b); -template Vector operator-(const Vector & a, const Vector & b); - -/* -------------------------------------------------------------------------- */ -template -Vector operator*(T scalar, const Vector & a) { - Vector r(a.size()); - r = a; - r *= scalar; - return r; -} - -template -Vector operator+(const Vector & a, const Vector & b) { - Vector r(a.size()); - r = a; - r += b; - return r; -} - -template -Vector operator-(const Vector& a, const Vector& b) { - Vector r(a.size()); - r = a; - r -= b; - return r; -} - -template -Matrix operator*(T scalar, const Matrix& a) { - Matrix r(a.rows(), a.cols()); - r = a; - r *= scalar; - return r; -} - -template -Matrix operator+(const Matrix& a, const Matrix& b) { - Matrix r(a.rows(), a.cols()); - r = a; - r += b; - return r; -} - -template -Matrix operator-(const Matrix& a, const Matrix& b) { - Matrix r(a.rows(), a.cols()); - r = a; - r -= b; - return r; -} - /* ------------------------------------------------------------------------ */ template<> inline bool Vector::equal(const Vector & 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 class Matrix : public TensorStorage< T, 2, Matrix > { typedef TensorStorage< T, 2, Matrix > parent; public: typedef typename parent::value_type value_type; typedef MatrixProxy 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 & 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& operator()(UInt i, UInt j) { - return this->at(i,j); - } - inline T& at(UInt i, UInt j) { return *(this->values + i + j*this->n[0]); } - - inline const T& operator()(UInt i, UInt j) const { - return this->at(i,j); - } - inline T& at(UInt i, UInt j) const { + 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 operator()(UInt j) { return VectorProxy(this->values + j*this->n[0], this->n[0]); } inline const VectorProxy operator()(UInt j) const { return VectorProxy(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(*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(C, B); return *this; } /* ---------------------------------------------------------------------- */ template 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(this->rows(), this->cols(), k, alpha, A.storage(), B.storage(), 0., this->storage()); } /* ---------------------------------------------------------------------- */ inline void outerProduct(const Vector & A, const Vector & 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 & eigs) : eigs(eigs) { } bool operator()(const UInt & a, const UInt & b) const { return (eigs(a) > eigs(b)); } private: const Vector & eigs; }; public: /* ---------------------------------------------------------------------- */ inline void eig(Vector & eigenvalues, Matrix & 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 tmp = *this; Vector tmp_eigs(eigenvalues.size()); Matrix 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 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 & eigenvalues) const { Matrix 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"); + 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 eye(UInt m, T alpha = 1.) { Matrix 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"); + 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 & 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."); + << " 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 << space << "Matrix<" << debug::demangle(typeid(T).name()) - << ">(" << this->n[0] << "," << this->n[1] <<") :" << "["; + 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 template inline void Vector::mul(const Matrix & A, const Vector & 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(A.rows(), A.cols(), alpha, A.storage(), x.storage(), 0., this->storage()); } /* -------------------------------------------------------------------------- */ template inline std::ostream & operator<<(std::ostream & stream, const Matrix & _this) { _this.printself(stream); return stream; } /* -------------------------------------------------------------------------- */ template inline std::ostream & operator<<(std::ostream & stream, const Vector & _this) { _this.printself(stream); return stream; } /* ------------------------------------------------------------------------ */ /* Tensor3 */ /* ------------------------------------------------------------------------ */ template class Tensor3 : public TensorStorage< T, 3, Tensor3 > { typedef TensorStorage< T, 3, Tensor3 > parent; public: typedef typename parent::value_type value_type; typedef Tensor3Proxy 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 operator()(UInt k) { return MatrixProxy(this->values + k*this->n[0]*this->n[1], this->n[0], this->n[1]); } inline const MatrixProxy operator()(UInt k) const { return MatrixProxy(this->values + k*this->n[0]*this->n[1], this->n[0], this->n[1]); } inline MatrixProxy operator[](UInt k) { return Matrix(this->values + k*this->n[0]*this->n[1], this->n[0], this->n[1]); } inline const MatrixProxy operator[](UInt k) const { return MatrixProxy(this->values + k*this->n[0]*this->n[1], this->n[0], this->n[1]); } }; + +/* -------------------------------------------------------------------------- */ +// support operations for the creation of other vectors +/* -------------------------------------------------------------------------- */ +template +Vector operator*(const T & scalar, const Vector & a) { + Vector r(a); + r *= scalar; + return r; +} + +template +Vector operator*(const Vector & a, const T & scalar) { + Vector r(a); + r *= scalar; + return r; +} + +template +Vector operator/(const Vector & a, const T & scalar) { + Vector r(a); + r /= scalar; + return r; +} + +template +Vector operator+(const Vector & a, const Vector & b) { + Vector r(a); + r += b; + return r; +} + +template +Vector operator-(const Vector& a, const Vector& b) { + Vector r(a); + r -= b; + return r; +} + +/* -------------------------------------------------------------------------- */ +template +Matrix operator*(const T & scalar, const Matrix& a) { + Matrix r(a); + r *= scalar; + return r; +} + +template +Matrix operator*(const Matrix& a, const T & scalar) { + Matrix r(a); + r *= scalar; + return r; +} + +template +Matrix operator/(const Matrix& a, const T & scalar) { + Matrix r(a); + r /= scalar; + return r; +} + +template +Matrix operator+(const Matrix& a, const Matrix& b) { + Matrix r(a); + r += b; + return r; +} + +template +Matrix operator-(const Matrix& a, const Matrix& b) { + Matrix r(a); + r -= b; + return r; +} + + + __END_AKANTU__ #endif /* __AKANTU_AKA_TYPES_HH__ */ diff --git a/src/fe_engine/integrator_gauss_inline_impl.cc b/src/fe_engine/integrator_gauss_inline_impl.cc index e92b003fd..9a181de82 100644 --- a/src/fe_engine/integrator_gauss_inline_impl.cc +++ b/src/fe_engine/integrator_gauss_inline_impl.cc @@ -1,483 +1,481 @@ /** * @file integrator_gauss_inline_impl.cc * * @author Guillaume Anciaux * @author Nicolas Richart * * @date creation: Tue Feb 15 2011 * @date last modification: Mon Jun 23 2014 * * @brief inline function of gauss integrator * * @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 . * */ __END_AKANTU__ #include "fe_engine.hh" #if defined(AKANTU_DEBUG_TOOLS) # include "aka_debug_tools.hh" #endif __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template inline void IntegratorGauss::initIntegrator(const Array & nodes, const ElementType & type, const GhostType & ghost_type) { #define INIT_INTEGRATOR(type) \ computeQuadraturePoints(ghost_type); \ precomputeJacobiansOnQuadraturePoints(nodes, ghost_type); \ checkJacobians(ghost_type); \ multiplyJacobiansByWeights(ghost_type); AKANTU_BOOST_ALL_ELEMENT_SWITCH(INIT_INTEGRATOR); #undef INIT_INTEGRATOR } /* -------------------------------------------------------------------------- */ template template inline void IntegratorGauss::integrateOnElement(const Array & f, Real * intf, UInt nb_degree_of_freedom, const UInt elem, const GhostType & ghost_type) const { Array & jac_loc = jacobians(type, ghost_type); UInt nb_quadrature_points = ElementClass::getNbQuadraturePoints(); AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degree_of_freedom , "The vector f do not have the good number of component."); Real * f_val = f.storage() + elem * f.getNbComponent(); Real * jac_val = jac_loc.storage() + elem * nb_quadrature_points; integrate(f_val, jac_val, intf, nb_degree_of_freedom, nb_quadrature_points); } /* -------------------------------------------------------------------------- */ template template inline Real IntegratorGauss::integrate(const Vector & in_f, UInt index, const GhostType & ghost_type) const { const Array & jac_loc = jacobians(type, ghost_type); UInt nb_quadrature_points = GaussIntegrationElement::getNbQuadraturePoints(); AKANTU_DEBUG_ASSERT(in_f.size() == nb_quadrature_points , "The vector f do not have nb_quadrature_points entries."); Real * jac_val = jac_loc.storage() + index * nb_quadrature_points; Real intf; integrate(in_f.storage(), jac_val, &intf, 1, nb_quadrature_points); return intf; } /* -------------------------------------------------------------------------- */ template inline void IntegratorGauss::integrate(Real *f, Real *jac, Real * inte, UInt nb_degree_of_freedom, UInt nb_quadrature_points) const { memset(inte, 0, nb_degree_of_freedom * sizeof(Real)); Real *cjac = jac; for (UInt q = 0; q < nb_quadrature_points; ++q) { for (UInt dof = 0; dof < nb_degree_of_freedom; ++dof) { inte[dof] += *f * *cjac; ++f; } ++cjac; } } /* -------------------------------------------------------------------------- */ template template inline const Matrix & IntegratorGauss::getQuadraturePoints(const GhostType & ghost_type) const { AKANTU_DEBUG_ASSERT(quadrature_points.exists(type, ghost_type), "Quadrature points for type " << quadrature_points.printType(type, ghost_type) << " have not been initialized." << " Did you use 'computeQuadraturePoints' function ?"); return quadrature_points(type, ghost_type); } /* -------------------------------------------------------------------------- */ template template inline void IntegratorGauss::computeQuadraturePoints(const GhostType & ghost_type) { Matrix & quads = quadrature_points(type, ghost_type); quads = GaussIntegrationElement::getQuadraturePoints(); } /* -------------------------------------------------------------------------- */ template template inline void IntegratorGauss:: computeJacobianOnQuadPointsByElement(const Matrix & node_coords, Vector & jacobians) { Matrix quad = GaussIntegrationElement::getQuadraturePoints(); // jacobian ElementClass::computeJacobian(quad, node_coords, jacobians); } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template IntegratorGauss::IntegratorGauss(const Mesh & mesh, const ID & id, const MemoryID & memory_id) : Integrator(mesh, id, memory_id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template template void IntegratorGauss::checkJacobians(const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = GaussIntegrationElement::getNbQuadraturePoints(); UInt nb_element; nb_element = mesh.getConnectivity(type,ghost_type).getSize(); Real * jacobians_val = jacobians(type, ghost_type).storage(); for (UInt i = 0; i < nb_element*nb_quadrature_points; ++i,++jacobians_val){ if(*jacobians_val < 0) AKANTU_DEBUG_ERROR("Negative jacobian computed," << " possible problem in the element node ordering (Quadrature Point " << i % nb_quadrature_points << ":" << i / nb_quadrature_points << ":" << type << ":" << ghost_type << ")"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template template void IntegratorGauss::precomputeJacobiansOnQuadraturePoints(const Array & nodes, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = GaussIntegrationElement::getNbQuadraturePoints(); UInt nb_element = mesh.getNbElement(type,ghost_type); Array * jacobians_tmp; if(!jacobians.exists(type, ghost_type)) jacobians_tmp = &jacobians.alloc(nb_element*nb_quadrature_points, 1, type, ghost_type); else { jacobians_tmp = &jacobians(type, ghost_type); jacobians_tmp->resize(nb_element*nb_quadrature_points); } Array::vector_iterator jacobians_it = jacobians_tmp->begin_reinterpret(nb_quadrature_points, nb_element); Array x_el(0, spatial_dimension * nb_nodes_per_element); FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type); Array::const_matrix_iterator x_it = x_el.begin(spatial_dimension, nb_nodes_per_element); // Matrix local_coord(spatial_dimension, nb_nodes_per_element); for (UInt elem = 0; elem < nb_element; ++elem, ++jacobians_it, ++x_it) { const Matrix & x = *x_it; Vector & J = *jacobians_it; computeJacobianOnQuadPointsByElement(x, J); } // >>>>>> DEBUG CODE >>>>>> // #if defined(AKANTU_DEBUG_TOOLS) #if defined(AKANTU_CORE_CXX11) debug::element_manager.print(debug::_dm_integrator, [ghost_type, this, nb_element, nb_quadrature_points](const Element & el)->std::string { std::stringstream out; if(el.ghost_type == ghost_type) { Array::vector_iterator jacobians_it = jacobians(el.type, el.ghost_type).begin(nb_quadrature_points); out << " jacobian: " << jacobians_it[el.element]; } return out.str(); }); #endif #endif // <<<<<< DEBUG CODE <<<<<< // AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template template void IntegratorGauss::multiplyJacobiansByWeights(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = GaussIntegrationElement::getNbQuadraturePoints(); UInt nb_element = this->mesh.getNbElement(type, ghost_type); Vector weights = GaussIntegrationElement::getWeights(); Array::vector_iterator jacobians_it = this->jacobians(type, ghost_type).begin_reinterpret(nb_quadrature_points, nb_element); Array::vector_iterator jacobians_end = this->jacobians(type, ghost_type).end_reinterpret(nb_quadrature_points, nb_element); for (; jacobians_it != jacobians_end; ++jacobians_it) { Vector & J = *jacobians_it; J *= weights; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ #if defined(AKANTU_COHESIVE_ELEMENT) template <> template void IntegratorGauss<_ek_cohesive>::precomputeJacobiansOnQuadraturePoints(const Array & nodes, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = GaussIntegrationElement::getNbQuadraturePoints(); UInt nb_element = mesh.getNbElement(type,ghost_type); Array * jacobians_tmp; if(!jacobians.exists(type, ghost_type)) jacobians_tmp = &jacobians.alloc(nb_element*nb_quadrature_points, 1, type, ghost_type); else { jacobians_tmp = &jacobians(type, ghost_type); jacobians_tmp->resize(nb_element*nb_quadrature_points); } Array::vector_iterator jacobians_it = jacobians_tmp->begin_reinterpret(nb_quadrature_points, nb_element); Vector weights = GaussIntegrationElement::getWeights(); Array x_el(0, spatial_dimension * nb_nodes_per_element); FEEngine::extractNodalToElementField(mesh, nodes, x_el, type, ghost_type); Array::const_matrix_iterator x_it = x_el.begin(spatial_dimension, nb_nodes_per_element); UInt nb_nodes_per_subelement = nb_nodes_per_element / 2; Matrix x(spatial_dimension, nb_nodes_per_subelement); // Matrix local_coord(spatial_dimension, nb_nodes_per_element); for (UInt elem = 0; elem < nb_element; ++elem, ++jacobians_it, ++x_it) { for (UInt s = 0; s < spatial_dimension; ++s) for (UInt n = 0; n < nb_nodes_per_subelement; ++n) x(s, n) = ((*x_it)(s, n) + (*x_it)(s, n + nb_nodes_per_subelement))*.5; Vector & J = *jacobians_it; if (type == _cohesive_1d_2) J(0) = 1; else computeJacobianOnQuadPointsByElement(x, J); - - J *= weights; } AKANTU_DEBUG_OUT(); } #endif /* -------------------------------------------------------------------------- */ template template void IntegratorGauss::integrate(const Array & in_f, Array &intf, UInt nb_degree_of_freedom, const GhostType & ghost_type, const Array & filter_elements) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type), "No jacobians for the type " << jacobians.printType(type, ghost_type)); UInt nb_points = GaussIntegrationElement::getNbQuadraturePoints(); const Array & jac_loc = jacobians(type, ghost_type); Array::const_matrix_iterator J_it; Array::matrix_iterator inte_it; Array::const_matrix_iterator f_it; UInt nb_element; Array * filtered_J = NULL; if(filter_elements != empty_filter) { nb_element = filter_elements.getSize(); filtered_J = new Array(0, jac_loc.getNbComponent()); FEEngine::filterElementalData(mesh, jac_loc, *filtered_J, type, ghost_type, filter_elements); const Array & cfiltered_J = *filtered_J; // \todo temporary patch J_it = cfiltered_J.begin_reinterpret(nb_points, 1, nb_element); } else { nb_element = mesh.getNbElement(type,ghost_type); J_it = jac_loc.begin_reinterpret(nb_points, 1, nb_element); } intf.resize(nb_element); f_it = in_f.begin_reinterpret(nb_degree_of_freedom, nb_points, nb_element); inte_it = intf.begin_reinterpret(nb_degree_of_freedom, 1, nb_element); for (UInt el = 0; el < nb_element; ++el, ++J_it, ++f_it, ++inte_it) { const Matrix & f = *f_it; const Matrix & J = *J_it; Matrix & inte_f = *inte_it; inte_f.mul(f, J); } delete filtered_J; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template template Real IntegratorGauss::integrate(const Array & in_f, const GhostType & ghost_type, const Array & filter_elements) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type), "No jacobians for the type " << jacobians.printType(type, ghost_type)); Array intfv(0, 1); integrate(in_f, intfv, 1, ghost_type, filter_elements); UInt nb_values = intfv.getSize(); if(nb_values == 0) return 0.; UInt nb_values_to_sum = nb_values >> 1; std::sort(intfv.begin(), intfv.end()); // as long as the half is not empty while(nb_values_to_sum) { UInt remaining = (nb_values - 2*nb_values_to_sum); if(remaining) intfv(nb_values - 2) += intfv(nb_values - 1); // sum to consecutive values and store the sum in the first half for (UInt i = 0; i < nb_values_to_sum; ++i) { intfv(i) = intfv(2*i) + intfv(2*i + 1); } nb_values = nb_values_to_sum; nb_values_to_sum >>= 1; } AKANTU_DEBUG_OUT(); return intfv(0); } /* -------------------------------------------------------------------------- */ template template void IntegratorGauss::integrateOnQuadraturePoints(const Array & in_f, Array &intf, UInt nb_degree_of_freedom, const GhostType & ghost_type, const Array & filter_elements) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(jacobians.exists(type, ghost_type), "No jacobians for the type " << jacobians.printType(type, ghost_type)); UInt nb_element; UInt nb_points = GaussIntegrationElement::getNbQuadraturePoints(); const Array & jac_loc = jacobians(type, ghost_type); Array::const_scalar_iterator J_it; Array::vector_iterator inte_it; Array::const_vector_iterator f_it; Array * filtered_J = NULL; if(filter_elements != empty_filter) { nb_element = filter_elements.getSize(); filtered_J = new Array(0, jac_loc.getNbComponent()); FEEngine::filterElementalData(mesh, jac_loc, *filtered_J, type, ghost_type, filter_elements); J_it = filtered_J->begin(); } else { nb_element = mesh.getNbElement(type,ghost_type); J_it = jac_loc.begin(); } intf.resize(nb_element*nb_points); f_it = in_f.begin(nb_degree_of_freedom); inte_it = intf.begin(nb_degree_of_freedom); for (UInt el = 0; el < nb_element; ++el, ++J_it, ++f_it, ++inte_it) { const Real & J = *J_it; const Vector & f = *f_it; Vector & inte_f = *inte_it; inte_f = f; inte_f *= J; } delete filtered_J; AKANTU_DEBUG_OUT(); } diff --git a/src/geometry/mesh_segment_intersector_tmpl.hh b/src/geometry/mesh_segment_intersector_tmpl.hh index b8d23a597..5fe3b49ff 100644 --- a/src/geometry/mesh_segment_intersector_tmpl.hh +++ b/src/geometry/mesh_segment_intersector_tmpl.hh @@ -1,270 +1,272 @@ /** * @file mesh_segment_intersector_tmpl.hh * * @author Lucas Frerot * * @date creation: Wed Apr 29 2015 * @date last modification: Wed Apr 29 2015 * * @brief Computation of mesh intersection with segments * * @section LICENSE * * Copyright (©) 2010-2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_SEGMENT_INTERSECTOR_TMPL_HH__ #define __AKANTU_MESH_SEGMENT_INTERSECTOR_TMPL_HH__ #include "aka_common.hh" #include "mesh_geom_common.hh" #include "tree_type_helper.hh" __BEGIN_AKANTU__ template MeshSegmentIntersector::MeshSegmentIntersector(const Mesh & mesh, Mesh & result_mesh): parent_type(mesh), result_mesh(result_mesh), current_physical_name() { this->constructData(); } template MeshSegmentIntersector::~MeshSegmentIntersector() {} template void MeshSegmentIntersector::computeIntersectionQuery(const K::Segment_3 & query) { AKANTU_DEBUG_IN(); result_mesh.addConnectivityType(_segment_2, _not_ghost); result_mesh.addConnectivityType(_segment_2, _ghost); std::list result_list; std::set, segmentPairsLess> segment_set; this->factory.getTree().all_intersections(query, std::back_inserter(result_list)); this->computeSegments(result_list, segment_set, query); // Arrays for storing nodes and connectivity Array & nodes = result_mesh.getNodes(); Array & connectivity = result_mesh.getConnectivity(_segment_2); // Arrays for storing associated element and physical name bool valid_elemental_data = true; Array * associated_element = NULL; Array * associated_physical_name = NULL; try { associated_element = &result_mesh.getData("associated_element", _segment_2); associated_physical_name = &result_mesh.getData("physical_names", _segment_2); } catch (debug::Exception & e) { valid_elemental_data = false; } std::set::iterator it = segment_set.begin(), end = segment_set.end(); // Loop over the segment pairs for (; it != end ; ++it) { - Vector segment_connectivity(2); - segment_connectivity(0) = result_mesh.getNbNodes(); - segment_connectivity(1) = result_mesh.getNbNodes() + 1; - connectivity.push_back(segment_connectivity); - - // Copy nodes - Vector source(dim), target(dim); - for (UInt j = 0 ; j < dim ; j++) { - source(j) = it->first.source()[j]; - target(j) = it->first.target()[j]; - } + if (!it->first.is_degenerate()) { + Vector segment_connectivity(2); + segment_connectivity(0) = result_mesh.getNbNodes(); + segment_connectivity(1) = result_mesh.getNbNodes() + 1; + connectivity.push_back(segment_connectivity); + + // Copy nodes + Vector source(dim), target(dim); + for (UInt j = 0 ; j < dim ; j++) { + source(j) = it->first.source()[j]; + target(j) = it->first.target()[j]; + } - nodes.push_back(source); - nodes.push_back(target); + nodes.push_back(source); + nodes.push_back(target); - // Copy associated element info - if (valid_elemental_data) { - associated_element->push_back(Element(type, it->second)); - associated_physical_name->push_back(current_physical_name); + // Copy associated element info + if (valid_elemental_data) { + associated_element->push_back(Element(type, it->second)); + associated_physical_name->push_back(current_physical_name); + } } } AKANTU_DEBUG_OUT(); } template void MeshSegmentIntersector::computeIntersectionQueryList(const std::list & query_list, const std::string & physical_name) { AKANTU_DEBUG_IN(); current_physical_name = physical_name; parent_type::computeIntersectionQueryList(query_list); AKANTU_DEBUG_OUT(); } template void MeshSegmentIntersector::computeIntersectionQueryList(const std::list & query_list) { AKANTU_DEBUG_IN(); parent_type::computeIntersectionQueryList(query_list); AKANTU_DEBUG_OUT(); } template void MeshSegmentIntersector::computeSegments(const std::list & intersections, std::set & segments, const K::Segment_3 & query) { AKANTU_DEBUG_IN(); /* * Number of intersections = 0 means * * - query is completely outside mesh * - query is completely inside primitive * * We try to determine the case and still construct the segment list */ if (intersections.size() == 0) { // We look at all the primitives intersected by two rays // If there is one primitive in common, then query is inside // that primitive K::Ray_3 ray1(query.source(), query.target()); K::Ray_3 ray2(query.target(), query.source()); std::set ray1_results, ray2_results; this->factory.getTree().all_intersected_primitives(ray1, std::inserter(ray1_results, ray1_results.begin())); this->factory.getTree().all_intersected_primitives(ray2, std::inserter(ray2_results, ray2_results.begin())); bool inside_primitive = false; UInt primitive_id = 0; std::set::iterator ray2_it = ray2_results.begin(), ray2_end = ray2_results.end(); // Test if first list contains an element of second list for (; ray2_it != ray2_end && !inside_primitive ; ++ray2_it) { if (ray1_results.find(*ray2_it) != ray1_results.end()) { inside_primitive = true; primitive_id = *ray2_it; } } if (inside_primitive) { segments.insert(std::make_pair(query, primitive_id)); } } else { typename std::list::const_iterator it = intersections.begin(), end = intersections.end(); for(; it != end ; ++it) { UInt el = (*it)->second; // Result of intersection is a segment if (const K::Segment_3 * segment = boost::get(&((*it)->first))) { // Check if the segment was alread created segments.insert(std::make_pair(*segment, el)); } // Result of intersection is a point else if (const K::Point_3 * point = boost::get(&((*it)->first))) { // We only want to treat points differently if we're in 3D with Tetra4 elements // This should be optimized by compilator if (dim == 3 && type == _tetrahedron_4) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); TreeTypeHelper, K>::container_type facets; const Array & nodes = this->mesh.getNodes(); Array::const_vector_iterator connectivity_vec = this->mesh.getConnectivity(type).begin(nb_nodes_per_element); const Vector & el_connectivity = connectivity_vec[el]; Matrix node_coordinates(dim, nb_nodes_per_element); for (UInt i = 0 ; i < nb_nodes_per_element ; i++) for (UInt j = 0 ; j < dim ; j++) node_coordinates(j, i) = nodes(el_connectivity(i), j); this->factory.addPrimitive(node_coordinates, el, facets); // Local tree TreeTypeHelper, K>::tree * local_tree = new TreeTypeHelper, K>::tree(facets.begin(), facets.end()); // Compute local intersections (with current element) std::list local_intersections; local_tree->all_intersections(query, std::back_inserter(local_intersections)); bool out_point_found = false; typename std::list::const_iterator local_it = local_intersections.begin(), local_end = local_intersections.end(); for (; local_it != local_end ; ++local_it) { if (const K::Point_3 * local_point = boost::get(&((*local_it)->first))) { if (!comparePoints(*point, *local_point)) { K::Segment_3 seg(*point, *local_point); segments.insert(std::make_pair(seg, el)); out_point_found = true; } } } if (!out_point_found) { TreeTypeHelper, K>::point_type a(node_coordinates(0, 0), node_coordinates(1, 0), node_coordinates(2, 0)), b(node_coordinates(0, 1), node_coordinates(1, 1), node_coordinates(2, 1)), c(node_coordinates(0, 2), node_coordinates(1, 2), node_coordinates(2, 2)), d(node_coordinates(0, 3), node_coordinates(1, 3), node_coordinates(2, 3)); K::Tetrahedron_3 tetra(a, b, c, d); const K::Point_3 * inside_point = NULL; if (tetra.has_on_bounded_side(query.source()) && !tetra.has_on_boundary(query.source())) inside_point = &query.source(); else if (tetra.has_on_bounded_side(query.target()) && !tetra.has_on_boundary(query.target())) inside_point = &query.target(); if (inside_point) { K::Segment_3 seg(*inside_point, *point); segments.insert(std::make_pair(seg, el)); } } delete local_tree; } } } } AKANTU_DEBUG_OUT(); } __END_AKANTU__ #endif // __AKANTU_MESH_SEGMENT_INTERSECTOR_TMPL_HH__ diff --git a/src/io/dumper/dumper_element_iterator.hh b/src/io/dumper/dumper_element_iterator.hh index 83a3945ac..d71c1064d 100644 --- a/src/io/dumper/dumper_element_iterator.hh +++ b/src/io/dumper/dumper_element_iterator.hh @@ -1,190 +1,193 @@ /** * @file dumper_element_iterator.hh * * @author Guillaume Anciaux * @author Nicolas Richart * * @date creation: Tue Sep 02 2014 * @date last modification: Wed Sep 03 2014 * * @brief Iterators for elemental fields * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ #ifndef __AKANTU_DUMPER_ELEMENT_ITERATOR_HH__ #define __AKANTU_DUMPER_ELEMENT_ITERATOR_HH__ /* -------------------------------------------------------------------------- */ #include "element.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ __BEGIN_AKANTU_DUMPER__ /* -------------------------------------------------------------------------- */ template class final_iterator> class element_iterator { /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ public: typedef typename types::it_type it_type; typedef typename types::field_type field_type; typedef typename types::array_type array_type; typedef typename types::array_iterator array_iterator; typedef final_iterator iterator; public: /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ element_iterator(const field_type & field, const typename field_type::type_iterator & t_it, const typename field_type::type_iterator & t_it_end, const array_iterator & array_it, const array_iterator & array_it_end, const GhostType ghost_type = _not_ghost) : field(field), tit(t_it), tit_end(t_it_end), array_it(array_it), array_it_end(array_it_end), ghost_type(ghost_type) { } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: bool operator!=(const iterator & it) const { return (ghost_type != it.ghost_type) || (tit != it.tit || (array_it != it.array_it)); } iterator & operator++() { ++array_it; while(array_it == array_it_end && tit != tit_end) { ++tit; if(tit != tit_end) { const array_type & vect = field(*tit, ghost_type); UInt _nb_data_per_elem = getNbDataPerElem(*tit); UInt nb_component = vect.getNbComponent(); UInt size = (vect.getSize() * nb_component) / _nb_data_per_elem; array_it = vect.begin_reinterpret(_nb_data_per_elem,size); array_it_end = vect.end_reinterpret (_nb_data_per_elem,size); } } return *(static_cast(this)); }; ElementType getType() { return *tit; } UInt element_type() { return getIOHelperType(*tit); } Element getCurrentElement(){ return Element(*tit,array_it.getCurrentIndex()); } UInt getNbDataPerElem(const ElementType & type) const { + if (!nb_data_per_elem.exists(type, ghost_type)) + return field(type,ghost_type).getNbComponent(); + return nb_data_per_elem(type,ghost_type); } void setNbDataPerElem(const ElementTypeMap & nb_data){ this->nb_data_per_elem = nb_data; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// the field to iterate on const field_type & field; /// field iterator typename field_type::type_iterator tit; /// field iterator end typename field_type::type_iterator tit_end; /// array iterator array_iterator array_it; /// internal iterator end array_iterator array_it_end; /// ghost type identification const GhostType ghost_type; /// number of data per element ElementTypeMap nb_data_per_elem; }; /* -------------------------------------------------------------------------- */ template class elemental_field_iterator : public element_iterator { public: /* ------------------------------------------------------------------------ */ /* Typedefs */ /* ------------------------------------------------------------------------ */ typedef element_iterator parent; typedef typename types::it_type it_type; typedef typename types::return_type return_type; typedef typename types::field_type field_type; typedef typename types::array_iterator array_iterator; public: /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ elemental_field_iterator(const field_type & field, const typename field_type::type_iterator & t_it, const typename field_type::type_iterator & t_it_end, const array_iterator & array_it, const array_iterator & array_it_end, const GhostType ghost_type = _not_ghost) : parent(field, t_it, t_it_end, array_it, array_it_end, ghost_type) { } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ return_type operator*(){ return *this->array_it; } private: }; /* -------------------------------------------------------------------------- */ __END_AKANTU_DUMPER__ __END_AKANTU__ /* -------------------------------------------------------------------------- */ #endif /* __AKANTU_DUMPER_ELEMENT_ITERATOR_HH__ */ diff --git a/src/io/parser/algebraic_parser.hh b/src/io/parser/algebraic_parser.hh index 838adb63b..d2e4b845d 100644 --- a/src/io/parser/algebraic_parser.hh +++ b/src/io/parser/algebraic_parser.hh @@ -1,498 +1,561 @@ /** * @file algebraic_parser.hh * * @author Nicolas Richart * * @date creation: Wed Nov 13 2013 * @date last modification: Fri May 16 2014 * * @brief algebraic_parser definition of the grammar * * @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 . * */ /* -------------------------------------------------------------------------- */ // Boost #include #include #include #include #include #ifndef __AKANTU_ALGEBRAIC_PARSER_HH__ #define __AKANTU_ALGEBRAIC_PARSER_HH__ namespace spirit = boost::spirit; namespace qi = boost::spirit::qi; namespace lbs = boost::spirit::qi::labels; namespace ascii = boost::spirit::ascii; namespace phx = boost::phoenix; namespace akantu { namespace parser { struct algebraic_error_handler_ { template struct result { typedef void type; }; template void operator()(qi::info const& what, Iterator err_pos, Iterator last) const { AKANTU_EXCEPTION("Error! Expecting " << what // what failed? << " here: \"" << std::string(err_pos, last) // iterators to error-pos, end << "\""); } }; static Real my_min(Real a, Real b) { return std::min(a, b); } static Real my_max(Real a, Real b) { return std::max(a, b); } template struct Skipper { typedef qi::rule type; }; struct lazy_unary_func_ { template struct result { typedef T type; }; template typename result::type operator()(Funct f, T a) const { return f(a); } }; struct lazy_binary_func_ { template struct result { typedef T1 type; }; template typename result::type operator()(Funct f, T1 a, T2 b) const { return f(a, b); } }; struct lazy_pow_ { template struct result { typedef T1 type; }; template typename result::type operator()(T1 a, T2 b) const { return std::pow(a, b); } }; struct lazy_eval_param_ { template struct result { typedef res type; }; template res operator()(T1 a, const T2 & section, __attribute__((unused)) const res & result) const { return section.getParameter(a, _ppsc_current_and_parent_scope); } }; template struct AlgebraicGrammar : qi::grammar { AlgebraicGrammar(const ParserSection & section) : AlgebraicGrammar::base_type(start, "algebraic_grammar"), section(section) { phx::function const error_handler = algebraic_error_handler_(); phx::function lazy_pow; phx::function lazy_unary_func; phx::function lazy_binary_func; phx::function lazy_eval_param; start = expr.alias() ; expr = term [ lbs::_val = lbs::_1 ] >> *( ('+' > term [ lbs::_val += lbs::_1 ]) | ('-' > term [ lbs::_val -= lbs::_1 ]) ) ; term = factor [ lbs::_val = lbs::_1 ] >> *( ('*' > factor [ lbs::_val *= lbs::_1 ]) | ('/' > factor [ lbs::_val /= lbs::_1 ]) ) ; factor = number [ lbs::_val = lbs::_1 ] >> *("**" > number [ lbs::_val = lazy_pow(lbs::_val, lbs::_1) ]) ; number = real [ lbs::_val = lbs::_1 ] | ('-' > number [ lbs::_val = -lbs::_1 ]) | ('+' > number [ lbs::_val = lbs::_1 ]) | constant [ lbs::_val = lbs::_1 ] | function [ lbs::_val = lbs::_1 ] | ('(' > expr > ')') [ lbs::_val = lbs::_1 ] | variable [ lbs::_val = lbs::_1 ] ; function = (qi::no_case[unary_function] > '(' > expr > ')') [ lbs::_val = lazy_unary_func(lbs::_1, lbs::_2) ] | (qi::no_case[binary_function] > '(' >> expr > ',' >> expr > ')') [ lbs::_val = lazy_binary_func(lbs::_1, lbs::_2, lbs::_3) ] ; variable = key [ lbs::_val = lazy_eval_param(lbs::_1, section, lbs::_val) ] ; key = qi::no_skip[qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9")] // coming from the InputFileGrammar ; constant.add ("pi", M_PI) ("e", M_E); unary_function.add ("abs" , &std::abs ) ("acos" , &std::acos ) ("asin" , &std::asin ) ("atan" , &std::atan ) ("ceil" , &std::ceil ) ("cos" , &std::cos ) ("cosh" , &std::cosh ) ("exp" , &std::exp ) ("floor" , &std::floor ) ("log10" , &std::log10 ) ("log" , &std::log ) ("sin" , &std::sin ) ("sinh" , &std::sinh ) ("sqrt" , &std::sqrt ) ("tan" , &std::tan ) ("tanh" , &std::tanh ) #if defined(AKANTU_CORE_CXX11 ) ("acosh" , &std::acosh ) ("asinh" , &std::asinh ) ("atanh" , &std::atanh ) ("exp2" , &std::exp2 ) ("expm1" , &std::expm1 ) ("log1p" , &std::log1p ) ("log2" , &std::log2 ) ("erf" , &std::erf ) ("erfc" , &std::erfc ) ("lgamma", &std::lgamma) ("tgamma", &std::tgamma) ("trunc" , &std::trunc ) ("round" , &std::round ) // ("crbt" , &std::crbt ) #endif ; binary_function.add ("pow" , &std::pow ) ("min" , &parser::my_min) ("max" , &parser::my_max) ("atan2", &std::atan2 ) ("fmod" , &std::fmod ) #if defined(AKANTU_CORE_CXX11) ("hypot", &std::hypot ) #endif ; qi::on_error(start, error_handler(lbs::_4, lbs::_3, lbs::_2)); expr .name("expression"); term .name("term"); factor .name("factor"); number .name("numerical-value"); variable.name("variable"); function.name("function"); constant.name("constants-list"); unary_function.name("unary-functions-list"); binary_function.name("binary-functions-list"); + +#if !defined AKANTU_NDEBUG + if(AKANTU_DEBUG_TEST(dblDebug)) { + qi::debug(expr); + qi::debug(term); + qi::debug(factor); + qi::debug(number); + qi::debug(variable); + qi::debug(function); + } +#endif } private: qi::rule start; qi::rule expr; qi::rule term; qi::rule factor; qi::rule number; qi::rule variable; qi::rule function; qi::rule key; qi::real_parser< Real, qi::real_policies > real; qi::symbols constant; qi::symbols unary_function; qi::symbols binary_function; const ParserSection & section; }; /* ---------------------------------------------------------------------- */ /* Vector Parser */ /* ---------------------------------------------------------------------- */ struct parsable_vector { operator Vector() { Vector tmp(_cells.size()); std::vector::iterator it = _cells.begin(); for (UInt i = 0; it != _cells.end(); ++it, ++i) tmp(i) = *it; return tmp; } std::vector _cells; }; + std::ostream& operator<<(std::ostream& stream, const parsable_vector& pv) { + stream << "pv["; + std::vector::const_iterator it = pv._cells.begin(); + if(it != pv._cells.end()) { + stream << *it; + for (++it; it != pv._cells.end(); ++it) stream << ", " << *it; + } + stream << "]"; + return stream; + } + struct parsable_matrix { operator Matrix() { size_t cols = 0; std::vector::iterator it_rows = _cells.begin(); for (;it_rows != _cells.end(); ++it_rows) cols = std::max(cols, it_rows->_cells.size()); Matrix tmp(_cells.size(), _cells[0]._cells.size(), 0.); it_rows = _cells.begin(); for (UInt i = 0; it_rows != _cells.end(); ++it_rows, ++i) { std::vector::iterator it_cols = it_rows->_cells.begin(); for (UInt j = 0; it_cols != it_rows->_cells.end(); ++it_cols, ++j) { tmp(i, j) = *it_cols; } } return tmp; } std::vector _cells; }; + std::ostream& operator<<(std::ostream& stream, const parsable_matrix& pm) { + stream << "pm["; + std::vector::const_iterator it = pm._cells.begin(); + if(it != pm._cells.end()) { + stream << *it; + for (++it; it != pm._cells.end(); ++it) stream << ", " << *it; + } + stream << "]"; + return stream; + } /* ---------------------------------------------------------------------- */ struct lazy_cont_add_ { template struct result { typedef void type; }; template void operator()(T1 & cont, T2 & value) const { cont._cells.push_back(value); } }; /* ---------------------------------------------------------------------- */ template struct VectorGrammar : qi::grammar { VectorGrammar(const ParserSection & section) : VectorGrammar::base_type(start, "vector_algebraic_grammar"), number(section) { - phx::function const error_handler = algebraic_error_handler_(); - //phx::function lazy_algebraic_eval; - phx::function lazy_vector_add; + phx::function const error_handler = algebraic_error_handler_(); + //phx::function lazy_algebraic_eval; + phx::function lazy_vector_add; - start - = '[' > vector > ']' - ; + start + = '[' > vector > ']' + ; - vector - = ( number [ lazy_vector_add(lbs::_a, lbs::_1) ] + vector + = ( number [ lazy_vector_add(lbs::_a, lbs::_1) ] >> *( ',' >> number [ lazy_vector_add(lbs::_a, lbs::_1) ] ) - ) [ lbs::_val = lbs::_a ] - ; + ) [ lbs::_val = lbs::_a ] + ; - qi::on_error(start, error_handler(lbs::_4, lbs::_3, lbs::_2)); + qi::on_error(start, error_handler(lbs::_4, lbs::_3, lbs::_2)); start .name("start"); - vector.name("vector"); + vector.name("vector"); number.name("value"); + +#if !defined AKANTU_NDEBUG + if(AKANTU_DEBUG_TEST(dblDebug)) { + qi::debug(start); + qi::debug(vector); + } +#endif } private: qi::rule start; qi::rule, Skipper> vector; qi::rule value; AlgebraicGrammar number; }; /* ---------------------------------------------------------------------- */ struct lazy_vector_eval_ { template struct result { typedef bool type; }; template bool operator()(T1 a, const T2 & section, res & result) const { std::string value = section.getParameter(a, _ppsc_current_and_parent_scope); std::string::const_iterator b = value.begin(); std::string::const_iterator e = value.end(); parser::VectorGrammar grammar(section); return qi::phrase_parse(b, e, grammar, qi::space, result); } }; /* ---------------------------------------------------------------------- */ template struct MatrixGrammar : qi::grammar { MatrixGrammar(const ParserSection & section) : MatrixGrammar::base_type(start, - "matrix_algebraic_grammar"), + "matrix_algebraic_grammar"), vector(section) { - phx::function const error_handler = algebraic_error_handler_(); - phx::function lazy_vector_eval; - phx::function lazy_matrix_add; + phx::function const error_handler = algebraic_error_handler_(); + phx::function lazy_vector_eval; + phx::function lazy_matrix_add; - start - = '[' > matrix > ']' - ; + start + = '[' >> matrix >> ']' + ; - matrix - = ( rows [ lazy_matrix_add(lbs::_a, lbs::_1) ] + matrix + = ( rows [ lazy_matrix_add(lbs::_a, lbs::_1) ] >> *( ',' >> rows [ lazy_matrix_add(lbs::_a, lbs::_1) ] ) ) [ lbs::_val = lbs::_a ] ; rows = eval_vector | vector ; eval_vector = (key [ lbs::_pass = lazy_vector_eval(lbs::_1, section, lbs::_a) ]) [lbs::_val = lbs::_a] ; key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9") // coming from the InputFileGrammar ; - qi::on_error(start, error_handler(lbs::_4, lbs::_3, lbs::_2)); - start.name("matrix"); + qi::on_error(start, error_handler(lbs::_4, lbs::_3, lbs::_2)); + + start .name("matrix"); matrix.name("all_rows"); - rows .name("rows"); + rows .name("rows"); vector.name("vector"); eval_vector.name("eval_vector"); + +#ifndef AKANTU_NDEBUG + if(AKANTU_DEBUG_TEST(dblDebug)) { + qi::debug(start); + qi::debug(matrix); + qi::debug(rows); + qi::debug(eval_vector); + qi::debug(key); + } +#endif } private: qi::rule start; qi::rule, Skipper> matrix; qi::rule rows; qi::rule, Skipper> eval_vector; qi::rule key; VectorGrammar vector; }; /* ---------------------------------------------------------------------- */ /* Randon Generator */ /* ---------------------------------------------------------------------- */ struct ParsableRandomGenerator { ParsableRandomGenerator(Real base = Real(), const RandomDistributionType & type = _rdt_not_defined, const parsable_vector & parameters = parsable_vector()) : base(base), type(type), parameters(parameters) {} Real base; RandomDistributionType type; parsable_vector parameters; }; + std::ostream& operator<<(std::ostream& stream, const ParsableRandomGenerator& prg) { + stream << "prg[" << prg.base << " " << UInt(prg.type) << " " << prg.parameters << "]"; + return stream; + } + /* ---------------------------------------------------------------------- */ template struct RandomGeneratorGrammar : qi::grammar { RandomGeneratorGrammar(const ParserSection & section) : RandomGeneratorGrammar::base_type(start, "random_generator_grammar"), number(section) { - phx::function const error_handler = algebraic_error_handler_(); - phx::function lazy_params_add; + phx::function const error_handler = algebraic_error_handler_(); + phx::function lazy_params_add; start = generator.alias() ; - generator - = qi::hold[distribution [ lbs::_val = lbs::_1 ] ] + generator + = qi::hold[distribution [ lbs::_val = lbs::_1 ] ] | number [ lbs::_val = phx::construct(lbs::_1) ] - ; + ; distribution = ( - number + number >> generator_type >> '[' >> generator_params >> ']' ) [ lbs::_val = phx::construct(lbs::_1, lbs::_2, lbs::_3) ] ; - generator_params - = ( number [ lazy_params_add(lbs::_a, lbs::_1) ] + generator_params + = ( number [ lazy_params_add(lbs::_a, lbs::_1) ] >> *( ',' > number [ lazy_params_add(lbs::_a, lbs::_1) ] ) ) [ lbs::_val = lbs::_a ] ; #define AKANTU_RANDOM_DISTRIBUTION_TYPE_ADD(r, data, elem) \ (BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, elem)), \ AKANTU_RANDOM_DISTRIBUTION_TYPES_PREFIX(BOOST_PP_TUPLE_ELEM(2, 0, elem))) generator_type.add BOOST_PP_SEQ_FOR_EACH(AKANTU_RANDOM_DISTRIBUTION_TYPE_ADD, _, AKANTU_RANDOM_DISTRIBUTION_TYPES); #undef AKANTU_RANDOM_DISTRIBUTION_TYPE_ADD - qi::on_error(start, error_handler(lbs::_4, lbs::_3, lbs::_2)); + qi::on_error(start, error_handler(lbs::_4, lbs::_3, lbs::_2)); start .name("random-generator"); generator .name("random-generator"); distribution .name("random-distribution"); generator_type .name("generator-type"); - generator_params.name("generator-parameters"); + generator_params.name("generator-parameters"); number .name("number"); + +#ifndef AKANTU_NDEBUG + if(AKANTU_DEBUG_TEST(dblDebug)) { + qi::debug(generator); + qi::debug(distribution); + qi::debug(generator_params); + } +#endif } private: qi::rule start; qi::rule generator; qi::rule distribution; qi::rule, Skipper> generator_params; AlgebraicGrammar number; qi::symbols generator_type; }; } } #endif /* __AKANTU_ALGEBRAIC_PARSER_HH__ */ diff --git a/src/io/parser/input_file_parser.hh b/src/io/parser/input_file_parser.hh index 30956171e..81eb05690 100644 --- a/src/io/parser/input_file_parser.hh +++ b/src/io/parser/input_file_parser.hh @@ -1,272 +1,287 @@ /** * @file input_file_parser.hh * * @author Nicolas Richart * * @date creation: Wed Nov 13 2013 * @date last modification: Fri Apr 04 2014 * * @brief Grammar definition for the input files * * @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 . * */ /* -------------------------------------------------------------------------- */ // Boost /* -------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #include //#include #ifndef __AKANTU_INPUT_FILE_PARSER_HH__ #define __AKANTU_INPUT_FILE_PARSER_HH__ namespace spirit = boost::spirit; namespace qi = boost::spirit::qi; namespace lbs = boost::spirit::qi::labels; namespace ascii = boost::spirit::ascii; namespace phx = boost::phoenix; __BEGIN_AKANTU__ namespace parser { struct error_handler_ { template struct result { typedef void type; }; template void operator()(qi::info const& what, Iterator err_pos, Iterator first, Iterator last) const { spirit::classic::file_position pos = err_pos.get_position(); AKANTU_EXCEPTION("Parse error [ " << "Expecting " << what << " instead of \"" << *err_pos << "\" ]" << " in file " << pos.file << " line " << pos.line << " column " << pos.column << std::endl << "'" << err_pos.get_currentline() << "'" << std::endl << std::setw(pos.column) << " " << "^- here"); } private: }; struct lazy_create_subsection_ { template struct result { typedef ParserSection& type; }; template ParserSection& operator()(const SectionType & type, const std::string & name, const T & option, ParserSection & sect) const { std::string opt; if(option) opt = *option; ParserSection sect_tmp(name, type, opt, sect); return sect.addSubSection(sect_tmp); } }; template struct lazy_create_parameter_ { lazy_create_parameter_(std::string & error_message) : error_message(error_message) {} template struct result { typedef bool type; }; template bool operator()(const Range & rng, const std::string & value, ParserSection & sect) const { try { std::string name(rng.begin(), rng.end()); name = trim(name); spirit::classic::file_position pos = rng.begin().get_position(); ParserParameter param_tmp(name, value, sect); param_tmp.setDebugInfo(pos.file, pos.line, pos.column); sect.addParameter(param_tmp); } catch (debug::Exception & e) { error_message = e.info(); return false; } return true; } private: std::string & error_message; }; struct lazy_concatenate_ { template struct result { typedef T1 type; }; template T1 operator()(const T1 & t1, const T2 & t2) const { return (t1 + t2); } }; /* ---------------------------------------------------------------------- */ /* Grammars definitions */ /* ---------------------------------------------------------------------- */ template struct InputFileGrammar : qi::grammar::type> { InputFileGrammar(ParserSection * sect) : InputFileGrammar::base_type(start, "input_file_grammar"), parent_section(sect) { phx::function const error_handler = error_handler_(); phx::function< lazy_create_parameter_ > lazy_create_parameter = lazy_create_parameter_(error_message); phx::function lazy_create_subsection; phx::function lazy_concatenate; start = mini_section(parent_section) ; mini_section = *( entry (lbs::_r1) | section(lbs::_r1) ) ; entry = ( qi::raw[key] >> '=' > value ) [ lbs::_pass = lazy_create_parameter(lbs::_1, lbs::_2, *lbs::_r1) ] ; section = ( qi::no_case[section_type] > qi::lexeme [ section_name > -section_option ] ) [ lbs::_a = &lazy_create_subsection(lbs::_1, phx::at_c<0>(lbs::_2), phx::at_c<1>(lbs::_2), *lbs::_r1) ] > '[' > mini_section(lbs::_a) > ']' ; section_name = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9") ; section_option = (+ascii::space >> section_name) [ lbs::_val = lbs::_2 ] ; key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9") ; value = ( mono_line_value [ lbs::_a = lazy_concatenate(lbs::_a, lbs::_1) ] > *( '\\' > mono_line_value [ lbs::_a = lazy_concatenate(lbs::_a, lbs::_1) ] ) ) [ lbs::_val = lbs::_a ] ; mono_line_value = qi::lexeme [ +(qi::char_ - (qi::char_('=') | spirit::eol | '#' | ';' | '\\')) ] ; skipper = ascii::space | "#" >> *(qi::char_ - spirit::eol) ; #define AKANTU_SECTION_TYPE_ADD(r, data, elem) \ (BOOST_PP_STRINGIZE(elem), AKANTU_SECTION_TYPES_PREFIX(elem)) section_type.add BOOST_PP_SEQ_FOR_EACH(AKANTU_SECTION_TYPE_ADD, _, AKANTU_SECTION_TYPES); #undef AKANTU_SECTION_TYPE_ADD qi::on_error(start, error_handler(lbs::_4, lbs::_3, lbs::_1, lbs::_2)); section .name("section"); section_name .name("section-name"); section_option .name("section-option"); mini_section .name("section-content"); entry .name("parameter"); key .name("parameter-name"); value .name("parameter-value"); section_type .name("section-types-list"); mono_line_value.name("mono-line-value"); + + +#if !defined AKANTU_NDEBUG + if(AKANTU_DEBUG_TEST(dblDebug)) { + // qi::debug(section); + qi::debug(section_name); + qi::debug(section_option); + // qi::debug(mini_section); + // qi::debug(entry); + qi::debug(key); + qi::debug(value); + qi::debug(mono_line_value); + } +#endif + } const std::string & getErrorMessage() const { return error_message; }; typedef typename Skipper::type skipper_type; skipper_type skipper; private: std::string error_message; qi::rule mini_section; qi::rule, skipper_type> section; qi::rule start; qi::rule section_name; qi::rule section_option; qi::rule entry; qi::rule key; qi::rule, skipper_type> value; qi::rule mono_line_value; qi::symbols section_type; ParserSection * parent_section; }; } __END_AKANTU__ #endif /* __AKANTU_INPUT_FILE_PARSER_HH__ */ diff --git a/src/io/parser/parser.cc b/src/io/parser/parser.cc index 056355802..ef41eb103 100644 --- a/src/io/parser/parser.cc +++ b/src/io/parser/parser.cc @@ -1,227 +1,231 @@ /** * @file parser.cc * * @author Nicolas Richart * * @date creation: Wed Nov 13 2013 * @date last modification: Fri Sep 05 2014 * * @brief implementation of the parser * * @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 . * */ /* -------------------------------------------------------------------------- */ // STL #include #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "parser.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ //#include #include #include #include /* -------------------------------------------------------------------------- */ #include "algebraic_parser.hh" #include "input_file_parser.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ ParserSection::~ParserSection() { } /* -------------------------------------------------------------------------- */ ParserParameter & ParserSection::addParameter(const ParserParameter & param) { if(parameters.find(param.getName()) != parameters.end()) AKANTU_EXCEPTION("The parameter \"" + param.getName() + "\" is already defined in this section"); return (parameters.insert (std::pair(param.getName(), param)).first->second); } /* -------------------------------------------------------------------------- */ ParserSection & ParserSection::addSubSection(const ParserSection & section) { return ((sub_sections_by_type.insert (std::pair(section.getType(), section)))->second); } /* -------------------------------------------------------------------------- */ std::string Parser::getLastParsedFile() const { return last_parsed_file; } /* -------------------------------------------------------------------------- */ void Parser::parse(const std::string& filename) { std::ifstream input(filename.c_str()); if(!input.good()) { AKANTU_EXCEPTION("Could not open file " << filename << "!"); } input.unsetf(std::ios::skipws); // wrap istream into iterator spirit::istream_iterator fwd_begin(input); spirit::istream_iterator fwd_end; // wrap forward iterator with position iterator, to record the position typedef spirit::classic::position_iterator2 pos_iterator_type; pos_iterator_type position_begin(fwd_begin, fwd_end, filename); pos_iterator_type position_end; // parse parser::InputFileGrammar ag(this); bool result = qi::phrase_parse(position_begin, position_end, ag, ag.skipper); if(!result || position_begin != position_end) { spirit::classic::file_position pos = position_begin.get_position(); AKANTU_EXCEPTION("Parse error [ " << ag.getErrorMessage() << " ]" << " in file " << filename << " line " << pos.line << " column " << pos.column << std::endl << "'" << position_begin.get_currentline() << "'" << std::endl << std::setw(pos.column) << " " << "^- here"); } try { DebugLevel dbl = debug::getDebugLevel(); debug::setDebugLevel(dblError); bool permissive = getParameter("parser_permissive", _ppsc_current_scope); debug::setDebugLevel(dbl); parser_permissive = permissive; AKANTU_DEBUG_INFO("Parser switched permissive mode to " << std::boolalpha << parser_permissive); } catch (debug::Exception & e) { } last_parsed_file = filename; input.close(); } /* -------------------------------------------------------------------------- */ template T Parser::parseType(const std::string & value, Grammar & grammar) { using boost::spirit::ascii::space; std::string::const_iterator b = value.begin(); std::string::const_iterator e = value.end(); T resultat = T(); bool res = false; try { res = qi::phrase_parse(b, e, grammar, space, resultat); } catch(debug::Exception & ex) { AKANTU_EXCEPTION("Could not parse '" << value << "' as a " << debug::demangle(typeid(T).name()) << ", an unknown error append '" << ex.what()); } if(!res || (b != e)) { AKANTU_EXCEPTION("Could not parse '" << value << "' as a " << debug::demangle(typeid(T).name()) << ", an unknown error append '" << std::string(value.begin(), b) << "" << std::string(b, e) << "'"); } return resultat; } /* -------------------------------------------------------------------------- */ Real Parser::parseReal(const std::string & value, const ParserSection & section) { using boost::spirit::ascii::space_type; parser::AlgebraicGrammar grammar(section); + grammar.name("algebraic_grammar"); return Parser::parseType(value, grammar); } /* -------------------------------------------------------------------------- */ Vector Parser::parseVector(const std::string & value, const ParserSection & section) { using boost::spirit::ascii::space_type; parser::VectorGrammar grammar(section); + grammar.name("vector_grammar"); return Parser::parseType(value, grammar); } /* -------------------------------------------------------------------------- */ Matrix Parser::parseMatrix(const std::string & value, const ParserSection & section) { using boost::spirit::ascii::space_type; parser::MatrixGrammar grammar(section); + grammar.name("matrix_grammar"); return Parser::parseType(value, grammar); } /* -------------------------------------------------------------------------- */ RandomParameter Parser::parseRandomParameter(const std::string & value, const ParserSection & section) { using boost::spirit::ascii::space_type; parser::RandomGeneratorGrammar grammar(section); + grammar.name("random_grammar"); parser::ParsableRandomGenerator rg = Parser::parseType(value, grammar); Vector params = rg.parameters; switch(rg.type) { case _rdt_not_defined: return RandomParameter(rg.base); case _rdt_uniform: return RandomParameter(rg.base, UniformDistribution(params(0), params(1))); case _rdt_weibull: return RandomParameter(rg.base, WeibullDistribution(params(0), params(1))); default: AKANTU_EXCEPTION("This is an unknown random distribution in the parser"); } } /* -------------------------------------------------------------------------- */ void ParserSection::printself(std::ostream & stream, unsigned int indent) const { std::string space; std::string ind = AKANTU_INDENT; for(unsigned int i = 0; i < indent; i++, space += ind); stream << space << "Section(" << this->type << ") " << this->name << (option != "" ? (" " + option) : "") << " [" << std::endl; if(!this->parameters.empty()) { stream << space << ind << "Parameters [" << std::endl; Parameters::const_iterator pit = this->parameters.begin(); for(;pit != this->parameters.end(); ++pit) { stream << space << ind << " + "; pit->second.printself(stream); stream << std::endl; } stream << space << ind << "]" << std::endl; } if(!this->sub_sections_by_type.empty()) { stream << space << ind << "Subsections [" << std::endl; SubSections::const_iterator sit = this->sub_sections_by_type.begin(); for (;sit != this->sub_sections_by_type.end(); ++sit) sit->second.printself(stream, indent + 2); stream << std::endl; stream << space << ind << "]" << std::endl; } stream << space << "]" << std::endl; } __END_AKANTU__ diff --git a/src/io/parser/parser_tmpl.hh b/src/io/parser/parser_tmpl.hh index 225456d02..5b722dd73 100644 --- a/src/io/parser/parser_tmpl.hh +++ b/src/io/parser/parser_tmpl.hh @@ -1,106 +1,106 @@ /** * @file parser_tmpl.hh * * @author Nicolas Richart * * @date creation: Wed Nov 13 2013 * @date last modification: Tue Jun 24 2014 * * @brief Implementation of the parser templated methods * * @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 . * */ /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template inline ParserParameter::operator T() const { T t; std::stringstream sstr(value); sstr >> t; if(sstr.bad()) AKANTU_EXCEPTION("No known conversion of a ParserParameter \"" << name << "\" to the type " << typeid(T).name()); return t; } /* -------------------------------------------------------------------------- */ template<> -inline ParserParameter::operator std::string() const { - return value; +inline ParserParameter::operator const char *() const { + return value.c_str(); } /* -------------------------------------------------------------------------- */ template<> inline ParserParameter::operator Real() const { return Parser::parseReal(value, *parent_section); } /* --------------------------------------------------------- ----------------- */ template<> inline ParserParameter::operator bool() const { bool b; std::stringstream sstr(value); sstr >> std::boolalpha >> b; if(sstr.fail()) { sstr.clear(); sstr >> std::noboolalpha >> b; } return b; } /* --------------------------------------------------------- ----------------- */ template<> inline ParserParameter::operator Vector() const { return Parser::parseVector(value, *parent_section); } /* --------------------------------------------------------- ----------------- */ template<> inline ParserParameter::operator Vector() const { Vector tmp = Parser::parseVector(value, *parent_section); Vector tmp_uint(tmp.size()); for (UInt i=0; i inline ParserParameter::operator Matrix() const { return Parser::parseMatrix(value, *parent_section); } /* -------------------------------------------------------------------------- */ template<> inline ParserParameter::operator RandomParameter() const { return Parser::parseRandomParameter(value, *parent_section); } __END_AKANTU__ diff --git a/src/mesh/mesh.cc b/src/mesh/mesh.cc index 0538af7a3..decdba584 100644 --- a/src/mesh/mesh.cc +++ b/src/mesh/mesh.cc @@ -1,508 +1,509 @@ /** * @file mesh.cc * * @author Guillaume Anciaux * @author David Simon Kammer * @author Marco Vocialta * @author Nicolas Richart * * @date creation: Fri Jun 18 2010 * @date last modification: Fri Sep 05 2014 * * @brief class handling meshes * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #include "aka_config.hh" /* -------------------------------------------------------------------------- */ #include "mesh.hh" #include "group_manager_inline_impl.cc" #include "mesh_io.hh" #include "element_class.hh" #include "static_communicator.hh" #include "element_group.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "dumper_field.hh" # include "dumper_material_internal_field.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ const Element ElementNull(_not_defined, 0); /* -------------------------------------------------------------------------- */ void Element::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Element [" << type << ", " << element << ", " << ghost_type << "]"; } /* -------------------------------------------------------------------------- */ Mesh::Mesh(UInt spatial_dimension, const ID & id, const MemoryID & memory_id) : Memory(id, memory_id), GroupManager(*this, id + ":group_manager", memory_id), nodes_global_ids(NULL), nodes_type(0, 1, id + ":nodes_type"), created_nodes(true), connectivities("connectivities", id), normals("normals", id), spatial_dimension(spatial_dimension), types_offsets(Array((UInt) _max_element_type + 1, 1)), ghost_types_offsets(Array((UInt) _max_element_type + 1, 1)), lower_bounds(spatial_dimension,0.), upper_bounds(spatial_dimension,0.), size(spatial_dimension, 0.), local_lower_bounds(spatial_dimension,0.), local_upper_bounds(spatial_dimension,0.), mesh_data("mesh_data", id, memory_id), mesh_facets(NULL) { AKANTU_DEBUG_IN(); this->nodes = &(alloc(id + ":coordinates", 0, this->spatial_dimension)); nb_global_nodes = 0; init(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Mesh::Mesh(UInt spatial_dimension, const ID & nodes_id, const ID & id, const MemoryID & memory_id) : Memory(id, memory_id), GroupManager(*this, id + ":group_manager", memory_id), nodes_global_ids(NULL), nodes_type(0, 1, id + ":nodes_type"), created_nodes(false), connectivities("connectivities", id), normals("normals", id), spatial_dimension(spatial_dimension), types_offsets(Array((UInt) _max_element_type + 1, 1)), ghost_types_offsets(Array((UInt) _max_element_type + 1, 1)), lower_bounds(spatial_dimension,0.), upper_bounds(spatial_dimension,0.), size(spatial_dimension, 0.), local_lower_bounds(spatial_dimension,0.), local_upper_bounds(spatial_dimension,0.), mesh_data("mesh_data", id, memory_id), mesh_facets(NULL) { AKANTU_DEBUG_IN(); this->nodes = &(getArray(nodes_id)); nb_global_nodes = nodes->getSize(); init(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Mesh::Mesh(UInt spatial_dimension, Array & nodes, const ID & id, const MemoryID & memory_id) : Memory(id, memory_id), GroupManager(*this, id + ":group_manager", memory_id), nodes_global_ids(NULL), nodes_type(0, 1, id + ":nodes_type"), created_nodes(false), connectivities("connectivities", id), normals("normals", id), spatial_dimension(spatial_dimension), types_offsets(Array(_max_element_type + 1, 1)), ghost_types_offsets(Array(_max_element_type + 1, 1)), lower_bounds(spatial_dimension,0.), upper_bounds(spatial_dimension,0.), size(spatial_dimension, 0.), local_lower_bounds(spatial_dimension,0.), local_upper_bounds(spatial_dimension,0.), mesh_data("mesh_data", id, memory_id), mesh_facets(NULL) { AKANTU_DEBUG_IN(); this->nodes = &(nodes); nb_global_nodes = nodes.getSize(); init(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Mesh & Mesh::initMeshFacets(const ID & id) { AKANTU_DEBUG_IN(); if (!mesh_facets) { mesh_facets = new Mesh(spatial_dimension, *(this->nodes), getID()+":"+id, getMemoryID()); mesh_facets->mesh_parent = this; mesh_facets->is_mesh_facets = true; } AKANTU_DEBUG_OUT(); return *mesh_facets; } /* -------------------------------------------------------------------------- */ void Mesh::defineMeshParent(const Mesh & mesh) { AKANTU_DEBUG_IN(); this->mesh_parent = &mesh; this->is_mesh_facets = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Mesh::init() { this->is_mesh_facets = false; this->mesh_parent = NULL; this->is_distributed = false; // computeBoundingBox(); } /* -------------------------------------------------------------------------- */ Mesh::~Mesh() { AKANTU_DEBUG_IN(); delete mesh_facets; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Mesh::read (const std::string & filename, const MeshIOType & mesh_io_type) { MeshIO mesh_io; mesh_io.read(filename, *this, mesh_io_type); type_iterator it = this->firstType(spatial_dimension, _not_ghost, _ek_not_defined); type_iterator last = this->lastType(spatial_dimension, _not_ghost, _ek_not_defined); if(it == last) AKANTU_EXCEPTION("The mesh contained in the file " << filename << " does not seam to be of the good dimension." << " No element of dimension " << spatial_dimension << " where read."); } /* -------------------------------------------------------------------------- */ void Mesh::write(const std::string & filename, const MeshIOType & mesh_io_type) { MeshIO mesh_io; mesh_io.write(filename, *this, mesh_io_type); } /* -------------------------------------------------------------------------- */ void Mesh::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Mesh [" << std::endl; stream << space << " + id : " << getID() << std::endl; stream << space << " + spatial dimension : " << this->spatial_dimension << std::endl; stream << space << " + nodes [" << std::endl; nodes->printself(stream, indent+2); stream << space << " + connectivities [" << std::endl; connectivities.printself(stream, indent+2); stream << space << " ]" << std::endl; GroupManager::printself(stream, indent + 1); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ void Mesh::computeBoundingBox(){ AKANTU_DEBUG_IN(); for (UInt k = 0; k < spatial_dimension; ++k) { local_lower_bounds(k) = std::numeric_limits::max(); local_upper_bounds(k) = - std::numeric_limits::max(); } for (UInt i = 0; i < nodes->getSize(); ++i) { // if(!isPureGhostNode(i)) for (UInt k = 0; k < spatial_dimension; ++k) { local_lower_bounds(k) = std::min(local_lower_bounds[k], (*nodes)(i, k)); local_upper_bounds(k) = std::max(local_upper_bounds[k], (*nodes)(i, k)); } } if (this->is_distributed) { StaticCommunicator & comm = StaticCommunicator::getStaticCommunicator(); Real reduce_bounds[2 * spatial_dimension]; for (UInt k = 0; k < spatial_dimension; ++k) { reduce_bounds[2*k ] = local_lower_bounds(k); reduce_bounds[2*k + 1] = - local_upper_bounds(k); } comm.allReduce(reduce_bounds, 2 * spatial_dimension, _so_min); for (UInt k = 0; k < spatial_dimension; ++k) { lower_bounds(k) = reduce_bounds[2*k]; upper_bounds(k) = - reduce_bounds[2*k + 1]; } } else { this->lower_bounds = this->local_lower_bounds; this->upper_bounds = this->local_upper_bounds; } size = upper_bounds - lower_bounds; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Mesh::initElementTypeMapArray(ElementTypeMapArray & vect, UInt nb_component, UInt dim, const bool & flag_nb_node_per_elem_multiply, ElementKind element_kind, bool size_to_nb_element) const { AKANTU_DEBUG_IN(); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; this->initElementTypeMapArray(vect, nb_component, dim, gt, flag_nb_node_per_elem_multiply, element_kind, size_to_nb_element); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Mesh::initElementTypeMapArray(ElementTypeMapArray & vect, UInt nb_component, UInt dim, GhostType gt, const bool & flag_nb_node_per_elem_multiply, ElementKind element_kind, bool size_to_nb_element) const { AKANTU_DEBUG_IN(); this->initElementTypeMapArray(vect, nb_component, dim, gt, T(), flag_nb_node_per_elem_multiply, element_kind, size_to_nb_element); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Mesh::initElementTypeMapArray(ElementTypeMapArray & vect, UInt nb_component, UInt dim, GhostType gt, const T & default_value, const bool & flag_nb_node_per_elem_multiply, ElementKind element_kind, bool size_to_nb_element) const { AKANTU_DEBUG_IN(); Mesh::type_iterator it = firstType(dim, gt, element_kind); Mesh::type_iterator end = lastType(dim, gt, element_kind); for(; it != end; ++it) { ElementType type = *it; - if (flag_nb_node_per_elem_multiply) nb_component *= Mesh::getNbNodesPerElement(*it); + UInt nb_comp = nb_component; + if (flag_nb_node_per_elem_multiply) nb_comp *= Mesh::getNbNodesPerElement(*it); UInt size = 0; if (size_to_nb_element) size = this->getNbElement(type, gt); - vect.alloc(size, nb_component, type, gt, default_value); + vect.alloc(size, nb_comp, type, gt, default_value); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Mesh::initNormals() { this->initElementTypeMapArray(normals, spatial_dimension, spatial_dimension, false, _ek_not_defined); } /* -------------------------------------------------------------------------- */ void Mesh::getGlobalConnectivity(ElementTypeMapArray & global_connectivity, UInt dimension, GhostType ghost_type) { AKANTU_DEBUG_IN(); Mesh::type_iterator it = firstType(dimension, ghost_type); Mesh::type_iterator end = lastType(dimension, ghost_type); for(; it != end; ++it) { ElementType type = *it; Array & local_conn = connectivities(type, ghost_type); Array & g_connectivity = global_connectivity(type, ghost_type); if (!nodes_global_ids) nodes_global_ids = mesh_parent->nodes_global_ids; UInt * local_c = local_conn.storage(); UInt * global_c = g_connectivity.storage(); UInt nb_terms = local_conn.getSize() * local_conn.getNbComponent(); for (UInt i = 0; i < nb_terms; ++i, ++local_c, ++global_c) *global_c = (*nodes_global_ids)(*local_c); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ DumperIOHelper & Mesh::getGroupDumper(const std::string & dumper_name, const std::string & group_name){ if (group_name == "all") return this->getDumper(dumper_name); else return element_groups[group_name]->getDumper(dumper_name); } /* -------------------------------------------------------------------------- */ #define AKANTU_INSTANTIATE_INIT(type) \ template void Mesh::initElementTypeMapArray(ElementTypeMapArray & vect, \ UInt nb_component, \ UInt dim, \ const bool & flag_nb_elem_multiply, \ ElementKind element_kind, \ bool size_to_nb_element) const; \ template void Mesh::initElementTypeMapArray(ElementTypeMapArray & vect, \ UInt nb_component, \ UInt dim, \ GhostType gt, \ const bool & flag_nb_elem_multiply, \ ElementKind element_kind, \ bool size_to_nb_element) const; \ template void Mesh::initElementTypeMapArray(ElementTypeMapArray & vect, \ UInt nb_component, \ UInt dim, \ GhostType gt, \ const type & default_value, \ const bool & flag_nb_elem_multiply, \ ElementKind element_kind, \ bool size_to_nb_element) const; AKANTU_INSTANTIATE_INIT(Real); AKANTU_INSTANTIATE_INIT(UInt); AKANTU_INSTANTIATE_INIT(Int); AKANTU_INSTANTIATE_INIT(bool); /* -------------------------------------------------------------------------- */ template ElementTypeMap Mesh::getNbDataPerElem(ElementTypeMapArray & array, const ElementKind & element_kind){ ElementTypeMap nb_data_per_elem; typename ElementTypeMapArray::type_iterator it = array.firstType(spatial_dimension, _not_ghost,element_kind); typename ElementTypeMapArray::type_iterator last_type = array.lastType(spatial_dimension, _not_ghost,element_kind); for(; it != last_type; ++it) { UInt nb_elements = this->getNbElement(*it); nb_data_per_elem(*it) = array(*it).getNbComponent() * array(*it).getSize(); nb_data_per_elem(*it) /= nb_elements; } return nb_data_per_elem; } /* -------------------------------------------------------------------------- */ template ElementTypeMap Mesh::getNbDataPerElem(ElementTypeMapArray & array, const ElementKind & element_kind); template ElementTypeMap Mesh::getNbDataPerElem(ElementTypeMapArray & array, const ElementKind & element_kind); /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER template dumper::Field * Mesh::createFieldFromAttachedData(const std::string & field_id, const std::string & group_name, const ElementKind & element_kind){ dumper::Field * field = NULL; ElementTypeMapArray * internal = NULL; try { internal = &(this->getData(field_id)); } catch (...){ return NULL; } ElementTypeMap nb_data_per_elem = this->getNbDataPerElem(*internal,element_kind); field = this->createElementalField(*internal, group_name, this->spatial_dimension, element_kind, nb_data_per_elem); return field; } template dumper::Field * Mesh::createFieldFromAttachedData(const std::string & field_id, const std::string & group_name, const ElementKind & element_kind); template dumper::Field * Mesh::createFieldFromAttachedData(const std::string & field_id, const std::string & group_name, const ElementKind & element_kind); /* -------------------------------------------------------------------------- */ #endif __END_AKANTU__ diff --git a/src/mesh/mesh_inline_impl.cc b/src/mesh/mesh_inline_impl.cc index 2bade9ae1..9e86ca47f 100644 --- a/src/mesh/mesh_inline_impl.cc +++ b/src/mesh/mesh_inline_impl.cc @@ -1,555 +1,553 @@ /** * @file mesh_inline_impl.cc * * @author Guillaume Anciaux * @author Dana Christen * @author Marco Vocialta * @author Nicolas Richart * * @date creation: Thu Jul 15 2010 * @date last modification: Fri Sep 05 2014 * * @brief Implementation of the inline functions of the mesh 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 . * */ /* -------------------------------------------------------------------------- */ #if defined(AKANTU_COHESIVE_ELEMENT) # include "cohesive_element.hh" #endif #if defined(AKANTU_IGFEM) # include "igfem_element.hh" #endif #ifndef __AKANTU_MESH_INLINE_IMPL_CC__ #define __AKANTU_MESH_INLINE_IMPL_CC__ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ inline RemovedNodesEvent::RemovedNodesEvent(const Mesh & mesh) : new_numbering(mesh.getNbNodes(), 1, "new_numbering") { } /* -------------------------------------------------------------------------- */ inline RemovedElementsEvent::RemovedElementsEvent(const Mesh & mesh) : new_numbering("new_numbering", mesh.getID()) { } /* -------------------------------------------------------------------------- */ template <> inline void Mesh::sendEvent(RemovedElementsEvent & event) { connectivities.onElementsRemoved(event.getNewNumbering()); EventHandlerManager::sendEvent(event); } /* -------------------------------------------------------------------------- */ template <> inline void Mesh::sendEvent(RemovedNodesEvent & event) { if(created_nodes) removeNodesFromArray(*nodes , event.getNewNumbering()); if(nodes_global_ids) removeNodesFromArray(*nodes_global_ids, event.getNewNumbering()); if(nodes_type.getSize() != 0) removeNodesFromArray(nodes_type , event.getNewNumbering()); EventHandlerManager::sendEvent(event); } /* -------------------------------------------------------------------------- */ template inline void Mesh::removeNodesFromArray(Array & vect, const Array & new_numbering) { Array tmp(vect.getSize(), vect.getNbComponent()); UInt nb_component = vect.getNbComponent(); UInt new_nb_nodes = 0; for (UInt i = 0; i < new_numbering.getSize(); ++i) { UInt new_i = new_numbering(i); if(new_i != UInt(-1)) { memcpy(tmp.storage() + new_i * nb_component, vect.storage() + i * nb_component, nb_component * sizeof(T)); ++new_nb_nodes; } } tmp.resize(new_nb_nodes); vect.copy(tmp); } /* -------------------------------------------------------------------------- */ #ifdef AKANTU_CORE_CXX11 template inline void Mesh::translate(Args... params) { // check that the number of parameters corresponds to the dimension AKANTU_DEBUG_ASSERT(sizeof...(Args) <= spatial_dimension , "Number of arguments greater than dimension."); // unpack parameters Real s[] = { params... }; Array& nodes = getNodes(); for (UInt i = 0; i < nodes.getSize(); ++i) for (UInt k = 0; k < sizeof...(Args); ++k) nodes(i, k) += s[k]; } #endif /* -------------------------------------------------------------------------- */ inline UInt Mesh::elementToLinearized(const Element & elem) const { AKANTU_DEBUG_ASSERT(elem.type < _max_element_type && elem.element < types_offsets.storage()[elem.type+1], "The element " << elem << "does not exists in the mesh " << getID()); return types_offsets.storage()[elem.type] + elem.element; } /* -------------------------------------------------------------------------- */ inline Element Mesh::linearizedToElement (UInt linearized_element) const { UInt t; for (t = _not_defined; t != _max_element_type && linearized_element >= types_offsets(t); ++t); AKANTU_DEBUG_ASSERT(linearized_element < types_offsets(t), "The linearized element " << linearized_element << "does not exists in the mesh " << getID()); --t; ElementType type = ElementType(t); return Element(type, linearized_element - types_offsets.storage()[t], _not_ghost, getKind(type)); } /* -------------------------------------------------------------------------- */ inline void Mesh::updateTypesOffsets(const GhostType & ghost_type) { Array * types_offsets_ptr = &this->types_offsets; if(ghost_type == _ghost) types_offsets_ptr = &this->ghost_types_offsets; Array & types_offsets = *types_offsets_ptr; types_offsets.clear(); type_iterator it = firstType(_all_dimensions, ghost_type, _ek_not_defined); type_iterator last = lastType(_all_dimensions, ghost_type, _ek_not_defined); for (; it != last; ++it) types_offsets(*it) = connectivities(*it, ghost_type).getSize(); for (UInt t = _not_defined + 1; t < _max_element_type; ++t) types_offsets(t) += types_offsets(t - 1); for (UInt t = _max_element_type; t > _not_defined; --t) types_offsets(t) = types_offsets(t - 1); types_offsets(0) = 0; } /* -------------------------------------------------------------------------- */ inline const Mesh::ConnectivityTypeList & Mesh::getConnectivityTypeList(const GhostType & ghost_type) const { if (ghost_type == _not_ghost) return type_set; else return ghost_type_set; } /* -------------------------------------------------------------------------- */ inline Array * Mesh::getNodesGlobalIdsPointer() { AKANTU_DEBUG_IN(); if(nodes_global_ids == NULL) { std::stringstream sstr; sstr << getID() << ":nodes_global_ids"; nodes_global_ids = &(alloc(sstr.str(), nodes->getSize(), 1)); } AKANTU_DEBUG_OUT(); return nodes_global_ids; } /* -------------------------------------------------------------------------- */ inline Array * Mesh::getNodesTypePointer() { AKANTU_DEBUG_IN(); if(nodes_type.getSize() == 0) { nodes_type.resize(nodes->getSize()); nodes_type.set(-1); } AKANTU_DEBUG_OUT(); return &nodes_type; } /* -------------------------------------------------------------------------- */ inline Array * Mesh::getConnectivityPointer(const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Array * tmp; if(!connectivities.exists(type, ghost_type)) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); tmp = &(connectivities.alloc(0, nb_nodes_per_element, type, ghost_type)); AKANTU_DEBUG_INFO("The connectivity vector for the type " << type << " created"); if (ghost_type == _not_ghost) type_set.insert(type); else ghost_type_set.insert(type); updateTypesOffsets(ghost_type); } else { tmp = &connectivities(type, ghost_type); } AKANTU_DEBUG_OUT(); return tmp; } /* -------------------------------------------------------------------------- */ inline Array< std::vector > * Mesh::getElementToSubelementPointer(const ElementType & type, const GhostType & ghost_type) { Array< std::vector > * tmp = getDataPointer< std::vector >("element_to_subelement", type, ghost_type, 1, true); return tmp; } /* -------------------------------------------------------------------------- */ inline Array * Mesh::getSubelementToElementPointer(const ElementType & type, const GhostType & ghost_type) { Array * tmp = getDataPointer("subelement_to_element", type, ghost_type, getNbFacetsPerElement(type), true, is_mesh_facets); return tmp; } /* -------------------------------------------------------------------------- */ inline const Array< std::vector > & Mesh::getElementToSubelement(const ElementType & type, const GhostType & ghost_type) const { return getData< std::vector >("element_to_subelement", type, ghost_type); } /* -------------------------------------------------------------------------- */ inline Array< std::vector > & Mesh::getElementToSubelement(const ElementType & type, const GhostType & ghost_type) { return getData< std::vector >("element_to_subelement", type, ghost_type); } /* -------------------------------------------------------------------------- */ inline const Array & Mesh::getSubelementToElement(const ElementType & type, const GhostType & ghost_type) const { return getData("subelement_to_element", type, ghost_type); } /* -------------------------------------------------------------------------- */ inline Array & Mesh::getSubelementToElement(const ElementType & type, const GhostType & ghost_type) { return getData("subelement_to_element", type, ghost_type); } /* -------------------------------------------------------------------------- */ template inline Array * Mesh::getDataPointer(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type, UInt nb_component, bool size_to_nb_element, bool resize_with_parent) { Array & tmp = mesh_data.getElementalDataArrayAlloc(data_name, el_type, ghost_type, nb_component); if (size_to_nb_element) { if (resize_with_parent) tmp.resize(mesh_parent->getNbElement(el_type, ghost_type)); else tmp.resize(this->getNbElement(el_type, ghost_type)); } else { tmp.resize(0); } return &tmp; } /* -------------------------------------------------------------------------- */ template inline const Array & Mesh::getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type) const { return mesh_data.getElementalDataArray(data_name, el_type, ghost_type); } /* -------------------------------------------------------------------------- */ template inline Array & Mesh::getData(const std::string & data_name, const ElementType & el_type, const GhostType & ghost_type) { return mesh_data.getElementalDataArray(data_name, el_type, ghost_type); } /* -------------------------------------------------------------------------- */ template inline const ElementTypeMapArray & Mesh::getData(const std::string & data_name) const { return mesh_data.getElementalData(data_name); } /* -------------------------------------------------------------------------- */ template inline ElementTypeMapArray & Mesh::getData(const std::string & data_name) { return mesh_data.getElementalData(data_name); } /* -------------------------------------------------------------------------- */ template inline ElementTypeMapArray & Mesh::registerData(const std::string & data_name) { this->mesh_data.registerElementalData(data_name); return this->getData(data_name); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbElement(const ElementType & type, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); try { const Array & conn = connectivities(type, ghost_type); AKANTU_DEBUG_OUT(); return conn.getSize(); } catch (...) { AKANTU_DEBUG_OUT(); return 0; } } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbElement(const UInt spatial_dimension, const GhostType & ghost_type, const ElementKind & kind) const { AKANTU_DEBUG_IN(); UInt nb_element = 0; type_iterator it = firstType(spatial_dimension, ghost_type, kind); type_iterator last = lastType(spatial_dimension, ghost_type, kind); for (; it != last; ++it) nb_element += getNbElement(*it, ghost_type); AKANTU_DEBUG_OUT(); return nb_element; } /* -------------------------------------------------------------------------- */ inline void Mesh::getBarycenter(UInt element, const ElementType & type, Real * barycenter, GhostType ghost_type) const { AKANTU_DEBUG_IN(); UInt * conn_val = getConnectivity(type, ghost_type).storage(); UInt nb_nodes_per_element = getNbNodesPerElement(type); Real local_coord[spatial_dimension * nb_nodes_per_element]; UInt offset = element * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { memcpy(local_coord + n * spatial_dimension, nodes->storage() + conn_val[offset + n] * spatial_dimension, spatial_dimension*sizeof(Real)); } Math::barycenter(local_coord, nb_nodes_per_element, spatial_dimension, barycenter); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void Mesh::getBarycenter(const Element & element, Vector & barycenter) const { getBarycenter(element.element, element.type, barycenter.storage(), element.ghost_type); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbNodesPerElement(const ElementType & type) { UInt nb_nodes_per_element = 0; #define GET_NB_NODES_PER_ELEMENT(type) \ nb_nodes_per_element = ElementClass::getNbNodesPerElement() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_NODES_PER_ELEMENT); #undef GET_NB_NODES_PER_ELEMENT return nb_nodes_per_element; } /* -------------------------------------------------------------------------- */ inline ElementType Mesh::getP1ElementType(const ElementType & type) { ElementType p1_type = _not_defined; #define GET_P1_TYPE(type) \ p1_type = ElementClass::getP1ElementType() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_P1_TYPE); #undef GET_P1_TYPE return p1_type; } /* -------------------------------------------------------------------------- */ inline ElementKind Mesh::getKind(const ElementType & type) { ElementKind kind = _ek_not_defined; #define GET_KIND(type) \ kind = ElementClass::getKind() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_KIND); #undef GET_KIND return kind; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getSpatialDimension(const ElementType & type) { UInt spatial_dimension = 0; #define GET_SPATIAL_DIMENSION(type) \ spatial_dimension = ElementClass::getSpatialDimension() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_SPATIAL_DIMENSION); #undef GET_SPATIAL_DIMENSION return spatial_dimension; } /* -------------------------------------------------------------------------- */ inline ElementType Mesh::getFacetType(const ElementType & type) { ElementType surface_type = _not_defined; #define GET_FACET_TYPE(type) \ surface_type = ElementClass::getFacetType() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_FACET_TYPE); #undef GET_FACET_TYPE return surface_type; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbFacetsPerElement(const ElementType & type) { AKANTU_DEBUG_IN(); UInt n_facet = 0; #define GET_NB_FACET(type) \ n_facet = ElementClass::getNbFacetsPerElement() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_NB_FACET); #undef GET_NB_FACET AKANTU_DEBUG_OUT(); return n_facet; } /* -------------------------------------------------------------------------- */ inline MatrixProxy Mesh::getFacetLocalConnectivity(const ElementType & type) { AKANTU_DEBUG_IN(); - MatrixProxy mat; - #define GET_FACET_CON(type) \ - mat = ElementClass::getFacetLocalConnectivityPerElement() + AKANTU_DEBUG_OUT(); \ + return ElementClass::getFacetLocalConnectivityPerElement() AKANTU_BOOST_ALL_ELEMENT_SWITCH(GET_FACET_CON); #undef GET_FACET_CON AKANTU_DEBUG_OUT(); - return mat; } /* -------------------------------------------------------------------------- */ inline Matrix Mesh::getFacetConnectivity(UInt element, const ElementType & type, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); Matrix local_facets(getFacetLocalConnectivity(type), false); Matrix facets(local_facets.rows(), local_facets.cols()); const Array & conn = connectivities(type, ghost_type); for (UInt f = 0; f < facets.rows(); ++f) { for (UInt n = 0; n < facets.cols(); ++n) { facets(f, n) = conn(element, local_facets(f, n)); } } AKANTU_DEBUG_OUT(); return facets; } /* -------------------------------------------------------------------------- */ template inline void Mesh::extractNodalValuesFromElement(const Array & nodal_values, T * local_coord, UInt * connectivity, UInt n_nodes, UInt nb_degree_of_freedom) const { for (UInt n = 0; n < n_nodes; ++n) { memcpy(local_coord + n * nb_degree_of_freedom, nodal_values.storage() + connectivity[n] * nb_degree_of_freedom, nb_degree_of_freedom * sizeof(T)); } } /* -------------------------------------------------------------------------- */ inline void Mesh::addConnectivityType(const ElementType & type, const GhostType & ghost_type){ getConnectivityPointer(type, ghost_type); } /* -------------------------------------------------------------------------- */ inline bool Mesh::isPureGhostNode(UInt n) const { return nodes_type.getSize() ? (nodes_type(n) == -3) : false; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isLocalOrMasterNode(UInt n) const { return nodes_type.getSize() ? (nodes_type(n) == -2) || (nodes_type(n) == -1) : true; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isLocalNode(UInt n) const { return nodes_type.getSize() ? nodes_type(n) == -1 : true; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isMasterNode(UInt n) const { return nodes_type.getSize() ? nodes_type(n) == -2 : false; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isSlaveNode(UInt n) const { return nodes_type.getSize() ? nodes_type(n) >= 0 : false; } /* -------------------------------------------------------------------------- */ inline Int Mesh::getNodeType(UInt local_id) const { return nodes_type.getSize() ? nodes_type(local_id) : -1; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNodeGlobalId(UInt local_id) const { return nodes_global_ids ? (*nodes_global_ids)(local_id) : local_id; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbGlobalNodes() const { return nodes_global_ids ? nb_global_nodes : nodes->getSize(); } /* -------------------------------------------------------------------------- */ __END_AKANTU__ #endif /* __AKANTU_MESH_INLINE_IMPL_CC__ */ 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 * * @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 . * */ /* -------------------------------------------------------------------------- */ #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::const_iterator 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 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 &); AKANTU_GET_MACRO(Nodes, node_group, const Array &); 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 & 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/heat_transfer/heat_transfer_model.cc b/src/model/heat_transfer/heat_transfer_model.cc index 2fda3f8d2..b999becfb 100644 --- a/src/model/heat_transfer/heat_transfer_model.cc +++ b/src/model/heat_transfer/heat_transfer_model.cc @@ -1,952 +1,986 @@ /** * @file heat_transfer_model.cc * * @author Guillaume Anciaux * @author Lucas Frerot * @author Srinivasa Babu Ramisetti * @author David Simon Kammer * @author Nicolas Richart * @author Rui Wang * * @date creation: Sun May 01 2011 * @date last modification: Mon Sep 15 2014 * * @brief Implementation of HeatTransferModel 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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "heat_transfer_model.hh" #include "group_manager_inline_impl.cc" #include "dumpable_inline_impl.hh" #include "aka_math.hh" #include "aka_common.hh" #include "fe_engine_template.hh" #include "mesh.hh" #include "static_communicator.hh" #include "parser.hh" #include "generalized_trapezoidal.hh" #ifdef AKANTU_USE_MUMPS #include "solver_mumps.hh" #endif #ifdef AKANTU_USE_IOHELPER # include "dumper_paraview.hh" # include "dumper_elemental_field.hh" # include "dumper_element_partition.hh" # include "dumper_material_internal_field.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ const HeatTransferModelOptions default_heat_transfer_model_options(_explicit_lumped_capacity); /* -------------------------------------------------------------------------- */ HeatTransferModel::HeatTransferModel(Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id) : Model(mesh, dim, id, memory_id), Parsable(_st_heat, id), integrator(new ForwardEuler()), stiffness_matrix(NULL), jacobian_matrix(NULL), temperature_gradient ("temperature_gradient", id), temperature_on_qpoints ("temperature_on_qpoints", id), conductivity_on_qpoints ("conductivity_on_qpoints", id), k_gradt_on_qpoints ("k_gradt_on_qpoints", id), int_bt_k_gT ("int_bt_k_gT", id), bt_k_gT ("bt_k_gT", id), conductivity(spatial_dimension, spatial_dimension), thermal_energy ("thermal_energy", id) { AKANTU_DEBUG_IN(); createSynchronizerRegistry(this); std::stringstream sstr; sstr << id << ":fem"; registerFEEngineObject(sstr.str(), mesh,spatial_dimension); this->temperature= NULL; this->residual = NULL; this->blocked_dofs = NULL; #ifdef AKANTU_USE_IOHELPER this->mesh.registerDumper("paraview_all", id, true); this->mesh.addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_regular); #endif this->registerParam("conductivity" , conductivity , _pat_parsmod); this->registerParam("conductivity_variation", conductivity_variation, 0., _pat_parsmod); this->registerParam("temperature_reference" , T_ref , 0., _pat_parsmod); this->registerParam("capacity" , capacity , _pat_parsmod); this->registerParam("density" , density , _pat_parsmod); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initModel() { getFEEngine().initShapeFunctions(_not_ghost); getFEEngine().initShapeFunctions(_ghost); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initParallel(MeshPartition * partition, DataAccessor * data_accessor) { AKANTU_DEBUG_IN(); if (data_accessor == NULL) data_accessor = this; Synchronizer & synch_parallel = createParallelSynch(partition,data_accessor); synch_registry->registerSynchronizer(synch_parallel, _gst_htm_capacity); synch_registry->registerSynchronizer(synch_parallel, _gst_htm_temperature); synch_registry->registerSynchronizer(synch_parallel, _gst_htm_gradient_temperature); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initPBC() { AKANTU_DEBUG_IN(); Model::initPBC(); PBCSynchronizer * synch = new PBCSynchronizer(pbc_pair); synch_registry->registerSynchronizer(*synch, _gst_htm_capacity); synch_registry->registerSynchronizer(*synch, _gst_htm_temperature); changeLocalEquationNumberForPBC(pbc_pair,1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initArrays() { AKANTU_DEBUG_IN(); UInt nb_nodes = getFEEngine().getMesh().getNbNodes(); std::stringstream sstr_temp; sstr_temp << Model::id << ":temperature"; std::stringstream sstr_temp_rate; sstr_temp_rate << Model::id << ":temperature_rate"; std::stringstream sstr_inc; sstr_inc << Model::id << ":increment"; std::stringstream sstr_ext_flx; sstr_ext_flx << Model::id << ":external_flux"; std::stringstream sstr_residual; sstr_residual << Model::id << ":residual"; std::stringstream sstr_lump; sstr_lump << Model::id << ":lumped"; std::stringstream sstr_boun; sstr_boun << Model::id << ":blocked_dofs"; temperature = &(alloc(sstr_temp.str(), nb_nodes, 1, REAL_INIT_VALUE)); temperature_rate = &(alloc(sstr_temp_rate.str(), nb_nodes, 1, REAL_INIT_VALUE)); increment = &(alloc(sstr_inc.str(), nb_nodes, 1, REAL_INIT_VALUE)); external_heat_rate = &(alloc(sstr_ext_flx.str(), nb_nodes, 1, REAL_INIT_VALUE)); residual = &(alloc(sstr_residual.str(), nb_nodes, 1, REAL_INIT_VALUE)); capacity_lumped = &(alloc(sstr_lump.str(), nb_nodes, 1, REAL_INIT_VALUE)); blocked_dofs = &(alloc(sstr_boun.str(), nb_nodes, 1, false)); Mesh::ConnectivityTypeList::const_iterator it; /* -------------------------------------------------------------------------- */ // byelementtype vectors getFEEngine().getMesh().initElementTypeMapArray(temperature_on_qpoints, - 1, - spatial_dimension); + 1, + spatial_dimension); getFEEngine().getMesh().initElementTypeMapArray(temperature_gradient, - spatial_dimension, - spatial_dimension); + spatial_dimension, + spatial_dimension); getFEEngine().getMesh().initElementTypeMapArray(conductivity_on_qpoints, - spatial_dimension*spatial_dimension, - spatial_dimension); + spatial_dimension*spatial_dimension, + spatial_dimension); getFEEngine().getMesh().initElementTypeMapArray(k_gradt_on_qpoints, - spatial_dimension, - spatial_dimension); + spatial_dimension, + spatial_dimension); getFEEngine().getMesh().initElementTypeMapArray(bt_k_gT, - 1, - spatial_dimension,true); + 1, + spatial_dimension, + true); getFEEngine().getMesh().initElementTypeMapArray(int_bt_k_gT, - 1, - spatial_dimension,true); + 1, + spatial_dimension, + true); getFEEngine().getMesh().initElementTypeMapArray(thermal_energy, 1, spatial_dimension); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; const Mesh::ConnectivityTypeList & type_list = getFEEngine().getMesh().getConnectivityTypeList(gt); for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_element = getFEEngine().getMesh().getNbElement(*it, gt); UInt nb_quad_points = this->getFEEngine().getNbQuadraturePoints(*it, gt) * nb_element; temperature_on_qpoints(*it, gt).resize(nb_quad_points); temperature_on_qpoints(*it, gt).clear(); temperature_gradient(*it, gt).resize(nb_quad_points); temperature_gradient(*it, gt).clear(); conductivity_on_qpoints(*it, gt).resize(nb_quad_points); conductivity_on_qpoints(*it, gt).clear(); k_gradt_on_qpoints(*it, gt).resize(nb_quad_points); k_gradt_on_qpoints(*it, gt).clear(); bt_k_gT(*it, gt).resize(nb_quad_points); bt_k_gT(*it, gt).clear(); int_bt_k_gT(*it, gt).resize(nb_element); int_bt_k_gT(*it, gt).clear(); thermal_energy(*it, gt).resize(nb_element); thermal_energy(*it, gt).clear(); } } /* -------------------------------------------------------------------------- */ dof_synchronizer = new DOFSynchronizer(getFEEngine().getMesh(),1); dof_synchronizer->initLocalDOFEquationNumbers(); dof_synchronizer->initGlobalDOFEquationNumbers(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initSolver(__attribute__((unused)) SolverOptions & options) { #if !defined(AKANTU_USE_MUMPS) // or other solver in the future \todo add AKANTU_HAS_SOLVER in CMake AKANTU_DEBUG_ERROR("You should at least activate one solver."); #else UInt nb_global_nodes = mesh.getNbGlobalNodes(); delete jacobian_matrix; std::stringstream sstr; sstr << Memory::id << ":jacobian_matrix"; jacobian_matrix = new SparseMatrix(nb_global_nodes, _symmetric, sstr.str(), memory_id); jacobian_matrix->buildProfile(mesh, *dof_synchronizer, 1); delete stiffness_matrix; std::stringstream sstr_sti; sstr_sti << Memory::id << ":stiffness_matrix"; stiffness_matrix = new SparseMatrix(*jacobian_matrix, sstr_sti.str(), memory_id); #ifdef AKANTU_USE_MUMPS std::stringstream sstr_solv; sstr_solv << Memory::id << ":solver"; solver = new SolverMumps(*jacobian_matrix, sstr_solv.str()); dof_synchronizer->initScatterGatherCommunicationScheme(); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif //AKANTU_USE_MUMPS if(solver) solver->initialize(options); #endif //AKANTU_HAS_SOLVER } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initImplicit(SolverOptions & solver_options) { method = _static; initSolver(solver_options); } /* -------------------------------------------------------------------------- */ HeatTransferModel::~HeatTransferModel() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::assembleCapacityLumped(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); FEEngine & fem = getFEEngine(); const Mesh::ConnectivityTypeList & type_list = fem.getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_element = getFEEngine().getMesh().getNbElement(*it,ghost_type); UInt nb_quadrature_points = getFEEngine().getNbQuadraturePoints(*it, ghost_type); Array rho_1 (nb_element * nb_quadrature_points,1, capacity * density); fem.assembleFieldLumped(rho_1,1,*capacity_lumped, dof_synchronizer->getLocalDOFEquationNumbers(), *it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::assembleCapacityLumped() { AKANTU_DEBUG_IN(); capacity_lumped->clear(); assembleCapacityLumped(_not_ghost); assembleCapacityLumped(_ghost); getSynchronizerRegistry().synchronize(_gst_htm_capacity); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::updateResidual() { AKANTU_DEBUG_IN(); /// @f$ r = q_{ext} - q_{int} - C \dot T @f$ // start synchronization synch_registry->asynchronousSynchronize(_gst_htm_temperature); // finalize communications synch_registry->waitEndSynchronize(_gst_htm_temperature); //clear the array /// first @f$ r = q_{ext} @f$ // residual->clear(); residual->copy(*external_heat_rate); /// then @f$ r -= q_{int} @f$ // update the not ghost ones updateResidual(_not_ghost); // update for the received ghosts updateResidual(_ghost); /* if (method == _explicit_lumped_capacity) { this->solveExplicitLumped(); }*/ AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::assembleStiffnessMatrix() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the new stiffness matrix."); stiffness_matrix->clear(); switch(mesh.getSpatialDimension()) { case 1: this->assembleStiffnessMatrix<1>(_not_ghost); break; case 2: this->assembleStiffnessMatrix<2>(_not_ghost); break; case 3: this->assembleStiffnessMatrix<3>(_not_ghost); break; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void HeatTransferModel::assembleStiffnessMatrix(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Mesh & mesh = this->getFEEngine().getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension, ghost_type); for(; it != last_type; ++it) { this->assembleStiffnessMatrix(*it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void HeatTransferModel::assembleStiffnessMatrix(const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); SparseMatrix & K = *stiffness_matrix; const Array & shapes_derivatives = this->getFEEngine().getShapesDerivatives(type, ghost_type); UInt nb_element = mesh.getNbElement(type, ghost_type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = getFEEngine().getNbQuadraturePoints(type, ghost_type); /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_d_b_size = nb_nodes_per_element; Array * bt_d_b = new Array(nb_element * nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B"); Matrix Bt_D(nb_nodes_per_element, dim); Array::const_iterator< Matrix > shapes_derivatives_it = shapes_derivatives.begin(dim, nb_nodes_per_element); Array::iterator< Matrix > Bt_D_B_it = bt_d_b->begin(bt_d_b_size, bt_d_b_size); this->computeConductivityOnQuadPoints(ghost_type); Array::iterator< Matrix > D_it = conductivity_on_qpoints(type, ghost_type).begin(dim, dim); Array::iterator< Matrix > D_end = conductivity_on_qpoints(type, ghost_type).end(dim, dim); for (; D_it != D_end; ++D_it, ++Bt_D_B_it, ++shapes_derivatives_it) { Matrix & D = *D_it; const Matrix & B = *shapes_derivatives_it; Matrix & Bt_D_B = *Bt_D_B_it; Bt_D.mul(B, D); Bt_D_B.mul(Bt_D, B); } /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array * K_e = new Array(nb_element, bt_d_b_size * bt_d_b_size, "K_e"); this->getFEEngine().integrate(*bt_d_b, *K_e, bt_d_b_size * bt_d_b_size, type, ghost_type); delete bt_d_b; this->getFEEngine().assembleMatrix(*K_e, K, 1, type, ghost_type); delete K_e; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::solveStatic() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving Ku = f"); AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, "You should first initialize the implicit solver and assemble the stiffness matrix"); UInt nb_nodes = temperature->getSize(); UInt nb_degree_of_freedom = temperature->getNbComponent() * nb_nodes; jacobian_matrix->copyContent(*stiffness_matrix); jacobian_matrix->applyBoundary(*blocked_dofs); increment->clear(); solver->setRHS(*residual); solver->factorize(); solver->solve(*increment); Real * increment_val = increment->storage(); Real * temperature_val = temperature->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++temperature_val, ++increment_val, ++blocked_dofs_val) { if (!(*blocked_dofs_val)) { *temperature_val += *increment_val; } else { *increment_val = 0.0; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::computeConductivityOnQuadPoints(const GhostType & ghost_type) { const Mesh::ConnectivityTypeList & type_list = this->getFEEngine().getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; Array & temperature_interpolated = temperature_on_qpoints(*it, ghost_type); //compute the temperature on quadrature points this->getFEEngine().interpolateOnQuadraturePoints(*temperature, temperature_interpolated, 1 ,*it,ghost_type); Array::matrix_iterator C_it = conductivity_on_qpoints(*it, ghost_type).begin(spatial_dimension, spatial_dimension); Array::matrix_iterator C_end = conductivity_on_qpoints(*it, ghost_type).end(spatial_dimension, spatial_dimension); Array::iterator T_it = temperature_interpolated.begin(); for (;C_it != C_end; ++C_it, ++T_it) { Matrix & C = *C_it; Real & T = *T_it; C = conductivity; Matrix variation(spatial_dimension, spatial_dimension, conductivity_variation * (T - T_ref)); C += conductivity_variation; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::computeKgradT(const GhostType & ghost_type) { computeConductivityOnQuadPoints(ghost_type); const Mesh::ConnectivityTypeList & type_list = this->getFEEngine().getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { const ElementType & type = *it; if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; Array & gradient = temperature_gradient(*it, ghost_type); this->getFEEngine().gradientOnQuadraturePoints(*temperature, gradient, 1 ,*it, ghost_type); Array::matrix_iterator C_it = conductivity_on_qpoints(*it, ghost_type).begin(spatial_dimension, spatial_dimension); Array::vector_iterator BT_it = gradient.begin(spatial_dimension); Array::vector_iterator k_BT_it = k_gradt_on_qpoints(type, ghost_type).begin(spatial_dimension); Array::vector_iterator k_BT_end = k_gradt_on_qpoints(type, ghost_type).end(spatial_dimension); for (;k_BT_it != k_BT_end; ++k_BT_it, ++BT_it, ++C_it) { Vector & k_BT = *k_BT_it; Vector & BT = *BT_it; Matrix & C = *C_it; k_BT.mul(C, BT); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::updateResidual(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); const Mesh::ConnectivityTypeList & type_list = this->getFEEngine().getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; Array & shapes_derivatives = const_cast &>(getFEEngine().getShapesDerivatives(*it,ghost_type)); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); // compute k \grad T computeKgradT(ghost_type); Array::vector_iterator k_BT_it = k_gradt_on_qpoints(*it,ghost_type).begin(spatial_dimension); Array::matrix_iterator B_it = shapes_derivatives.begin(spatial_dimension, nb_nodes_per_element); Array::vector_iterator Bt_k_BT_it = bt_k_gT(*it,ghost_type).begin(nb_nodes_per_element); Array::vector_iterator Bt_k_BT_end = bt_k_gT(*it,ghost_type).end(nb_nodes_per_element); for (;Bt_k_BT_it != Bt_k_BT_end; ++Bt_k_BT_it, ++B_it, ++k_BT_it) { Vector & k_BT = *k_BT_it; Vector & Bt_k_BT = *Bt_k_BT_it; Matrix & B = *B_it; Bt_k_BT.mul(B, k_BT); } this->getFEEngine().integrate(bt_k_gT(*it,ghost_type), int_bt_k_gT(*it,ghost_type), nb_nodes_per_element, *it,ghost_type); this->getFEEngine().assembleArray(int_bt_k_gT(*it,ghost_type), *residual, dof_synchronizer->getLocalDOFEquationNumbers(), 1, *it,ghost_type, empty_filter, -1); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::solveExplicitLumped() { AKANTU_DEBUG_IN(); /// finally @f$ r -= C \dot T @f$ // lumped C UInt nb_nodes = temperature_rate->getSize(); UInt nb_degree_of_freedom = temperature_rate->getNbComponent(); Real * capacity_val = capacity_lumped->storage(); Real * temp_rate_val = temperature_rate->storage(); Real * res_val = residual->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { if(!(*blocked_dofs_val)) { *res_val -= *capacity_val * *temp_rate_val; } blocked_dofs_val++; res_val++; capacity_val++; temp_rate_val++; } #ifndef AKANTU_NDEBUG getSynchronizerRegistry().synchronize(akantu::_gst_htm_gradient_temperature); #endif capacity_val = capacity_lumped->storage(); res_val = residual->storage(); blocked_dofs_val = blocked_dofs->storage(); Real * inc = increment->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { if(!(*blocked_dofs_val)) { *inc = (*res_val / *capacity_val); } res_val++; blocked_dofs_val++; inc++; capacity_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::explicitPred() { AKANTU_DEBUG_IN(); integrator->integrationSchemePred(time_step, *temperature, *temperature_rate, *blocked_dofs); UInt nb_nodes = temperature->getSize(); UInt nb_degree_of_freedom = temperature->getNbComponent(); Real * temp = temperature->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n, ++temp) if(*temp < 0.) *temp = 0.; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::explicitCorr() { AKANTU_DEBUG_IN(); integrator->integrationSchemeCorrTempRate(time_step, *temperature, *temperature_rate, *blocked_dofs, *increment); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getStableTimeStep() { AKANTU_DEBUG_IN(); Real el_size; Real min_el_size = std::numeric_limits::max(); Real conductivitymax = conductivity(0, 0); //get the biggest parameter from k11 until k33// for(UInt i = 0; i < spatial_dimension; i++) for(UInt j = 0; j < spatial_dimension; j++) conductivitymax = std::max(conductivity(i, j), conductivitymax); const Mesh::ConnectivityTypeList & type_list = getFEEngine().getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(getFEEngine().getMesh().getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_nodes_per_element = getFEEngine().getMesh().getNbNodesPerElement(*it); Array coord(0, nb_nodes_per_element*spatial_dimension); FEEngine::extractNodalToElementField(getFEEngine().getMesh(), getFEEngine().getMesh().getNodes(), coord, *it, _not_ghost); Array::matrix_iterator el_coord = coord.begin(spatial_dimension, nb_nodes_per_element); UInt nb_element = getFEEngine().getMesh().getNbElement(*it); for (UInt el = 0; el < nb_element; ++el, ++el_coord) { el_size = getFEEngine().getElementInradius(*el_coord, *it); min_el_size = std::min(min_el_size, el_size); } AKANTU_DEBUG_INFO("The minimum element size : " << min_el_size << " and the max conductivity is : " << conductivitymax); } Real min_dt = 2 * min_el_size * min_el_size * density * capacity / conductivitymax; StaticCommunicator::getStaticCommunicator().allReduce(&min_dt, 1, _so_min); AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ void HeatTransferModel::readMaterials() { std::pair sub_sect = this->parser->getSubSections(_st_heat); Parser::const_section_iterator it = sub_sect.first; const ParserSection & section = *it; this->parseSection(section); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initFull(const ModelOptions & options){ Model::initFull(options); readMaterials(); const HeatTransferModelOptions & my_options = dynamic_cast(options); //initialize the vectors initArrays(); temperature->clear(); temperature_rate->clear(); external_heat_rate->clear(); method = my_options.analysis_method; if (method == _static) { initImplicit(); } } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initFEEngineBoundary(bool create_surface) { if(create_surface) MeshUtils::buildFacets(getFEEngine().getMesh()); FEEngine & fem_boundary = getFEEngineBoundary(); fem_boundary.initShapeFunctions(); fem_boundary.computeNormalsOnControlPoints(); } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::computeThermalEnergyByNode() { AKANTU_DEBUG_IN(); Real ethermal = 0.; Array::vector_iterator heat_rate_it = residual->begin(residual->getNbComponent()); Array::vector_iterator heat_rate_end = residual->end(residual->getNbComponent()); UInt n = 0; for(;heat_rate_it != heat_rate_end; ++heat_rate_it, ++n) { Real heat = 0; bool is_local_node = mesh.isLocalOrMasterNode(n); bool is_not_pbc_slave_node = !isPBCSlaveNode(n); bool count_node = is_local_node && is_not_pbc_slave_node; Vector & heat_rate = *heat_rate_it; for (UInt i = 0; i < heat_rate.size(); ++i) { if (count_node) heat += heat_rate[i] * time_step; } ethermal += heat; } StaticCommunicator::getStaticCommunicator().allReduce(ðermal, 1, _so_sum); AKANTU_DEBUG_OUT(); return ethermal; } /* -------------------------------------------------------------------------- */ template void HeatTransferModel::getThermalEnergy(iterator Eth, Array::const_iterator T_it, Array::const_iterator T_end) const { for(;T_it != T_end; ++T_it, ++Eth) { *Eth = capacity * density * *T_it; } } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getThermalEnergy(const ElementType & type, UInt index) { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = getFEEngine().getNbQuadraturePoints(type); Vector Eth_on_quarature_points(nb_quadrature_points); Array::iterator T_it = this->temperature_on_qpoints(type).begin(); T_it += index * nb_quadrature_points; Array::iterator T_end = T_it + nb_quadrature_points; getThermalEnergy(Eth_on_quarature_points.storage(), T_it, T_end); return getFEEngine().integrate(Eth_on_quarature_points, type, index); } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getThermalEnergy() { Real Eth = 0; Mesh & mesh = getFEEngine().getMesh(); Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator last_type = mesh.lastType(spatial_dimension); for(; it != last_type; ++it) { UInt nb_element = getFEEngine().getMesh().getNbElement(*it, _not_ghost); UInt nb_quadrature_points = getFEEngine().getNbQuadraturePoints(*it, _not_ghost); Array Eth_per_quad(nb_element * nb_quadrature_points, 1); Array::iterator T_it = this->temperature_on_qpoints(*it).begin(); Array::iterator T_end = this->temperature_on_qpoints(*it).end(); getThermalEnergy(Eth_per_quad.begin(), T_it, T_end); Eth += getFEEngine().integrate(Eth_per_quad, *it); } return Eth; } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getEnergy(const std::string & id) { AKANTU_DEBUG_IN(); Real energy = 0; if("thermal") energy = getThermalEnergy(); // reduction sum over all processors StaticCommunicator::getStaticCommunicator().allReduce(&energy, 1, _so_sum); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getEnergy(const std::string & energy_id, const ElementType & type, UInt index) { AKANTU_DEBUG_IN(); Real energy = 0.; if("thermal") energy = getThermalEnergy(type, index); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +#ifdef AKANTU_USE_IOHELPER + dumper::Field * HeatTransferModel::createNodalFieldBool(const std::string & field_name, const std::string & group_name, bool padding_flag) { std::map* > uint_nodal_fields; uint_nodal_fields["blocked_dofs" ] = blocked_dofs; dumper::Field * field = NULL; field = mesh.createNodalField(uint_nodal_fields[field_name],group_name); return field; } /* -------------------------------------------------------------------------- */ dumper::Field * HeatTransferModel::createNodalFieldReal(const std::string & field_name, const std::string & group_name, bool padding_flag) { std::map* > real_nodal_fields; real_nodal_fields["temperature" ] = temperature; real_nodal_fields["temperature_rate" ] = temperature_rate; real_nodal_fields["external_heat_rate" ] = external_heat_rate; real_nodal_fields["residual" ] = residual; real_nodal_fields["capacity_lumped" ] = capacity_lumped; dumper::Field * field = mesh.createNodalField(real_nodal_fields[field_name],group_name); return field; } + /* -------------------------------------------------------------------------- */ + dumper::Field * HeatTransferModel ::createElementalField(const std::string & field_name, const std::string & group_name, bool padding_flag, const ElementKind & element_kind){ dumper::Field * field = NULL; if(field_name == "partitions") field = mesh.createElementalField(mesh.getConnectivities(),group_name,this->spatial_dimension,element_kind); else if(field_name == "temperature_gradient"){ ElementTypeMap nb_data_per_elem = this->mesh.getNbDataPerElem(temperature_gradient,element_kind); field = mesh.createElementalField(temperature_gradient, group_name, this->spatial_dimension, element_kind, nb_data_per_elem); } return field; } +/* -------------------------------------------------------------------------- */ +#else +/* -------------------------------------------------------------------------- */ +dumper::Field * HeatTransferModel +::createElementalField(const std::string & field_name, + const std::string & group_name, + bool padding_flag, + const ElementKind & element_kind){ + + return NULL; +} + +/* -------------------------------------------------------------------------- */ + +dumper::Field * HeatTransferModel::createNodalFieldBool(const std::string & field_name, + const std::string & group_name, + bool padding_flag) { + + return NULL; +} /* -------------------------------------------------------------------------- */ - - + +dumper::Field * HeatTransferModel::createNodalFieldReal(const std::string & field_name, + const std::string & group_name, + bool padding_flag) { + + return NULL; +} + +#endif __END_AKANTU__ diff --git a/src/model/solid_mechanics/embedded_interface_model.cc b/src/model/solid_mechanics/embedded_interface_model.cc index 4151d82f8..5298792b8 100644 --- a/src/model/solid_mechanics/embedded_interface_model.cc +++ b/src/model/solid_mechanics/embedded_interface_model.cc @@ -1,183 +1,185 @@ /** * @file embedded_interface_model.cc * * @author Lucas Frérot * * @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 . * */ /* -------------------------------------------------------------------------- */ #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); + EmbeddedInterfaceModel::EmbeddedInterfaceModel(Mesh & mesh, Mesh & primitive_mesh, UInt spatial_dimension, const ID & id, const MemoryID & memory_id) : SolidMechanicsModel(mesh, spatial_dimension, id, memory_id), interface_mesh(NULL), primitive_mesh(primitive_mesh), interface_material_selector(NULL), intersector(mesh, primitive_mesh) { // This pointer should be deleted by ~SolidMechanicsModel() MaterialSelector * mat_sel_pointer = new MeshDataMaterialSelector("physical_names", *this); this->setMaterialSelector(*mat_sel_pointer); } EmbeddedInterfaceModel::~EmbeddedInterfaceModel() { delete interface_material_selector; } void EmbeddedInterfaceModel::initFull(const ModelOptions & options) { const EmbeddedInterfaceModelOptions & eim_options = dynamic_cast(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("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); this->initMaterials(); #if defined(AKANTU_USE_IOHELPER) this->mesh.registerDumper("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("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 & 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 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 *>(materials[m]); break; case 2: mat = dynamic_cast *>(materials[m]); break; case 3: mat = dynamic_cast *>(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(); } 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 (field_id == "stress_embedded" || field_id == "inelastic_strain") 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/material.hh b/src/model/solid_mechanics/material.hh index ef9f67ef4..c3e3dffb5 100644 --- a/src/model/solid_mechanics/material.hh +++ b/src/model/solid_mechanics/material.hh @@ -1,600 +1,600 @@ /** * @file material.hh * * @author Marco Vocialta * @author Nicolas Richart * @author Daniel Pino Muñoz * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Sep 16 2014 * * @brief Mother class for all materials * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "aka_voigthelper.hh" #include "parser.hh" #include "parsable.hh" #include "data_accessor.hh" #include "internal_field.hh" #include "random_internal_field.hh" #include "solid_mechanics_model_event_handler.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_HH__ #define __AKANTU_MATERIAL_HH__ /* -------------------------------------------------------------------------- */ namespace akantu { class Model; class SolidMechanicsModel; } __BEGIN_AKANTU__ /** * Interface of all materials * Prerequisites for a new material * - inherit from this class * - implement the following methods: * \code * virtual Real getStableTimeStep(Real h, const Element & element = ElementNull); * * virtual void computeStress(ElementType el_type, * GhostType ghost_type = _not_ghost); * * virtual void computeTangentStiffness(const ElementType & el_type, * Array & tangent_matrix, * GhostType ghost_type = _not_ghost); * \endcode * */ class Material : public Memory, public DataAccessor, public Parsable, public MeshEventHandler, protected SolidMechanicsModelEventHandler { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Material(SolidMechanicsModel & model, const ID & id = ""); virtual ~Material(); /* ------------------------------------------------------------------------ */ /* Function that materials can/should reimplement */ /* ------------------------------------------------------------------------ */ protected: /// constitutive law virtual void computeStress(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the tangent stiffness matrix virtual void computeTangentModuli(__attribute__((unused)) const ElementType & el_type, __attribute__((unused)) Array & tangent_matrix, __attribute__((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the potential energy virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the potential energy for an element virtual void computePotentialEnergyByElement(__attribute__((unused)) ElementType type, __attribute__((unused)) UInt index, __attribute__((unused)) Vector & epot_on_quad_points) { AKANTU_DEBUG_TO_IMPLEMENT(); } virtual void updateEnergies(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) { } virtual void updateEnergiesAfterDamage(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) {} /// set the material to steady state (to be implemented for materials that need it) virtual void setToSteadyState(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost) { } /// function called to update the internal parameters when the modifiable /// parameters are modified virtual void updateInternalParameters() {} public: /// compute the p-wave speed in the material virtual Real getPushWaveSpeed(const Element & element) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// compute the s-wave speed in the material virtual Real getShearWaveSpeed(const Element & element) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// get a material celerity to compute the stable time step (default: is the push wave speed) virtual Real getCelerity(const Element & element) const { return getPushWaveSpeed(element); } /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: template void registerInternal(__attribute__((unused)) InternalField & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); } template void unregisterInternal(__attribute__((unused)) InternalField & vect) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// initialize the material computed parameter virtual void initMaterial(); /// compute the residual for this material virtual void updateResidual(GhostType ghost_type = _not_ghost); /// assemble the residual for this material virtual void assembleResidual(GhostType ghost_type); /// Operations before and after solveStep in implicit virtual void beforeSolveStep() {} virtual void afterSolveStep() {} /// save the stress in the previous_stress if needed virtual void savePreviousState(); /// compute the stresses for this material virtual void computeAllStresses(GhostType ghost_type = _not_ghost); virtual void computeAllNonLocalStresses(__attribute__((unused)) GhostType ghost_type = _not_ghost) {}; virtual void computeAllStressesFromTangentModuli(GhostType ghost_type = _not_ghost); virtual void computeAllCauchyStresses(GhostType ghost_type = _not_ghost); /// set material to steady state void setToSteadyState(GhostType ghost_type = _not_ghost); /// compute the stiffness matrix virtual void assembleStiffnessMatrix(GhostType ghost_type); /// add an element to the local mesh filter inline UInt addElement(const ElementType & type, UInt element, const GhostType & ghost_type); /// add many elements at once void addElements(const Array & elements_to_add); /// remove many element at once void removeElements(const Array & elements_to_remove); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const; /** * interpolate stress on given positions for each element by means * of a geometrical interpolation on quadrature points */ void interpolateStress(ElementTypeMapArray & result, const GhostType ghost_type = _not_ghost); /** * interpolate stress on given positions for each element by means * of a geometrical interpolation on quadrature points and store the * results per facet */ void interpolateStressOnFacets(ElementTypeMapArray & result, const GhostType ghost_type = _not_ghost); /** * function to initialize the elemental field interpolation * function by inverting the quadrature points' coordinates */ void initElementalFieldInterpolation(const ElementTypeMapArray & interpolation_points_coordinates); /* ------------------------------------------------------------------------ */ /* Common part */ /* ------------------------------------------------------------------------ */ protected: /// assemble the residual template void assembleResidual(GhostType ghost_type); /// Computation of Cauchy stress tensor in the case of finite deformation template void computeCauchyStress(__attribute__((unused)) ElementType el_type, __attribute__((unused)) GhostType ghost_type = _not_ghost); template inline void computeCauchyStressOnQuad(const Matrix & F, const Matrix & S, Matrix & cauchy, const Real & C33 = 1.0 ) const; template void computeAllStressesFromTangentModuli(const ElementType & type, GhostType ghost_type); template void assembleStiffnessMatrix(const ElementType & type, GhostType ghost_type); /// assembling in finite deformation template void assembleStiffnessMatrixNL(const ElementType & type, GhostType ghost_type); template void assembleStiffnessMatrixL2(const ElementType & type, GhostType ghost_type); /// write the stress tensor in the Voigt notation. template inline void SetCauchyStressArray(const Matrix & S_t, Matrix & 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 inline void setCauchyStressMatrix(const Matrix & S_t, Matrix & Stress_matrix); /// compute the potential energy by element void computePotentialEnergyByElements(); /// resize the intenals arrays - void resizeInternals(); + virtual void resizeInternals(); public: /// compute the coordinates of the quadrature points void computeQuadraturePointsCoordinates(ElementTypeMapArray & quadrature_points_coordinates, const GhostType & ghost_type) const; protected: /// interpolate an elemental field on given points for each element void interpolateElementalField(const ElementTypeMapArray & field, ElementTypeMapArray & result, const GhostType ghost_type); /// interpolate an elemental field and store the results per facet void interpolateElementalFieldOnFacets(const ElementTypeMapArray & field, ElementTypeMapArray & result, const GhostType ghost_type); /// template function to initialize the elemental field interpolation template void initElementalFieldInterpolation(const Array & quad_coordinates, const Array & 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 inline void buildElementalFieldInterpolationCoodinates(const Matrix & coordinates, Matrix & coordMatrix); /// build interpolation coordinates for basic linear elements inline void buildElementalFieldInterpolationCoodinatesLinear(const Matrix & coordinates, Matrix & coordMatrix); /// build interpolation coordinates for basic quadratic elements inline void buildElementalFieldInterpolationCoodinatesQuadratic(const Matrix & coordinates, Matrix & coordMatrix); public: /* ------------------------------------------------------------------------ */ /* Conversion functions */ /* ------------------------------------------------------------------------ */ template static inline void gradUToF (const Matrix & grad_u, Matrix & F); static inline void rightCauchy(const Matrix & F, Matrix & C); static inline void leftCauchy (const Matrix & F, Matrix & B); template static inline void gradUToEpsilon(const Matrix & grad_u, Matrix & epsilon); template static inline void gradUToGreenStrain(const Matrix & grad_u, Matrix & epsilon); static inline Real stressToVonMises(const Matrix & stress); protected: /// converts global element to local element inline Element convertToLocalElement(const Element & global_element) const; /// converts local element to global element inline Element convertToGlobalElement(const Element & local_element) const; /// converts global quadrature point to local quadrature point inline 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 & elements, SynchronizationTag tag) const; virtual inline void packElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag) const; virtual inline void unpackElementData(CommunicationBuffer & buffer, const Array & elements, SynchronizationTag tag); template inline void packElementDataHelper(const ElementTypeMapArray & data_to_pack, CommunicationBuffer & buffer, const Array & elements, const ID & fem_id = ID()) const; template inline void unpackElementDataHelper(ElementTypeMapArray & data_to_unpack, CommunicationBuffer & buffer, const Array & elements, const ID & fem_id = ID()); /* ------------------------------------------------------------------------ */ /* MeshEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ virtual void onElementsAdded(const Array & element_list, const NewElementsEvent & event); virtual void onElementsRemoved(const Array & element_list, const ElementTypeMapArray & new_numbering, const RemovedElementsEvent & event); /* ------------------------------------------------------------------------ */ /* SolidMechanicsModelEventHandler inherited members */ /* ------------------------------------------------------------------------ */ public: virtual void onBeginningSolveStep(const AnalysisMethod & method); virtual void onEndSolveStep(const AnalysisMethod & method); virtual void onDamageIteration(); virtual void onDamageUpdate(); virtual void onDump(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(Model, *model, const SolidMechanicsModel &) AKANTU_GET_MACRO(ID, Memory::getID(), const ID &); AKANTU_GET_MACRO(Rho, rho, Real); AKANTU_SET_MACRO(Rho, rho, Real); /// return the potential energy for the subset of elements contained by the material Real getPotentialEnergy(); /// return the potential energy for the provided element Real getPotentialEnergy(ElementType & type, UInt index); /// return the energy (identified by id) for the subset of elements contained by the material virtual Real getEnergy(std::string energy_id); /// return the energy (identified by id) for the provided element virtual Real getEnergy(std::string energy_id, ElementType type, UInt index); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, UInt); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(GradU, gradu, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real); AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PotentialEnergy, potential_energy, Real); AKANTU_GET_MACRO(GradU, gradu, const ElementTypeMapArray &); AKANTU_GET_MACRO(Stress, stress, const ElementTypeMapArray &); AKANTU_GET_MACRO(ElementFilter, element_filter, const ElementTypeMapArray &); bool isNonLocal() const { return is_non_local; } const Array & getArray(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost) const; Array & getArray(const ID & id, const ElementType & type, const GhostType & ghost_type = _not_ghost); const InternalField & getInternal(const ID & id) const; InternalField & getInternal(const ID & id); inline bool isInternal(const ID & id, const ElementKind & element_kind) const; inline ElementTypeMap getInternalDataPerElem(const ID & id, const ElementKind & element_kind, const ID & fe_engine_id = "") const; bool isFiniteDeformation() const { return finite_deformation; } bool isInelasticDeformation() const { return inelastic_deformation; } template inline void setParam(const ID & param, T value); template inline const T & getParam(const ID & param) const; virtual void flattenInternal(const std::string & field_id, ElementTypeMapArray & internal_flat, const GhostType ghost_type = _not_ghost, ElementKind element_kind = _ek_not_defined); protected: bool isInit() const { return is_init; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// boolean to know if the material has been initialized bool is_init; std::map *> internal_vectors_real; std::map *> 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 element_filter; /// stresses arrays ordered by element types InternalField stress; /// eigenstrain arrays ordered by element types InternalField eigenstrain; /// grad_u arrays ordered by element types InternalField gradu; /// Green Lagrange strain (Finite deformation) InternalField green_strain; /// Second Piola-Kirchhoff stress tensor arrays ordered by element types (Finite deformation) InternalField piola_kirchhoff_2; /// potential energy by element InternalField potential_energy; /// tell if using in non local mode or not bool is_non_local; /// tell if the material need the previous stress state bool use_previous_stress; /// tell if the material need the previous strain state bool use_previous_gradu; /// elemental field interpolation coordinates InternalField interpolation_inverse_coordinates; /// elemental field interpolation points InternalField interpolation_points_matrices; }; /* -------------------------------------------------------------------------- */ /* 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::matrix_iterator gradu_it = \ this->gradu(el_type, ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ Array::matrix_iterator gradu_end = \ this->gradu(el_type, ghost_type).end(this->spatial_dimension, \ this->spatial_dimension); \ \ this->stress(el_type, \ ghost_type).resize(this->gradu(el_type, \ ghost_type).getSize()); \ \ Array::iterator< Matrix > stress_it = \ this->stress(el_type, ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ \ if(this->isFiniteDeformation()){ \ this->piola_kirchhoff_2(el_type, \ ghost_type).resize(this->gradu(el_type, \ ghost_type).getSize()); \ stress_it = \ this->piola_kirchhoff_2(el_type, \ ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ } \ \ for(;gradu_it != gradu_end; ++gradu_it, ++stress_it) { \ Matrix & __attribute__((unused)) grad_u = *gradu_it; \ Matrix & __attribute__((unused)) sigma = *stress_it #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END \ } \ #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_mat) \ Array::matrix_iterator gradu_it = \ this->gradu(el_type, ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ Array::matrix_iterator gradu_end = \ this->gradu(el_type, ghost_type).end(this->spatial_dimension, \ this->spatial_dimension); \ Array::matrix_iterator sigma_it = \ this->stress(el_type, ghost_type).begin(this->spatial_dimension, \ this->spatial_dimension); \ \ tangent_mat.resize(this->gradu(el_type, ghost_type).getSize()); \ \ UInt tangent_size = \ this->getTangentStiffnessVoigtSize(this->spatial_dimension); \ Array::matrix_iterator tangent_it = \ tangent_mat.begin(tangent_size, \ tangent_size); \ \ for(;gradu_it != gradu_end; ++gradu_it, ++sigma_it, ++tangent_it) { \ Matrix & __attribute__((unused)) grad_u = *gradu_it; \ Matrix & __attribute__((unused)) sigma_tensor = *sigma_it; \ Matrix & tangent = *tangent_it #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END \ } \ /* -------------------------------------------------------------------------- */ #define 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/materials/internal_field_tmpl.hh b/src/model/solid_mechanics/materials/internal_field_tmpl.hh index e7d11c241..407dc13cb 100644 --- a/src/model/solid_mechanics/materials/internal_field_tmpl.hh +++ b/src/model/solid_mechanics/materials/internal_field_tmpl.hh @@ -1,305 +1,305 @@ /** * @file internal_field_tmpl.hh * * @author Nicolas Richart * * @date creation: Wed Nov 13 2013 * @date last modification: Thu Jun 05 2014 * * @brief Material internal properties * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_INTERNAL_FIELD_TMPL_HH__ #define __AKANTU_INTERNAL_FIELD_TMPL_HH__ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template InternalField::InternalField(const ID & id, Material & material) : ElementTypeMapArray(id, material.getID(), material.getMemoryID()), material(material), fem(material.getModel().getFEEngine()), element_filter(material.getElementFilter()), default_value(T()), spatial_dimension(material.getModel().getSpatialDimension()), element_kind(_ek_regular), nb_component(0), is_init(false), previous_values(NULL) { } /* -------------------------------------------------------------------------- */ template InternalField::InternalField(const ID & id, Material & material, FEEngine & fem, const ElementTypeMapArray & element_filter) : ElementTypeMapArray(id, material.getID(), material.getMemoryID()), material(material), fem(fem), element_filter(element_filter), default_value(T()), spatial_dimension(material.getModel().getSpatialDimension()), element_kind(_ek_regular), nb_component(0), is_init(false), previous_values(NULL) { } /* -------------------------------------------------------------------------- */ template InternalField::InternalField(const ID & id, const InternalField & other) : ElementTypeMapArray(id, other.material.getID(), other.material.getMemoryID()), material(other.material), fem(other.fem), element_filter(other.element_filter), default_value(other.default_value), spatial_dimension(other.spatial_dimension), element_kind(other.element_kind), nb_component(other.nb_component), is_init(false), previous_values(NULL) { AKANTU_DEBUG_ASSERT(other.is_init, "Cannot create a copy of a non initialized field"); this->internalInitialize(this->nb_component); } /* -------------------------------------------------------------------------- */ template InternalField::~InternalField() { if(this->is_init) { this->material.unregisterInternal(*this); } delete previous_values; } /* -------------------------------------------------------------------------- */ template void InternalField::initialize(UInt nb_component) { internalInitialize(nb_component); } /* -------------------------------------------------------------------------- */ template void InternalField::initializeHistory() { if(!previous_values) previous_values = new InternalField("previous_" + this->getID(), *this); } /* -------------------------------------------------------------------------- */ template void InternalField::resize() { if(!this->is_init) return; for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; typename ElementTypeMapArray::type_iterator it = element_filter.firstType(spatial_dimension, gt, element_kind); typename ElementTypeMapArray::type_iterator end = element_filter.lastType(spatial_dimension, gt, element_kind); for(; it != end; ++it) { UInt nb_element = element_filter(*it, gt).getSize(); UInt nb_quadrature_points = fem.getNbQuadraturePoints(*it, gt); UInt new_size = nb_element * nb_quadrature_points; UInt old_size = 0; Array * vect = NULL; if(this->exists(*it, gt)) { vect = &(this->operator()(*it, gt)); old_size = vect->getSize(); vect->resize(new_size); } else { vect = &(this->alloc(nb_element * nb_quadrature_points, nb_component, *it, gt)); } this->setArrayValues(vect->storage() + old_size * vect->getNbComponent(), vect->storage() + new_size * vect->getNbComponent()); } } } /* -------------------------------------------------------------------------- */ template void InternalField::setDefaultValue(const T & value) { this->default_value = value; this->reset(); } /* -------------------------------------------------------------------------- */ template void InternalField::reset() { for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; typename ElementTypeMapArray::type_iterator it = this->firstType(spatial_dimension, gt, element_kind); typename ElementTypeMapArray::type_iterator end = this->lastType(spatial_dimension, gt, element_kind); for(; it != end; ++it) { Array & vect = this->operator()(*it, gt); vect.clear(); this->setArrayValues(vect.storage(), vect.storage() + vect.getSize() * vect.getNbComponent()); } } } /* -------------------------------------------------------------------------- */ template void InternalField::internalInitialize(UInt nb_component) { if(!this->is_init) { this->nb_component = nb_component; for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; typename ElementTypeMapArray::type_iterator it = element_filter.firstType(spatial_dimension, gt, element_kind); typename ElementTypeMapArray::type_iterator end = element_filter.lastType(spatial_dimension, gt, element_kind); for(; it != end; ++it) { UInt nb_element = element_filter(*it, gt).getSize(); UInt nb_quadrature_points = fem.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 void InternalField::setArrayValues(T * begin, T * end) { for(; begin < end; ++begin) *begin = default_value; } /* -------------------------------------------------------------------------- */ template void InternalField::saveCurrentValues() { AKANTU_DEBUG_ASSERT(previous_values != NULL, "The history of the internal " << this->getID() << " has not been activated"); if(!is_init) return; for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; - typename ElementTypeMapArray::type_iterator it = this->firstType(spatial_dimension, gt, element_kind); - typename ElementTypeMapArray::type_iterator end = this->lastType(spatial_dimension, gt, element_kind); + typename ElementTypeMapArray::type_iterator it = this->firstType(_all_dimensions, gt, element_kind); + typename ElementTypeMapArray::type_iterator end = this->lastType(_all_dimensions, gt, element_kind); for(; it != end; ++it) { this->previous_values->operator()(*it, gt).copy(this->operator()(*it, gt)); } } } /* -------------------------------------------------------------------------- */ template void InternalField::removeQuadraturePoints(const ElementTypeMapArray & new_numbering) { for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; ElementTypeMapArray::type_iterator it = new_numbering.firstType(_all_dimensions, gt, _ek_not_defined); ElementTypeMapArray::type_iterator end = new_numbering.lastType(_all_dimensions, gt, _ek_not_defined); for (; it != end; ++it) { ElementType type = *it; if(this->exists(type, gt)){ const Array & renumbering = new_numbering(type, gt); Array & vect = this->operator()(type, gt); UInt nb_quad_per_elem = fem.getNbQuadraturePoints(type, gt); UInt nb_component = vect.getNbComponent(); Array tmp(renumbering.getSize()*nb_quad_per_elem, nb_component); AKANTU_DEBUG_ASSERT(tmp.getSize() == vect.getSize(), "Something strange append some mater was created from nowhere!!"); AKANTU_DEBUG_ASSERT(tmp.getSize() == vect.getSize(), "Something strange append some mater was created or disappeared in "<< vect.getID() << "("<< vect.getSize() <<"!=" << tmp.getSize() <<") ""!!"); UInt new_size = 0; for (UInt i = 0; i < renumbering.getSize(); ++i) { UInt new_i = renumbering(i); if(new_i != UInt(-1)) { memcpy(tmp.storage() + new_i * nb_component * nb_quad_per_elem, vect.storage() + i * nb_component * nb_quad_per_elem, nb_component * nb_quad_per_elem * sizeof(T)); ++new_size; } } tmp.resize(new_size * nb_quad_per_elem); vect.copy(tmp); } } } } /* -------------------------------------------------------------------------- */ template void InternalField::printself(std::ostream & stream, unsigned int indent) const { stream << "InternalField [ " << this->getID(); #if !defined(AKANTU_NDEBUG) if(AKANTU_DEBUG_TEST(dblDump)) { stream << std::endl; InternalField::printself(stream, indent + 3); } else { #endif stream << " {" << this->getData(_not_ghost).size() << " types - " << this->getData(_ghost).size() << " ghost types" << "}"; #if !defined(AKANTU_NDEBUG) } #endif stream << " ]"; } /* -------------------------------------------------------------------------- */ template<> inline void ParsableParamTyped< InternalField >::parseParam(const ParserParameter & in_param) { ParsableParam::parseParam(in_param); Real r = in_param; param.setDefaultValue(r); } /* -------------------------------------------------------------------------- */ template inline InternalField::operator T() const { return default_value; } __END_AKANTU__ #endif /* __AKANTU_INTERNAL_FIELD_TMPL_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.cc index d9f4824b8..918fd45f2 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,696 @@ /** * @file material_cohesive_linear.cc * * @author Marco Vocialta * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include "material_cohesive_linear.hh" #include "solid_mechanics_model_cohesive.hh" #include "sparse_matrix.hh" #include "dof_synchronizer.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template MaterialCohesiveLinear::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 void MaterialCohesiveLinear::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 void MaterialCohesiveLinear::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 > & 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::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_list = facet_to_element(f); // compute bounding volume Real volume = 0; std::vector::const_iterator elem = element_list.begin(); std::vector::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 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 void MaterialCohesiveLinear::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 & facets_check = inserter.getCheckFacets(type_facet); Array & f_insertion = inserter.getInsertionFacets(type_facet); Array & f_filter = facet_filter(type_facet); Array & sig_c_eff = sigma_c_eff(type_cohesive); Array & del_c = delta_c_eff(type_cohesive); Array & ins_stress = insertion_stress(type_cohesive); Array & trac_old = tractions_old(type_cohesive); const Array & f_stress = model->getStressOnFacets(type_facet); const Array & 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::const_iterator sigma_lim_it = sigma_lim.begin(); Matrix stress_tmp(spatial_dimension, spatial_dimension); Matrix normal_traction(spatial_dimension, nb_quad_facet); Vector stress_check(nb_quad_facet); UInt sp2 = spatial_dimension * spatial_dimension; const Array & tangents = model->getTangents(type_facet); const Array & normals = model->getFEEngine("FacetsFEEngine").getNormalsOnQuadPoints(type_facet); Array::const_vector_iterator normal_begin = normals.begin(spatial_dimension); Array::const_vector_iterator tangent_begin = tangents.begin(tangents.getNbComponent()); Array::const_matrix_iterator facet_stress_begin = f_stress.begin(spatial_dimension, spatial_dimension * 2); std::vector new_sigmas; std::vector< Vector > new_normal_traction; std::vector 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 & normal = normal_begin[current_quad]; const Vector & tangent = tangent_begin[current_quad]; const Matrix & facet_stress_it = facet_stress_begin[current_quad]; // compute average stress on the current quadrature point Matrix stress_1(facet_stress_it.storage(), spatial_dimension, spatial_dimension); Matrix stress_2(facet_stress_it.storage() + sp2, spatial_dimension, spatial_dimension); stress_tmp.copy(stress_1); stress_tmp += stress_2; stress_tmp /= 2.; Vector 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 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){ ++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 abs_max(comm.getNbProc()); abs_max(comm.whoAmI()) = max_ratio; comm.allGather(abs_max.storage(), 1); Array::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::iterator > normal_traction_it = // normal_traction.begin_reinterpret(nb_quad_facet, spatial_dimension, nb_facet); Array::const_iterator sigma_lim_it = sigma_lim.begin(); for (UInt q = 0; q < nb_quad_facet; ++q) { // Vector ins_s(normal_traction_it[index_f].storage() + q * spatial_dimension, // spatial_dimension); Real new_sigma = (sigma_lim_it[index_f]); new_sigmas.push_back(new_sigma); new_normal_traction.push_back(0.0); 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(); - } + AKANTU_DEBUG_OUT(); +} /* -------------------------------------------------------------------------- */ template void MaterialCohesiveLinear::computeTraction(const Array & normal, ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array::iterator< Vector > traction_it = tractions(el_type, ghost_type).begin(spatial_dimension); Array::iterator< Vector > opening_it = opening(el_type, ghost_type).begin(spatial_dimension); Array::iterator< Vector > contact_traction_it = contact_tractions(el_type, ghost_type).begin(spatial_dimension); Array::iterator< Vector > contact_opening_it = contact_opening(el_type, ghost_type).begin(spatial_dimension); Array::const_iterator< Vector > normal_it = normal.begin(spatial_dimension); Array::iterator< Vector >traction_end = tractions(el_type, ghost_type).end(spatial_dimension); Array::iteratorsigma_c_it = sigma_c_eff(el_type, ghost_type).begin(); Array::iteratordelta_max_it = delta_max(el_type, ghost_type).begin(); Array::iteratordelta_max_prev_it = delta_max.previous(el_type, ghost_type).begin(); Array::iteratordelta_c_it = delta_c_eff(el_type, ghost_type).begin(); Array::iteratordamage_it = damage(el_type, ghost_type).begin(); Array::iterator > insertion_stress_it = insertion_stress(el_type, ghost_type).begin(spatial_dimension); Real * memory_space = new Real[2*spatial_dimension]; Vector normal_opening(memory_space, spatial_dimension); Vector 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 void MaterialCohesiveLinear::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 & 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::iteratordelta_max_it = delta_max(el_type, ghost_type).begin(); Array::iteratordelta_max_end = delta_max(el_type, ghost_type).end(); Array::iteratordelta_max_prev_it = delta_max.previous(el_type, ghost_type).begin(); Array::iteratordelta_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 void MaterialCohesiveLinear::computeTangentTraction(const ElementType & el_type, Array & tangent_matrix, const Array & normal, GhostType ghost_type) { AKANTU_DEBUG_IN(); /// define iterators Array::matrix_iterator tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension); Array::matrix_iterator tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension); Array::const_vector_iterator normal_it = normal.begin(spatial_dimension); Array::vector_iterator opening_it = opening(el_type, ghost_type).begin(spatial_dimension); Array::iteratordelta_max_it = delta_max.previous(el_type, ghost_type).begin(); Array::iteratorsigma_c_it = sigma_c_eff(el_type, ghost_type).begin(); Array::iteratordelta_c_it = delta_c_eff(el_type, ghost_type).begin(); Array::iteratordamage_it = damage(el_type, ghost_type).begin(); Array::iterator< Vector > contact_opening_it = contact_opening(el_type, ghost_type).begin(spatial_dimension); Vector normal_opening(spatial_dimension); Vector tangential_opening(spatial_dimension); Array 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 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 I(spatial_dimension, spatial_dimension); I.eye(beta2_kappa); Matrix nn(n_outer_n); nn *= (1 - beta2_kappa); nn += I; nn *= t/delta; Vector t_tilde(normal_opening); t_tilde *= (1 - beta2_kappa2); Vector mm(*opening_it); mm *= beta2_kappa2; t_tilde += mm; Vector t_hat(normal_opening); t_hat += beta2_kappa * tangential_opening; Matrix 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_cohesive/constitutive_laws/material_cohesive_linear.hh b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.hh index 084be91f1..79483268e 100644 --- a/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.hh +++ b/src/model/solid_mechanics/materials/material_cohesive/constitutive_laws/material_cohesive_linear.hh @@ -1,168 +1,168 @@ /** * @file material_cohesive_linear.hh * * @author Marco Vocialta * * @date creation: Tue May 08 2012 * @date last modification: Tue Jul 29 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 . * */ /* -------------------------------------------------------------------------- */ #include "material_cohesive.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_COHESIVE_LINEAR_HH__ #define __AKANTU_MATERIAL_COHESIVE_LINEAR_HH__ /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /** * Cohesive material linear damage for extrinsic case * * parameters in the material files : * - sigma_c : critical stress sigma_c (default: 0) * - beta : weighting parameter for sliding and normal opening (default: 0) * - G_cI : fracture energy for mode I (default: 0) * - G_cII : fracture energy for mode II (default: 0) * - penalty : stiffness in compression to prevent penetration */ template class MaterialCohesiveLinear : public MaterialCohesive { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialCohesiveLinear(SolidMechanicsModel & model, const ID & id = ""); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the material parameters virtual void initMaterial(); /// check stress for cohesive elements' insertion virtual void checkInsertion(bool check_only = false); /// compute effective stress norm for insertion check - inline Real computeEffectiveNorm(const Matrix & stress, - const Vector & normal, - const Vector & tangent, - Vector & normal_stress) const; + Real computeEffectiveNorm(const Matrix & stress, + const Vector & normal, + const Vector & tangent, + Vector & normal_stress) const; protected: /// constitutive law virtual void computeTraction(const Array & normal, ElementType el_type, GhostType ghost_type = _not_ghost); /// check delta_max for cohesive elements in case of no convergence /// in the solveStep (only for extrinsic-implicit) void checkDeltaMax(GhostType ghost_type = _not_ghost); /// compute tangent stiffness matrix void computeTangentTraction(const ElementType & el_type, Array & tangent_matrix, const Array & normal, GhostType ghost_type); /** * Scale insertion traction sigma_c according to the volume of the * two elements surrounding a facet * * see the article: F. Zhou and J. F. Molinari "Dynamic crack * propagation with cohesive elements: a methodology to address mesh * dependency" International Journal for Numerical Methods in * Engineering (2004) */ void scaleInsertionTraction(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get sigma_c_eff AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(InsertionTraction, sigma_c_eff, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// beta parameter Real beta; /// beta square inverse to compute effective norm Real beta2_inv; /// mode I fracture energy Real G_c; /// kappa parameter Real kappa; /// constitutive law scalar to compute delta Real beta2_kappa2; /// constitutive law scalar to compute traction Real beta2_kappa; /// penalty coefficient Real penalty; /// reference volume used to scale sigma_c Real volume_s; /// weibull exponent used to scale sigma_c Real m_s; /// critical effective stress RandomInternalField sigma_c_eff; /// effective critical displacement (each element can have a /// different value) CohesiveInternalField delta_c_eff; /// stress at insertion CohesiveInternalField insertion_stress; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_cohesive_linear_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_MATERIAL_COHESIVE_LINEAR_HH__ */ diff --git a/src/model/solid_mechanics/materials/material_elastic.cc b/src/model/solid_mechanics/materials/material_elastic.cc index 4787baf68..e045e2b42 100644 --- a/src/model/solid_mechanics/materials/material_elastic.cc +++ b/src/model/solid_mechanics/materials/material_elastic.cc @@ -1,229 +1,229 @@ /** * @file material_elastic.cc * * @author Lucas Frerot * @author Marco Vocialta * @author Nicolas Richart * @author Daniel Pino Muñoz * * @date creation: Tue Jul 27 2010 * @date last modification: Tue Sep 16 2014 * * @brief 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 . * */ /* -------------------------------------------------------------------------- */ #include "material_elastic.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template MaterialElastic::MaterialElastic(SolidMechanicsModel & model, const ID & id) : Material(model, id), Parent(model, id) { AKANTU_DEBUG_IN(); 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 void MaterialElastic::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 void MaterialElastic::updateInternalParameters() { MaterialThermal::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 void MaterialElastic::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Parent::computeStress(el_type, ghost_type); Array::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 E(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); /// compute E this->template gradUToGreenStrain(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 void MaterialElastic::computeTangentModuli(__attribute__((unused)) const ElementType & el_type, Array & 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 Real MaterialElastic::getPushWaveSpeed(__attribute__((unused)) const Element & element) const { return sqrt((lambda + 2*mu)/this->rho); } /* -------------------------------------------------------------------------- */ template Real MaterialElastic::getShearWaveSpeed(__attribute__((unused)) const Element & element) const { return sqrt(mu/this->rho); } /* -------------------------------------------------------------------------- */ template void MaterialElastic::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialThermal::computePotentialEnergy(el_type, ghost_type); if(ghost_type != _not_ghost) return; Array::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 E(spatial_dimension, spatial_dimension); MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, ghost_type); this->template gradUToGreenStrain(grad_u, E); this->computePotentialEnergyOnQuad(E, sigma, *epot); ++epot; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialElastic::computePotentialEnergyByElement(ElementType type, UInt index, Vector & epot_on_quad_points) { Array::matrix_iterator gradu_it = this->gradu(type).begin(spatial_dimension, spatial_dimension); Array::matrix_iterator gradu_end = this->gradu(type).begin(spatial_dimension, spatial_dimension); Array::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 grad_u(spatial_dimension, spatial_dimension); for(;gradu_it != gradu_end; ++gradu_it, ++stress_it, ++epot_quad) { if (this->finite_deformation) this->template gradUToGreenStrain(*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..5c3de0bb4 100644 --- a/src/model/solid_mechanics/materials/material_elastic.hh +++ b/src/model/solid_mechanics/materials/material_elastic.hh @@ -1,140 +1,140 @@ /** * @file material_elastic.hh * * @author Lucas Frerot * @author Daniel Pino Muñoz * @author Nicolas Richart * * @date creation: Wed Aug 04 2010 * @date last modification: Tue Sep 16 2014 * * @brief Material isotropic elastic * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material_thermal.hh" #include "plane_stress_toolbox.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_ELASTIC_HH__ #define __AKANTU_MATERIAL_ELASTIC_HH__ __BEGIN_AKANTU__ /** * Material elastic isotropic * * parameters in the material files : * - E : Young's modulus (default: 0) * - nu : Poisson's ratio (default: 1/2) * - Plane_Stress : if 0: plane strain, else: plane stress (default: 0) */ template class MaterialElastic : public PlaneStressToolbox< spatial_dimension, MaterialThermal > { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ private: typedef PlaneStressToolbox< spatial_dimension, MaterialThermal > Parent; public: MaterialElastic(SolidMechanicsModel & model, const ID & id = ""); virtual ~MaterialElastic() {} /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void initMaterial(); /// constitutive law for all element of a type virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the tangent stiffness matrix for an element type virtual void computeTangentModuli(const ElementType & el_type, Array & tangent_matrix, GhostType ghost_type = _not_ghost); /// compute the elastic potential energy virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); virtual void computePotentialEnergyByElement(ElementType type, UInt index, Vector & epot_on_quad_points); /// compute the p-wave speed in the material virtual Real getPushWaveSpeed(const Element & element) const; /// compute the s-wave speed in the material virtual Real getShearWaveSpeed(const Element & element) const; protected: /// constitutive law for a given quadrature point inline void computeStressOnQuad(const Matrix & grad_u, Matrix & sigma, const Real sigma_th = 0) const; /// compute the tangent stiffness matrix for an element - inline void computeTangentModuliOnQuad(Matrix & tangent); + inline void computeTangentModuliOnQuad(Matrix & tangent) const; /// recompute the lame coefficient if E or nu changes virtual void updateInternalParameters(); static inline void computePotentialEnergyOnQuad(const Matrix & grad_u, const Matrix & sigma, Real & epot); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* 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 * @author Nicolas Richart * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template inline void MaterialElastic::computeStressOnQuad(const Matrix & grad_u, Matrix & 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 & grad_u, Matrix & sigma, Real sigma_th) const { sigma(0, 0) = this->E * grad_u(0, 0) + sigma_th; } /* -------------------------------------------------------------------------- */ template -inline void MaterialElastic::computeTangentModuliOnQuad(Matrix & tangent) { +inline void MaterialElastic::computeTangentModuliOnQuad(Matrix & 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 inline void MaterialElastic::computePotentialEnergyOnQuad(const Matrix & grad_u, const Matrix & sigma, Real & epot) { epot = .5 * sigma.doubleDot(grad_u); } /* -------------------------------------------------------------------------- */ template<> -inline void MaterialElastic<1>::computeTangentModuliOnQuad(Matrix & tangent) { +inline void MaterialElastic<1>::computeTangentModuliOnQuad(Matrix & 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 * * @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 . * */ /* -------------------------------------------------------------------------- */ #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_template.hh b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement_template.hh index aeb473d5e..428532ac8 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,122 @@ /** * @file material_reinforcement_template.hh * * @author Lucas Frérot * * @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 . * */ /* -------------------------------------------------------------------------- */ #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. * Be careful ! Because of multiple inheritance, this class * forms a diamond. */ template > class MaterialReinforcementTemplate : public MaterialReinforcement, 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 & 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 & internal_flat, + ElementTypeMapArray & internal_flat, const GhostType ghost_type = _not_ghost, ElementKind element_kind = _ek_not_defined); + /// Save the previous internals + virtual void savePreviousState(); + protected: + /// Init plasticity internals if ConstLaw is plastic law + void initPlastic(MaterialReinforcementTemplate > & _this); + void initPlastic( + MaterialReinforcementTemplate > & _this); + /** * @brief Compute interface gradu from bulk gradu * \f[ * \varepsilon_s = C \varepsilon_c * \f] */ inline void computeInterfaceGradUOnQuad(const Matrix & full_gradu, Real & gradu, const Matrix & 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 63% 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..94e84ac1f 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,292 @@ /** - * @file material_reinforcement_template.cc + * @file material_reinforcement_template_tmpl.hh * * @author Lucas Frérot * * @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 . * */ +// /!\ no namespace here ! + /* -------------------------------------------------------------------------- */ template MaterialReinforcementTemplate::MaterialReinforcementTemplate(SolidMechanicsModel & model, - const ID & id): + const ID & id): Material(model, id), MaterialReinforcement(model, id), - ConstLaw(model, id) -{} + ConstLaw(model, id) { + this->element_filter.free(); + this->model->getInterfaceMesh().initElementTypeMapArray(this->element_filter, 1, 1, + false, _ek_regular); +} /* -------------------------------------------------------------------------- */ template MaterialReinforcementTemplate::~MaterialReinforcementTemplate() {} /* -------------------------------------------------------------------------- */ +/// TODO this function is super ugly. Find better way to initialize internals template void MaterialReinforcementTemplate::initMaterial() { MaterialReinforcement::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::model->getInterfaceMesh().firstType(); - Mesh::type_iterator type_end = this->MaterialReinforcement::model->getInterfaceMesh().lastType(); + Mesh::type_iterator + type_it = this->MaterialReinforcement::model->getInterfaceMesh().firstType(), + type_end = this->MaterialReinforcement::model->getInterfaceMesh().lastType(); // Reshape the ConstLaw internal fields for (; type_it != type_end ; ++type_it) { UInt nb_elements = this->MaterialReinforcement::element_filter(*type_it).getSize(); FEEngine & interface_engine = this->MaterialReinforcement::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); + + if (this->ConstLaw::use_previous_stress) { + this->ConstLaw::stress.initializeHistory(); + this->ConstLaw::stress.previous().free(); + this->ConstLaw::stress.previous().alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); + } + + if (this->ConstLaw::use_previous_gradu) { + this->ConstLaw::gradu.initializeHistory(); + this->ConstLaw::gradu.previous().free(); + this->ConstLaw::gradu.previous().alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); + } + + if (this->ConstLaw::use_previous_stress_thermal) { + this->ConstLaw::sigma_th.initializeHistory(); + this->ConstLaw::sigma_th.previous().free(); + this->ConstLaw::sigma_th.previous().alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); + } + + this->initPlastic(*this); } } /* -------------------------------------------------------------------------- */ template void MaterialReinforcementTemplate::computeGradU(const ElementType & el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); MaterialReinforcement::computeGradU(el_type, ghost_type); const UInt voigt_size = Material::getTangentStiffnessVoigtSize(dim); Array::matrix_iterator full_gradu_it = this->MaterialReinforcement::gradu(el_type, ghost_type).begin(dim, dim); Array::matrix_iterator full_gradu_end = this->MaterialReinforcement::gradu(el_type, ghost_type).end(dim, dim); Array::scalar_iterator gradu_it = this->ConstLaw::gradu(el_type, ghost_type).begin(); Array::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 & full_gradu = *full_gradu_it; Real & gradu = *gradu_it; Matrix & C = *cosines_it; computeInterfaceGradUOnQuad(full_gradu, gradu, C); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialReinforcementTemplate::computeInterfaceGradUOnQuad(const Matrix & full_gradu, Real & gradu, const Matrix & C) { const UInt voigt_size = Material::getTangentStiffnessVoigtSize(dim); Matrix epsilon(dim, dim); Vector e_voigt(voigt_size); Vector e_interface_voigt(voigt_size); epsilon = 0.5 * (full_gradu + full_gradu.transpose()); MaterialReinforcement::strainTensorToVoigtVector(epsilon, e_voigt); e_interface_voigt.mul(C, e_voigt); gradu = e_interface_voigt(0); } /* -------------------------------------------------------------------------- */ template void MaterialReinforcementTemplate::computeTangentModuli(const ElementType & el_type, - Array & tangent, - GhostType ghost_type) { + Array & 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 void MaterialReinforcementTemplate::computeStress(ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); ConstLaw::computeStress(type, ghost_type); Array::matrix_iterator full_sigma_it = this->MaterialReinforcement::stress(type, ghost_type).begin(dim, dim); Array::matrix_iterator full_sigma_end = this->MaterialReinforcement::stress(type, ghost_type).end(dim, dim); Array::scalar_iterator sigma_it = this->ConstLaw::stress(type, ghost_type).begin(); Array::scalar_iterator pre_stress_it = this->MaterialReinforcement::pre_stress(type, ghost_type).begin(); for (; full_sigma_it != full_sigma_end ; ++full_sigma_it, ++sigma_it, ++pre_stress_it) { Matrix & sigma = *full_sigma_it; sigma(0, 0) = *sigma_it + *pre_stress_it; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template Real MaterialReinforcementTemplate::getEnergy(std::string id) { return MaterialReinforcement::getEnergy(id); } /* -------------------------------------------------------------------------- */ template void MaterialReinforcementTemplate::computePotentialEnergy(ElementType type, GhostType ghost_type) { ConstLaw::computePotentialEnergy(type, ghost_type); } +/* -------------------------------------------------------------------------- */ + template void MaterialReinforcementTemplate::flattenInternal(const std::string & field_id, ElementTypeMapArray & internal_flat, const GhostType ghost_type, ElementKind element_kind) { - if (field_id == "stress_embedded") + if (field_id == "stress_embedded" || field_id == "inelastic_strain") MaterialReinforcement::flattenInternal(field_id, internal_flat, ghost_type, element_kind); } + +template +void MaterialReinforcementTemplate::initPlastic( + MaterialReinforcementTemplate > & _this) { + +} + +template +void MaterialReinforcementTemplate::initPlastic( + MaterialReinforcementTemplate > & _this) { + _this.ConstLaw::iso_hardening.free(); + _this.ConstLaw::plastic_energy.free(); + _this.ConstLaw::d_plastic_energy.free(); + _this.ConstLaw::inelastic_strain.free(); + + Mesh::type_iterator + type_it = _this.MaterialReinforcement::model->getInterfaceMesh().firstType(), + type_end = _this.MaterialReinforcement::model->getInterfaceMesh().lastType(); + + for (; type_it != type_end ; ++type_it) { + UInt nb_elements = _this.MaterialReinforcement::element_filter(*type_it).getSize(); + + FEEngine & interface_engine = + _this.MaterialReinforcement::model->getFEEngine("EmbeddedInterfaceFEEngine"); + + UInt nb_quad = interface_engine.getNbQuadraturePoints(*type_it); + + _this.ConstLaw::iso_hardening.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); + _this.ConstLaw::plastic_energy.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); + _this.ConstLaw::d_plastic_energy.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); + _this.ConstLaw::inelastic_strain.alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); + + _this.plastic_energy.initialize(1); + _this.d_plastic_energy.initialize(1); + _this.iso_hardening.initialize(1); + _this.inelastic_strain.initialize(1); + + _this.ConstLaw::iso_hardening.initializeHistory(); + _this.ConstLaw::iso_hardening.previous().free(); + _this.ConstLaw::iso_hardening.previous().alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); + + _this.ConstLaw::plastic_energy.initializeHistory(); + _this.ConstLaw::plastic_energy.previous().free(); + _this.ConstLaw::plastic_energy.previous().alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); + + _this.ConstLaw::d_plastic_energy.initializeHistory(); + _this.ConstLaw::d_plastic_energy.previous().free(); + _this.ConstLaw::d_plastic_energy.previous().alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); + + _this.ConstLaw::inelastic_strain.initializeHistory(); + _this.ConstLaw::inelastic_strain.previous().free(); + _this.ConstLaw::inelastic_strain.previous().alloc(nb_elements * nb_quad, 1, *type_it, _not_ghost); + } +} + +template +void MaterialReinforcementTemplate::savePreviousState() { + ConstLaw::savePreviousState(); +} 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 * @author Daniel Pino Muñoz * @author Nicolas Richart * @author Ramin Aghababaei * @author Benjamin Paccaud * * @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 . * */ #include "material_linear_isotropic_hardening.hh" /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ ///Infinitesimal deformations template inline void MaterialLinearIsotropicHardening::computeStressOnQuad(const Matrix & grad_u, const Matrix & previous_grad_u, Matrix & sigma, const Matrix & previous_sigma, Matrix & inelastic_strain, const Matrix & 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 grad_delta_u(grad_u); grad_delta_u -= previous_grad_u; //Compute trial stress, sigma_tr Matrix sigma_tr(dim, dim); MaterialElastic::computeStressOnQuad(grad_delta_u, sigma_tr, delta_sigma_th); sigma_tr += previous_sigma; // Compute deviatoric trial stress, sigma_tr_dev Matrix sigma_tr_dev(sigma_tr); sigma_tr_dev -= Matrix::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 delta_inelastic_strain(dim, dim, 0.); if (std::abs(sigma_tr_dev_eff) > sigma_tr_dev.norm() * Math::getTolerance()) { delta_inelastic_strain.copy(sigma_tr_dev); delta_inelastic_strain *= 3./2. * dp / sigma_tr_dev_eff; } MaterialPlastic::computeStressAndInelasticStrainOnQuad(grad_delta_u, sigma, previous_sigma, inelastic_strain, previous_inelastic_strain, delta_inelastic_strain); } /* -------------------------------------------------------------------------- */ ///Finite deformations template inline void MaterialLinearIsotropicHardening::computeStressOnQuad(const Matrix & grad_u, const Matrix & previous_grad_u, Matrix & sigma, const Matrix & previous_sigma, Matrix & inelastic_strain, const Matrix & previous_inelastic_strain, Real & iso_hardening, const Real & previous_iso_hardening, const Real & sigma_th, const Real & previous_sigma_th, const Matrix & 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 grad_delta_u(grad_u); grad_delta_u -= previous_grad_u; //Compute trial stress, sigma_tr Matrix sigma_tr(dim, dim); MaterialElastic::computeStressOnQuad(grad_delta_u, sigma_tr, delta_sigma_th); sigma_tr += previous_sigma; // Compute deviatoric trial stress, sigma_tr_dev Matrix sigma_tr_dev(sigma_tr); sigma_tr_dev -= Matrix::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 cauchy_stress(dim,dim); Material::computeCauchyStressOnQuad(F_tensor,sigma_tr,cauchy_stress); Matrix cauchy_stress_dev(cauchy_stress); cauchy_stress_dev -= Matrix::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:"<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:"< delta_inelastic_strain(dim, dim, 0.); if (std::abs(sigma_tr_dev_eff) > sigma_tr_dev.norm() * 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 cauchy_dev_F(dim,dim); cauchy_dev_F.mul(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(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::computeStressAndInelasticStrainOnQuad(grad_delta_u, sigma, previous_sigma, inelastic_strain, previous_inelastic_strain, delta_inelastic_strain); } /* -------------------------------------------------------------------------- */ template inline void MaterialLinearIsotropicHardening::computeTangentModuliOnQuad(Matrix & tangent, const Matrix & grad_u, const Matrix & previous_grad_u, const Matrix & sigma_tensor, const Matrix & previous_sigma_tensor, const Real & iso_hardening) const { // Real r=iso_hardening; // Matrix grad_delta_u(grad_u); // grad_delta_u -= previous_grad_u; // //Compute trial stress, sigma_tr // Matrix sigma_tr(dim, dim); // MaterialElastic::computeStressOnQuad(grad_delta_u, sigma_tr); // sigma_tr += previous_sigma_tensor; // // Compute deviatoric trial stress, sigma_tr_dev // Matrix sigma_tr_dev(sigma_tr); // sigma_tr_dev -= Matrix::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 sigma_dev(sigma_tensor); // sigma_dev -= Matrix::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::vec[m][0]; UInt j = VoigtHelper::vec[m][1]; for (UInt n = 0; n < cols; ++n) { UInt k = VoigtHelper::vec[n][0]; UInt l = VoigtHelper::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::computeTangentModuliOnQuad(tangent); } diff --git a/src/model/solid_mechanics/solid_mechanics_model.cc b/src/model/solid_mechanics/solid_mechanics_model.cc index d5ff25dfb..f034e6d45 100644 --- a/src/model/solid_mechanics/solid_mechanics_model.cc +++ b/src/model/solid_mechanics/solid_mechanics_model.cc @@ -1,1834 +1,1836 @@ /** * @file solid_mechanics_model.cc * * @author Guillaume Anciaux * @author David Simon Kammer * @author Aurelia Isabel Cuba Ramos * @author Daniel Pino Muñoz * @author Nicolas Richart * * @date creation: Tue Jul 27 2010 * @date last modification: Fri Sep 19 2014 * * @brief Implementation of the SolidMechanicsModel class * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_math.hh" #include "aka_common.hh" #include "solid_mechanics_model.hh" #include "group_manager_inline_impl.cc" #include "dumpable_inline_impl.hh" #include "integration_scheme_2nd_order.hh" #include "element_group.hh" #include "static_communicator.hh" #include "dof_synchronizer.hh" #include "element_group.hh" #include #ifdef AKANTU_USE_MUMPS #include "solver_mumps.hh" #endif #ifdef AKANTU_USE_PETSC #include "solver_petsc.hh" #include "petsc_matrix.hh" #endif #ifdef AKANTU_USE_IOHELPER # include "dumper_field.hh" # include "dumper_paraview.hh" # include "dumper_homogenizing_field.hh" # include "dumper_material_internal_field.hh" # include "dumper_elemental_field.hh" # include "dumper_material_padders.hh" # include "dumper_element_partition.hh" # include "dumper_iohelper.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ const SolidMechanicsModelOptions default_solid_mechanics_model_options(_explicit_lumped_mass, false); /* -------------------------------------------------------------------------- */ /** * A solid mechanics model need a mesh and a dimension to be created. the model * by it self can not do a lot, the good init functions should be called in * order to configure the model depending on what we want to do. * * @param mesh mesh representing the model we want to simulate * @param dim spatial dimension of the problem, if dim = 0 (default value) the * dimension of the problem is assumed to be the on of the mesh * @param id an id to identify the model */ SolidMechanicsModel::SolidMechanicsModel(Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id) : Model(mesh, dim, id, memory_id), BoundaryCondition(), time_step(NAN), f_m2a(1.0), mass_matrix(NULL), velocity_damping_matrix(NULL), stiffness_matrix(NULL), jacobian_matrix(NULL), material_index("material index", id), material_local_numbering("material local numbering", id), material_selector(new DefaultMaterialSelector(material_index)), is_default_material_selector(true), integrator(NULL), increment_flag(false), solver(NULL), synch_parallel(NULL), are_materials_instantiated(false) { AKANTU_DEBUG_IN(); createSynchronizerRegistry(this); registerFEEngineObject("SolidMechanicsFEEngine", mesh, spatial_dimension); this->displacement = NULL; this->mass = NULL; this->velocity = NULL; this->acceleration = NULL; this->force = NULL; this->residual = NULL; this->blocked_dofs = NULL; this->increment = NULL; this->increment_acceleration = NULL; this->dof_synchronizer = NULL; this->previous_displacement = NULL; materials.clear(); mesh.registerEventHandler(*this); #if defined(AKANTU_USE_IOHELPER) this->mesh.registerDumper("paraview_all", id, true); this->mesh.addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_regular); #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolidMechanicsModel::~SolidMechanicsModel() { AKANTU_DEBUG_IN(); std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { delete *mat_it; } materials.clear(); delete integrator; delete solver; delete mass_matrix; delete velocity_damping_matrix; if(stiffness_matrix && stiffness_matrix != jacobian_matrix) delete stiffness_matrix; delete jacobian_matrix; delete synch_parallel; if(is_default_material_selector) { delete material_selector; material_selector = NULL; } AKANTU_DEBUG_OUT(); } void SolidMechanicsModel::setTimeStep(Real time_step) { this->time_step = time_step; #if defined(AKANTU_USE_IOHELPER) this->mesh.getDumper().setTimeStep(time_step); #endif } /* -------------------------------------------------------------------------- */ /* Initialisation */ /* -------------------------------------------------------------------------- */ /** * This function groups many of the initialization in on function. For most of * basics case the function should be enough. The functions initialize the * model, the internal vectors, set them to 0, and depending on the parameters * it also initialize the explicit or implicit solver. * * @param material_file the file containing the materials to use * @param method the analysis method wanted. See the akantu::AnalysisMethod for * the different possibilities */ void SolidMechanicsModel::initFull(const ModelOptions & options) { Model::initFull(options); const SolidMechanicsModelOptions & smm_options = dynamic_cast(options); method = smm_options.analysis_method; // initialize the vectors initArrays(); // set the initial condition to 0 force->clear(); velocity->clear(); acceleration->clear(); displacement->clear(); // initialize pcb if(pbc_pair.size()!=0) initPBC(); // initialize the time integration schemes switch(method) { case _explicit_lumped_mass: initExplicit(); break; case _explicit_consistent_mass: initSolver(); initExplicit(); break; case _implicit_dynamic: initImplicit(true); break; case _static: initImplicit(false); break; default: AKANTU_EXCEPTION("analysis method not recognised by SolidMechanicsModel"); break; } // initialize the materials if(this->parser->getLastParsedFile() != "") { instantiateMaterials(); } if(!smm_options.no_init_materials) { initMaterials(); } if(increment_flag) initBC(*this, *displacement, *increment, *force); else initBC(*this, *displacement, *force); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initParallel(MeshPartition * partition, DataAccessor * data_accessor) { AKANTU_DEBUG_IN(); if (data_accessor == NULL) data_accessor = this; synch_parallel = &createParallelSynch(partition,data_accessor); synch_registry->registerSynchronizer(*synch_parallel, _gst_material_id); synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_mass); synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_stress); synch_registry->registerSynchronizer(*synch_parallel, _gst_smm_boundary); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initFEEngineBoundary() { FEEngine & fem_boundary = getFEEngineBoundary(); fem_boundary.initShapeFunctions(_not_ghost); fem_boundary.initShapeFunctions(_ghost); fem_boundary.computeNormalsOnControlPoints(_not_ghost); fem_boundary.computeNormalsOnControlPoints(_ghost); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initExplicit(AnalysisMethod analysis_method) { AKANTU_DEBUG_IN(); //in case of switch from implicit to explicit if(!this->isExplicit()) method = analysis_method; if (integrator) delete integrator; integrator = new CentralDifference(); UInt nb_nodes = acceleration->getSize(); UInt nb_degree_of_freedom = acceleration->getNbComponent(); std::stringstream sstr; sstr << id << ":increment_acceleration"; increment_acceleration = &(alloc(sstr.str(), nb_nodes, nb_degree_of_freedom, Real())); AKANTU_DEBUG_OUT(); } void SolidMechanicsModel::initArraysPreviousDisplacment() { AKANTU_DEBUG_IN(); SolidMechanicsModel::setIncrementFlagOn(); UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_disp_t; sstr_disp_t << id << ":previous_displacement"; previous_displacement = &(alloc (sstr_disp_t.str(), nb_nodes, spatial_dimension, 0.)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Allocate all the needed vectors. By default their are not necessarily set to * 0 * */ void SolidMechanicsModel::initArrays() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_disp; sstr_disp << id << ":displacement"; // std::stringstream sstr_mass; sstr_mass << id << ":mass"; std::stringstream sstr_velo; sstr_velo << id << ":velocity"; std::stringstream sstr_acce; sstr_acce << id << ":acceleration"; std::stringstream sstr_forc; sstr_forc << id << ":force"; std::stringstream sstr_resi; sstr_resi << id << ":residual"; std::stringstream sstr_boun; sstr_boun << id << ":blocked_dofs"; displacement = &(alloc(sstr_disp.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); // mass = &(alloc(sstr_mass.str(), nb_nodes, spatial_dimension, 0)); velocity = &(alloc(sstr_velo.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); acceleration = &(alloc(sstr_acce.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); force = &(alloc(sstr_forc.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); residual = &(alloc(sstr_resi.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); blocked_dofs = &(alloc(sstr_boun.str(), nb_nodes, spatial_dimension, false)); std::stringstream sstr_curp; sstr_curp << id << ":current_position"; current_position = &(alloc(sstr_curp.str(), 0, spatial_dimension, REAL_INIT_VALUE)); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; Mesh::type_iterator it = mesh.firstType(spatial_dimension, gt, _ek_not_defined); Mesh::type_iterator end = mesh.lastType(spatial_dimension, gt, _ek_not_defined); for(; it != end; ++it) { UInt nb_element = mesh.getNbElement(*it, gt); material_index.alloc(nb_element, 1, *it, gt); material_local_numbering.alloc(nb_element, 1, *it, gt); } } dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension); dof_synchronizer->initLocalDOFEquationNumbers(); dof_synchronizer->initGlobalDOFEquationNumbers(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Initialize the model,basically it pre-compute the shapes, shapes derivatives * and jacobian * */ void SolidMechanicsModel::initModel() { /// \todo add the current position as a parameter to initShapeFunctions for /// large deformation getFEEngine().initShapeFunctions(_not_ghost); getFEEngine().initShapeFunctions(_ghost); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initPBC() { Model::initPBC(); registerPBCSynchronizer(); // as long as there are ones on the diagonal of the matrix, we can put boudandary true for slaves std::map::iterator it = pbc_pair.begin(); std::map::iterator end = pbc_pair.end(); UInt dim = mesh.getSpatialDimension(); while(it != end) { for (UInt i=0; iregisterSynchronizer(*synch, _gst_smm_uv); synch_registry->registerSynchronizer(*synch, _gst_smm_mass); synch_registry->registerSynchronizer(*synch, _gst_smm_res); synch_registry->registerSynchronizer(*synch, _gst_for_dump); changeLocalEquationNumberForPBC(pbc_pair, mesh.getSpatialDimension()); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateCurrentPosition() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); current_position->resize(nb_nodes); Real * current_position_val = current_position->storage(); Real * position_val = mesh.getNodes().storage(); Real * displacement_val = displacement->storage(); /// compute current_position = initial_position + displacement memcpy(current_position_val, position_val, nb_nodes*spatial_dimension*sizeof(Real)); for (UInt n = 0; n < nb_nodes*spatial_dimension; ++n) { *current_position_val++ += *displacement_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initializeUpdateResidualData() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); residual->resize(nb_nodes); /// copy the forces in residual for boundary conditions memcpy(residual->storage(), force->storage(), nb_nodes*spatial_dimension*sizeof(Real)); // start synchronization synch_registry->asynchronousSynchronize(_gst_smm_uv); synch_registry->waitEndSynchronize(_gst_smm_uv); updateCurrentPosition(); AKANTU_DEBUG_OUT(); } /*----------------------------------------------------------------------------*/ void SolidMechanicsModel::reInitialize() { } /* -------------------------------------------------------------------------- */ /* Explicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /** * This function compute the second member of the motion equation. That is to * say the sum of forces @f$ r = F_{ext} - F_{int} @f$. @f$ F_{ext} @f$ is given * by the user in the force vector, and @f$ F_{int} @f$ is computed as @f$ * F_{int} = \int_{\Omega} N \sigma d\Omega@f$ * */ void SolidMechanicsModel::updateResidual(bool need_initialize) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the internal forces"); // f = f_ext - f_int // f = f_ext if(need_initialize) initializeUpdateResidualData(); AKANTU_DEBUG_INFO("Compute local stresses"); std::vector::iterator mat_it; for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllStresses(_not_ghost); } #ifdef AKANTU_DAMAGE_NON_LOCAL /* ------------------------------------------------------------------------ */ /* Computation of the non local part */ synch_registry->asynchronousSynchronize(_gst_mnl_for_average); AKANTU_DEBUG_INFO("Compute non local stresses for local elements"); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllNonLocalStresses(_not_ghost); } AKANTU_DEBUG_INFO("Wait distant non local stresses"); synch_registry->waitEndSynchronize(_gst_mnl_for_average); AKANTU_DEBUG_INFO("Compute non local stresses for ghosts elements"); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllNonLocalStresses(_ghost); } #endif /* ------------------------------------------------------------------------ */ /* assembling the forces internal */ // communicate the stress AKANTU_DEBUG_INFO("Send data for residual assembly"); synch_registry->asynchronousSynchronize(_gst_smm_stress); AKANTU_DEBUG_INFO("Assemble residual for local elements"); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.assembleResidual(_not_ghost); } AKANTU_DEBUG_INFO("Wait distant stresses"); // finalize communications synch_registry->waitEndSynchronize(_gst_smm_stress); AKANTU_DEBUG_INFO("Assemble residual for ghost elements"); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.assembleResidual(_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::computeStresses() { if (isExplicit()) { // start synchronization synch_registry->asynchronousSynchronize(_gst_smm_uv); synch_registry->waitEndSynchronize(_gst_smm_uv); // compute stresses on all local elements for each materials std::vector::iterator mat_it; for (mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllStresses(_not_ghost); } /* ------------------------------------------------------------------------ */ #ifdef AKANTU_DAMAGE_NON_LOCAL /* Computation of the non local part */ synch_registry->asynchronousSynchronize(_gst_mnl_for_average); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllNonLocalStresses(_not_ghost); } synch_registry->waitEndSynchronize(_gst_mnl_for_average); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllNonLocalStresses(_ghost); } #endif } else { std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; mat.computeAllStressesFromTangentModuli(_not_ghost); } } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateResidualInternal() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Update the residual"); // f = f_ext - f_int - Ma - Cv = r - Ma - Cv; if(method != _static) { // f -= Ma if(mass_matrix) { // if full mass_matrix Array * Ma = new Array(*acceleration, true, "Ma"); *Ma *= *mass_matrix; /// \todo check unit conversion for implicit dynamics // *Ma /= f_m2a *residual -= *Ma; delete Ma; } else if (mass) { // else lumped mass UInt nb_nodes = acceleration->getSize(); UInt nb_degree_of_freedom = acceleration->getNbComponent(); Real * mass_val = mass->storage(); Real * accel_val = acceleration->storage(); Real * res_val = residual->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); for (UInt n = 0; n < nb_nodes * nb_degree_of_freedom; ++n) { if(!(*blocked_dofs_val)) { *res_val -= *accel_val * *mass_val /f_m2a; } blocked_dofs_val++; res_val++; mass_val++; accel_val++; } } else { AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix."); } // f -= Cv if(velocity_damping_matrix) { Array * Cv = new Array(*velocity); *Cv *= *velocity_damping_matrix; *residual -= *Cv; delete Cv; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateAcceleration() { AKANTU_DEBUG_IN(); updateResidualInternal(); if(method == _explicit_lumped_mass) { /* residual = residual_{n+1} - M * acceleration_n therefore solution = increment acceleration not acceleration */ solveLumped(*increment_acceleration, *mass, *residual, *blocked_dofs, f_m2a); } else if (method == _explicit_consistent_mass) { solve(*increment_acceleration); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveLumped(Array & x, const Array & A, const Array & b, const Array & blocked_dofs, Real alpha) { Real * A_val = A.storage(); Real * b_val = b.storage(); Real * x_val = x.storage(); bool * blocked_dofs_val = blocked_dofs.storage(); UInt nb_degrees_of_freedom = x.getSize() * x.getNbComponent(); for (UInt n = 0; n < nb_degrees_of_freedom; ++n) { if(!(*blocked_dofs_val)) { *x_val = alpha * (*b_val / *A_val); } x_val++; A_val++; b_val++; blocked_dofs_val++; } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::explicitPred() { AKANTU_DEBUG_IN(); if(increment_flag) { if(previous_displacement) increment->copy(*previous_displacement); else increment->copy(*displacement); } AKANTU_DEBUG_ASSERT(integrator,"itegrator should have been allocated: " << "have called initExplicit ? " << "or initImplicit ?"); integrator->integrationSchemePred(time_step, *displacement, *velocity, *acceleration, *blocked_dofs); if(increment_flag) { Real * inc_val = increment->storage(); Real * dis_val = displacement->storage(); UInt nb_degree_of_freedom = displacement->getSize() * displacement->getNbComponent(); for (UInt n = 0; n < nb_degree_of_freedom; ++n) { *inc_val = *dis_val - *inc_val; inc_val++; dis_val++; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::explicitCorr() { AKANTU_DEBUG_IN(); integrator->integrationSchemeCorrAccel(time_step, *displacement, *velocity, *acceleration, *blocked_dofs, *increment_acceleration); if(previous_displacement) previous_displacement->copy(*displacement); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveStep() { AKANTU_DEBUG_IN(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeSolveStepEvent(method)); this->explicitPred(); this->updateResidual(); this->updateAcceleration(); this->explicitCorr(); EventManager::sendEvent(SolidMechanicsModelEvent::AfterSolveStepEvent(method)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Implicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /** * Initialize the solver and create the sparse matrices needed. * */ void SolidMechanicsModel::initSolver(__attribute__((unused)) SolverOptions & options) { #if !defined(AKANTU_USE_MUMPS) && !defined(AKANTU_USE_PETSC)// or other solver in the future \todo add AKANTU_HAS_SOLVER in CMake AKANTU_DEBUG_ERROR("You should at least activate one solver."); #else UInt nb_global_nodes = mesh.getNbGlobalNodes(); delete jacobian_matrix; std::stringstream sstr; sstr << id << ":jacobian_matrix"; #ifdef AKANTU_USE_PETSC jacobian_matrix = new PETScMatrix(nb_global_nodes * spatial_dimension, _symmetric, sstr.str(), memory_id); #else jacobian_matrix = new SparseMatrix(nb_global_nodes * spatial_dimension, _symmetric, sstr.str(), memory_id); #endif //AKANTU_USE PETSC jacobian_matrix->buildProfile(mesh, *dof_synchronizer, spatial_dimension); if (!isExplicit()) { delete stiffness_matrix; std::stringstream sstr_sti; sstr_sti << id << ":stiffness_matrix"; #ifdef AKANTU_USE_PETSC stiffness_matrix = new SparseMatrix(nb_global_nodes * spatial_dimension, _symmetric, sstr.str(), memory_id); stiffness_matrix->buildProfile(mesh, *dof_synchronizer, spatial_dimension); #else stiffness_matrix = new SparseMatrix(*jacobian_matrix, sstr_sti.str(), memory_id); #endif //AKANTU_USE_PETSC } delete solver; std::stringstream sstr_solv; sstr_solv << id << ":solver"; #ifdef AKANTU_USE_PETSC solver = new SolverPETSc(*jacobian_matrix, sstr_solv.str()); #elif defined(AKANTU_USE_MUMPS) solver = new SolverMumps(*jacobian_matrix, sstr_solv.str()); dof_synchronizer->initScatterGatherCommunicationScheme(); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif //AKANTU_USE_MUMPS if(solver) solver->initialize(options); #endif //AKANTU_HAS_SOLVER } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initJacobianMatrix() { #if defined(AKANTU_USE_MUMPS) && !defined(AKANTU_USE_PETSC) // @todo make it more flexible: this is an ugly patch to treat the case of non // fix profile of the K matrix delete jacobian_matrix; std::stringstream sstr_sti; sstr_sti << id << ":jacobian_matrix"; jacobian_matrix = new SparseMatrix(*stiffness_matrix, sstr_sti.str(), memory_id); std::stringstream sstr_solv; sstr_solv << id << ":solver"; delete solver; solver = new SolverMumps(*jacobian_matrix, sstr_solv.str()); if(solver) solver->initialize(_solver_no_options); #else AKANTU_DEBUG_ERROR("You need to activate the solver mumps."); #endif } /* -------------------------------------------------------------------------- */ /** * Initialize the implicit solver, either for dynamic or static cases, * * @param dynamic */ void SolidMechanicsModel::initImplicit(bool dynamic, SolverOptions & solver_options) { AKANTU_DEBUG_IN(); method = dynamic ? _implicit_dynamic : _static; if (!increment) setIncrementFlagOn(); initSolver(solver_options); if(method == _implicit_dynamic) { if(integrator) delete integrator; integrator = new TrapezoidalRule2(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initialAcceleration() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving Ma = f"); Solver * acc_solver = NULL; std::stringstream sstr; sstr << id << ":tmp_mass_matrix"; SparseMatrix * tmp_mass = new SparseMatrix(*mass_matrix, sstr.str(), memory_id); #ifdef AKANTU_USE_MUMPS std::stringstream sstr_solver; sstr << id << ":solver_mass_matrix"; acc_solver = new SolverMumps(*mass_matrix, sstr_solver.str()); dof_synchronizer->initScatterGatherCommunicationScheme(); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif //AKANTU_USE_MUMPS acc_solver->initialize(); tmp_mass->applyBoundary(*blocked_dofs); acc_solver->setRHS(*residual); acc_solver->solve(*acceleration); delete acc_solver; delete tmp_mass; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleStiffnessMatrix() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Assemble the new stiffness matrix."); stiffness_matrix->clear(); // call compute stiffness matrix on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->assembleStiffnessMatrix(_not_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseMatrix & SolidMechanicsModel::initVelocityDampingMatrix() { if(!velocity_damping_matrix) velocity_damping_matrix = new SparseMatrix(*jacobian_matrix, id + ":velocity_damping_matrix", memory_id); return *velocity_damping_matrix; } /* -------------------------------------------------------------------------- */ template<> bool SolidMechanicsModel::testConvergence<_scc_increment>(Real tolerance, Real & error){ AKANTU_DEBUG_IN(); UInt nb_nodes = displacement->getSize(); UInt nb_degree_of_freedom = displacement->getNbComponent(); error = 0; Real norm[2] = {0., 0.}; Real * increment_val = increment->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); Real * displacement_val = displacement->storage(); for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); for (UInt d = 0; d < nb_degree_of_freedom; ++d) { if(!(*blocked_dofs_val) && is_local_node) { norm[0] += *increment_val * *increment_val; norm[1] += *displacement_val * *displacement_val; } blocked_dofs_val++; increment_val++; displacement_val++; } } StaticCommunicator::getStaticCommunicator().allReduce(norm, 2, _so_sum); norm[0] = sqrt(norm[0]); norm[1] = sqrt(norm[1]); AKANTU_DEBUG_ASSERT(!Math::isnan(norm[0]), "Something goes wrong in the solve phase"); if (norm[1] < Math::getTolerance()) { error = norm[0]; AKANTU_DEBUG_OUT(); // cout<<"Error 1: "< Math::getTolerance()) error = norm[0] / norm[1]; else error = norm[0]; //In case the total displacement is zero! // cout<<"Error 2: "< bool SolidMechanicsModel::testConvergence<_scc_residual>(Real tolerance, Real & norm) { AKANTU_DEBUG_IN(); UInt nb_nodes = residual->getSize(); UInt nb_degree_of_freedom = displacement->getNbComponent(); norm = 0; Real * residual_val = residual->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); if(is_local_node) { for (UInt d = 0; d < nb_degree_of_freedom; ++d) { if(!(*blocked_dofs_val)) { norm += *residual_val * *residual_val; } blocked_dofs_val++; residual_val++; } } else { blocked_dofs_val += spatial_dimension; residual_val += spatial_dimension; } } StaticCommunicator::getStaticCommunicator().allReduce(&norm, 1, _so_sum); norm = sqrt(norm); AKANTU_DEBUG_ASSERT(!Math::isnan(norm), "Something goes wrong in the solve phase"); AKANTU_DEBUG_OUT(); return (norm < tolerance); } /* -------------------------------------------------------------------------- */ template<> bool SolidMechanicsModel::testConvergence<_scc_residual_mass_wgh>(Real tolerance, Real & norm) { AKANTU_DEBUG_IN(); UInt nb_nodes = residual->getSize(); norm = 0; Real * residual_val = residual->storage(); Real * mass_val = this->mass->storage(); bool * blocked_dofs_val = blocked_dofs->storage(); for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); if(is_local_node) { for (UInt d = 0; d < spatial_dimension; ++d) { if(!(*blocked_dofs_val)) { norm += *residual_val * *residual_val/(*mass_val * *mass_val); } blocked_dofs_val++; residual_val++; mass_val++; } } else { blocked_dofs_val += spatial_dimension; residual_val += spatial_dimension; mass_val += spatial_dimension; } } StaticCommunicator::getStaticCommunicator().allReduce(&norm, 1, _so_sum); norm = sqrt(norm); AKANTU_DEBUG_ASSERT(!Math::isnan(norm), "Something goes wrong in the solve phase"); AKANTU_DEBUG_OUT(); return (norm < tolerance); } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceResidual(Real tolerance){ AKANTU_DEBUG_IN(); Real error=0; bool res = this->testConvergence<_scc_residual>(tolerance, error); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceResidual(Real tolerance, Real & error){ AKANTU_DEBUG_IN(); bool res = this->testConvergence<_scc_residual>(tolerance, error); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance){ AKANTU_DEBUG_IN(); Real error=0; bool res = this->testConvergence<_scc_increment>(tolerance, error); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance, Real & error){ AKANTU_DEBUG_IN(); bool res = this->testConvergence<_scc_increment>(tolerance, error); AKANTU_DEBUG_OUT(); return res; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::implicitPred() { AKANTU_DEBUG_IN(); if(previous_displacement) previous_displacement->copy(*displacement); if(method == _implicit_dynamic) integrator->integrationSchemePred(time_step, *displacement, *velocity, *acceleration, *blocked_dofs); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::implicitCorr() { AKANTU_DEBUG_IN(); if(method == _implicit_dynamic) { integrator->integrationSchemeCorrDispl(time_step, *displacement, *velocity, *acceleration, *blocked_dofs, *increment); } else { UInt nb_nodes = displacement->getSize(); UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes; Real * incr_val = increment->storage(); Real * disp_val = displacement->storage(); bool * boun_val = blocked_dofs->storage(); for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++disp_val, ++incr_val, ++boun_val){ *incr_val *= (1. - *boun_val); *disp_val += *incr_val; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateIncrement() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(previous_displacement,"The previous displacement has to be initialized." << " Are you working with Finite or Ineslactic deformations?"); UInt nb_nodes = displacement->getSize(); UInt nb_degree_of_freedom = displacement->getNbComponent() * nb_nodes; Real * incr_val = increment->storage(); Real * disp_val = displacement->storage(); Real * prev_disp_val = previous_displacement->storage(); for (UInt j = 0; j < nb_degree_of_freedom; ++j, ++disp_val, ++incr_val, ++prev_disp_val) *incr_val = (*disp_val - *prev_disp_val); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updatePreviousDisplacement() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(previous_displacement,"The previous displacement has to be initialized." << " Are you working with Finite or Ineslactic deformations?"); previous_displacement->copy(*displacement); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Information */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::synchronizeBoundaries() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(synch_registry,"Synchronizer registry was not initialized." << " Did you call initParallel?"); synch_registry->synchronize(_gst_smm_boundary); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::synchronizeResidual() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(synch_registry,"Synchronizer registry was not initialized." << " Did you call initPBC?"); synch_registry->synchronize(_gst_smm_res); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::setIncrementFlagOn() { AKANTU_DEBUG_IN(); if(!increment) { UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_inc; sstr_inc << id << ":increment"; increment = &(alloc(sstr_inc.str(), nb_nodes, spatial_dimension, 0.)); } increment_flag = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getStableTimeStep() { AKANTU_DEBUG_IN(); Real min_dt = getStableTimeStep(_not_ghost); /// reduction min over all processors StaticCommunicator::getStaticCommunicator().allReduce(&min_dt, 1, _so_min); AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getStableTimeStep(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); Material ** mat_val = &(materials.at(0)); Real min_dt = std::numeric_limits::max(); updateCurrentPosition(); Element elem; elem.ghost_type = ghost_type; elem.kind = _ek_regular; Mesh::type_iterator it = mesh.firstType(spatial_dimension, ghost_type); Mesh::type_iterator end = mesh.lastType(spatial_dimension, ghost_type); for(; it != end; ++it) { elem.type = *it; UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*it); UInt nb_element = mesh.getNbElement(*it); Array::const_scalar_iterator mat_indexes = material_index(*it, ghost_type).begin(); Array::const_scalar_iterator mat_loc_num = material_local_numbering(*it, ghost_type).begin(); Array X(0, nb_nodes_per_element*spatial_dimension); FEEngine::extractNodalToElementField(mesh, *current_position, X, *it, _not_ghost); Array::matrix_iterator X_el = X.begin(spatial_dimension, nb_nodes_per_element); for (UInt el = 0; el < nb_element; ++el, ++X_el, ++mat_indexes, ++mat_loc_num) { elem.element = *mat_loc_num; Real el_h = getFEEngine().getElementInradius(*X_el, *it); Real el_c = mat_val[*mat_indexes]->getCelerity(elem); Real el_dt = el_h / el_c; min_dt = std::min(min_dt, el_dt); } } AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getPotentialEnergy() { AKANTU_DEBUG_IN(); Real energy = 0.; /// call update residual on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { energy += (*mat_it)->getPotentialEnergy(); } /// reduction sum over all processors StaticCommunicator::getStaticCommunicator().allReduce(&energy, 1, _so_sum); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy() { AKANTU_DEBUG_IN(); if (!mass && !mass_matrix) AKANTU_DEBUG_ERROR("No function called to assemble the mass matrix."); Real ekin = 0.; UInt nb_nodes = mesh.getNbNodes(); Real * vel_val = velocity->storage(); Real * mass_val = mass->storage(); for (UInt n = 0; n < nb_nodes; ++n) { Real mv2 = 0; bool is_local_node = mesh.isLocalOrMasterNode(n); bool is_not_pbc_slave_node = !isPBCSlaveNode(n); bool count_node = is_local_node && is_not_pbc_slave_node; for (UInt i = 0; i < spatial_dimension; ++i) { if (count_node) mv2 += *vel_val * *vel_val * *mass_val; vel_val++; mass_val++; } ekin += mv2; } StaticCommunicator::getStaticCommunicator().allReduce(&ekin, 1, _so_sum); AKANTU_DEBUG_OUT(); return ekin * .5; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy(const ElementType & type, UInt index) { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = getFEEngine().getNbQuadraturePoints(type); Array vel_on_quad(nb_quadrature_points, spatial_dimension); Array filter_element(1, 1, index); getFEEngine().interpolateOnQuadraturePoints(*velocity, vel_on_quad, spatial_dimension, type, _not_ghost, filter_element); Array::vector_iterator vit = vel_on_quad.begin(spatial_dimension); Array::vector_iterator vend = vel_on_quad.end(spatial_dimension); Vector rho_v2(nb_quadrature_points); Real rho = materials[material_index(type)(index)]->getRho(); for (UInt q = 0; vit != vend; ++vit, ++q) { rho_v2(q) = rho * vit->dot(*vit); } AKANTU_DEBUG_OUT(); return .5*getFEEngine().integrate(rho_v2, type, index); } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getExternalWork() { AKANTU_DEBUG_IN(); Real * velo = velocity->storage(); Real * forc = force->storage(); Real * resi = residual->storage(); bool * boun = blocked_dofs->storage(); Real work = 0.; UInt nb_nodes = mesh.getNbNodes(); for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); bool is_not_pbc_slave_node = !isPBCSlaveNode(n); bool count_node = is_local_node && is_not_pbc_slave_node; for (UInt i = 0; i < spatial_dimension; ++i) { if (count_node) { if(*boun) work -= *resi * *velo * time_step; else work += *forc * *velo * time_step; } ++velo; ++forc; ++resi; ++boun; } } StaticCommunicator::getStaticCommunicator().allReduce(&work, 1, _so_sum); AKANTU_DEBUG_OUT(); return work; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getEnergy(const std::string & energy_id) { AKANTU_DEBUG_IN(); if (energy_id == "kinetic") { return getKineticEnergy(); } else if (energy_id == "external work"){ return getExternalWork(); } Real energy = 0.; std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { energy += (*mat_it)->getEnergy(energy_id); } /// reduction sum over all processors StaticCommunicator::getStaticCommunicator().allReduce(&energy, 1, _so_sum); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getEnergy(const std::string & energy_id, const ElementType & type, UInt index){ AKANTU_DEBUG_IN(); if (energy_id == "kinetic") { return getKineticEnergy(type, index); } std::vector::iterator mat_it; UInt mat_index = this->material_index(type, _not_ghost)(index); UInt mat_loc_num = this->material_local_numbering(type, _not_ghost)(index); Real energy = this->materials[mat_index]->getEnergy(energy_id, type, mat_loc_num); AKANTU_DEBUG_OUT(); return energy; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onElementsAdded(const Array & element_list, const NewElementsEvent & event) { AKANTU_DEBUG_IN(); this->getFEEngine().initShapeFunctions(_not_ghost); this->getFEEngine().initShapeFunctions(_ghost); for(UInt g = _not_ghost; g <= _ghost; ++g) { GhostType gt = (GhostType) g; Mesh::type_iterator it = this->mesh.firstType(spatial_dimension, gt, _ek_not_defined); Mesh::type_iterator end = this->mesh.lastType(spatial_dimension, gt, _ek_not_defined); for(; it != end; ++it) { UInt nb_element = this->mesh.getNbElement(*it, gt); if(!material_index.exists(*it, gt)) { this->material_index .alloc(nb_element, 1, *it, gt); this->material_local_numbering.alloc(nb_element, 1, *it, gt); } else { this->material_index (*it, gt).resize(nb_element); this->material_local_numbering(*it, gt).resize(nb_element); } } } Array::const_iterator it = element_list.begin(); Array::const_iterator end = element_list.end(); ElementTypeMapArray filter("new_element_filter", this->getID()); for (UInt el = 0; it != end; ++it, ++el) { const Element & elem = *it; if(!filter.exists(elem.type, elem.ghost_type)) filter.alloc(0, 1, elem.type, elem.ghost_type); filter(elem.type, elem.ghost_type).push_back(elem.element); } this->assignMaterialToElements(&filter); std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->onElementsAdded(element_list, event); } if(method == _explicit_lumped_mass) this->assembleMassLumped(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onElementsRemoved(__attribute__((unused)) const Array & element_list, const ElementTypeMapArray & new_numbering, const RemovedElementsEvent & event) { this->getFEEngine().initShapeFunctions(_not_ghost); this->getFEEngine().initShapeFunctions(_ghost); std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->onElementsRemoved(element_list, new_numbering, event); } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onNodesAdded(const Array & nodes_list, __attribute__((unused)) const NewNodesEvent & event) { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); if(displacement) displacement->resize(nb_nodes); if(mass ) mass ->resize(nb_nodes); if(velocity ) velocity ->resize(nb_nodes); if(acceleration) acceleration->resize(nb_nodes); if(force ) force ->resize(nb_nodes); if(residual ) residual ->resize(nb_nodes); if(blocked_dofs) blocked_dofs->resize(nb_nodes); if(previous_displacement) previous_displacement->resize(nb_nodes); if(increment_acceleration) increment_acceleration->resize(nb_nodes); if(increment) increment->resize(nb_nodes); if(current_position) current_position->resize(nb_nodes); delete dof_synchronizer; dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension); dof_synchronizer->initLocalDOFEquationNumbers(); dof_synchronizer->initGlobalDOFEquationNumbers(); std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->onNodesAdded(nodes_list, event); } if (method != _explicit_lumped_mass) { this->initSolver(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onNodesRemoved(__attribute__((unused)) const Array & element_list, const Array & new_numbering, __attribute__((unused)) const RemovedNodesEvent & event) { if(displacement) mesh.removeNodesFromArray(*displacement, new_numbering); if(mass ) mesh.removeNodesFromArray(*mass , new_numbering); if(velocity ) mesh.removeNodesFromArray(*velocity , new_numbering); if(acceleration) mesh.removeNodesFromArray(*acceleration, new_numbering); if(force ) mesh.removeNodesFromArray(*force , new_numbering); if(residual ) mesh.removeNodesFromArray(*residual , new_numbering); if(blocked_dofs) mesh.removeNodesFromArray(*blocked_dofs, new_numbering); if(increment_acceleration) mesh.removeNodesFromArray(*increment_acceleration, new_numbering); if(increment) mesh.removeNodesFromArray(*increment , new_numbering); delete dof_synchronizer; dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension); dof_synchronizer->initLocalDOFEquationNumbers(); dof_synchronizer->initGlobalDOFEquationNumbers(); if (method != _explicit_lumped_mass) { this->initSolver(); } } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::isInternal(const std::string & field_name, const ElementKind & element_kind){ bool is_internal = false; /// check if at least one material contains field_id as an internal for (UInt m = 0; m < materials.size() && !is_internal; ++m) { is_internal |= materials[m]->isInternal(field_name, element_kind); } return is_internal; } /* -------------------------------------------------------------------------- */ ElementTypeMap SolidMechanicsModel::getInternalDataPerElem(const std::string & field_name, const ElementKind & element_kind){ if (!(this->isInternal(field_name,element_kind))) AKANTU_EXCEPTION("unknown internal " << field_name); for (UInt m = 0; m < materials.size() ; ++m) { if (materials[m]->isInternal(field_name, element_kind)) return materials[m]->getInternalDataPerElem(field_name,element_kind); } return ElementTypeMap(); } /* -------------------------------------------------------------------------- */ ElementTypeMapArray & SolidMechanicsModel::flattenInternal(const std::string & field_name, const ElementKind & kind, const GhostType ghost_type){ std::pair key(field_name,kind); if (this->registered_internals.count(key) == 0){ this->registered_internals[key] = new ElementTypeMapArray(field_name,this->id); } ElementTypeMapArray * internal_flat = this->registered_internals[key]; - for (UInt m = 0; m < materials.size(); ++m) - materials[m]->flattenInternal(field_name,*internal_flat,ghost_type,kind); + for (UInt m = 0; m < materials.size(); ++m) { + if (materials[m]->isInternal(field_name, kind)) + materials[m]->flattenInternal(field_name,*internal_flat,ghost_type,kind); + } return *internal_flat; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::flattenAllRegisteredInternals(const ElementKind & kind){ std::map,ElementTypeMapArray *> ::iterator it = this->registered_internals.begin(); std::map,ElementTypeMapArray *>::iterator end = this->registered_internals.end(); while (it != end){ if (kind == it->first.second) this->flattenInternal(it->first.first,kind); ++it; } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::onDump(){ this->flattenAllRegisteredInternals(_ek_regular); } /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER dumper::Field * SolidMechanicsModel ::createElementalField(const std::string & field_name, const std::string & group_name, bool padding_flag, const UInt & spatial_dimension, const ElementKind & kind) { dumper::Field * field = NULL; if(field_name == "partitions") field = mesh.createElementalField(mesh.getConnectivities(),group_name,spatial_dimension,kind); else if(field_name == "material_index") field = mesh.createElementalField(material_index,group_name,spatial_dimension,kind); else { // this copy of field_name is used to compute derivated data such as // strain and von mises stress that are based on grad_u and stress std::string field_name_copy(field_name); if (field_name == "strain" || field_name == "Green strain" || field_name == "principal strain" || field_name == "principal Green strain") field_name_copy = "grad_u"; else if (field_name == "Von Mises stress") field_name_copy = "stress"; bool is_internal = this->isInternal(field_name_copy,kind); if (is_internal) { ElementTypeMap nb_data_per_elem = this->getInternalDataPerElem(field_name_copy,kind); ElementTypeMapArray & internal_flat = this->flattenInternal(field_name_copy,kind); field = mesh.createElementalField(internal_flat, group_name, spatial_dimension,kind,nb_data_per_elem); if (field_name == "strain"){ dumper::ComputeStrain * foo = new dumper::ComputeStrain(*this); field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); } else if (field_name == "Von Mises stress") { dumper::ComputeVonMisesStress * foo = new dumper::ComputeVonMisesStress(*this); field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); } else if (field_name == "Green strain") { dumper::ComputeStrain * foo = new dumper::ComputeStrain(*this); field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); } else if (field_name == "principal strain") { dumper::ComputePrincipalStrain * foo = new dumper::ComputePrincipalStrain(*this); field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); } else if (field_name == "principal Green strain") { dumper::ComputePrincipalStrain * foo = new dumper::ComputePrincipalStrain(*this); field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); } //treat the paddings if (padding_flag){ if (field_name == "stress"){ if (spatial_dimension == 2) { dumper::StressPadder<2> * foo = new dumper::StressPadder<2>(*this); field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); } } else if (field_name == "strain" || field_name == "Green strain"){ if (spatial_dimension == 2) { dumper::StrainPadder<2> * foo = new dumper::StrainPadder<2>(*this); field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); } } } // homogenize the field dumper::ComputeFunctorInterface * foo = dumper::HomogenizerProxy::createHomogenizer(*field); field = dumper::FieldComputeProxy::createFieldCompute(field,*foo); } } return field; } /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createNodalFieldReal(const std::string & field_name, const std::string & group_name, bool padding_flag) { std::map* > real_nodal_fields; real_nodal_fields["displacement" ] = displacement; real_nodal_fields["mass" ] = mass; real_nodal_fields["velocity" ] = velocity; real_nodal_fields["acceleration" ] = acceleration; real_nodal_fields["force" ] = force; real_nodal_fields["residual" ] = residual; real_nodal_fields["increment" ] = increment; dumper::Field * field = NULL; if (padding_flag) field = mesh.createNodalField(real_nodal_fields[field_name],group_name, 3); else field = mesh.createNodalField(real_nodal_fields[field_name],group_name); return field; } /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createNodalFieldBool(const std::string & field_name, const std::string & group_name, bool padding_flag) { std::map* > uint_nodal_fields; uint_nodal_fields["blocked_dofs" ] = blocked_dofs; dumper::Field * field = NULL; field = mesh.createNodalField(uint_nodal_fields[field_name],group_name); return field; } /* -------------------------------------------------------------------------- */ #else /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel ::createElementalField(const std::string & field_name, const std::string & group_name, bool padding_flag, const UInt & spatial_dimension, const ElementKind & kind){ return NULL; } /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createNodalFieldReal(const std::string & field_name, const std::string & group_name, bool padding_flag) { return NULL; } /* -------------------------------------------------------------------------- */ dumper::Field * SolidMechanicsModel::createNodalFieldBool(const std::string & field_name, const std::string & group_name, bool padding_flag) { return NULL; } #endif /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); synch_registry->synchronize(_gst_for_dump); mesh.dump(dumper_name); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name, UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); synch_registry->synchronize(_gst_for_dump); mesh.dump(dumper_name, step); } /* ------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(const std::string & dumper_name, Real time, UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); synch_registry->synchronize(_gst_for_dump); mesh.dump(dumper_name, time, step); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump() { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(step); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::dump(Real time, UInt step) { this->onDump(); EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent()); mesh.dump(time, step); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::computeCauchyStresses() { AKANTU_DEBUG_IN(); // call compute stiffness matrix on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; if(mat.isFiniteDeformation()) mat.computeAllCauchyStresses(_not_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::saveStressAndStrainBeforeDamage() { EventManager::sendEvent(SolidMechanicsModelEvent::BeginningOfDamageIterationEvent()); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateEnergiesAfterDamage() { EventManager::sendEvent(SolidMechanicsModelEvent::AfterDamageEvent()); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Solid Mechanics Model [" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + spatial dimension : " << spatial_dimension << std::endl; stream << space << " + fem [" << std::endl; getFEEngine().printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + nodals information [" << std::endl; displacement->printself(stream, indent + 2); mass ->printself(stream, indent + 2); velocity ->printself(stream, indent + 2); acceleration->printself(stream, indent + 2); force ->printself(stream, indent + 2); residual ->printself(stream, indent + 2); blocked_dofs->printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + material information [" << std::endl; material_index.printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + materials [" << std::endl; std::vector::const_iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { const Material & mat = *(*mat_it); mat.printself(stream, indent + 1); } stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive.cc index cdf29f034..9b33687ea 100644 --- a/src/model/solid_mechanics/solid_mechanics_model_cohesive.cc +++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive.cc @@ -1,705 +1,677 @@ /** * @file solid_mechanics_model_cohesive.cc * * @author Marco Vocialta * @author Nicolas Richart * * @date creation: Tue May 08 2012 * @date last modification: Fri Sep 05 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 . * */ /* -------------------------------------------------------------------------- */ #include #include "shape_cohesive.hh" #include "solid_mechanics_model_cohesive.hh" #include "dumpable_inline_impl.hh" #include "material_cohesive.hh" #ifdef AKANTU_USE_IOHELPER # include "dumper_paraview.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ const SolidMechanicsModelCohesiveOptions default_solid_mechanics_model_cohesive_options(_explicit_lumped_mass, false, false); /* -------------------------------------------------------------------------- */ SolidMechanicsModelCohesive::SolidMechanicsModelCohesive(Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id) : SolidMechanicsModel(mesh, dim, id, memory_id), tangents("tangents", id), facet_stress("facet_stress", id), facet_material("facet_material", id) { AKANTU_DEBUG_IN(); inserter = NULL; #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) facet_synchronizer = NULL; facet_stress_synchronizer = NULL; cohesive_distributed_synchronizer = NULL; global_connectivity = NULL; #endif delete material_selector; material_selector = new DefaultMaterialCohesiveSelector(*this); this->registerEventHandler(*this); #if defined(AKANTU_USE_IOHELPER) this->mesh.registerDumper("cohesive elements", id); this->mesh.addDumpMeshToDumper("cohesive elements", mesh, spatial_dimension, _not_ghost, _ek_cohesive); #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolidMechanicsModelCohesive::~SolidMechanicsModelCohesive() { AKANTU_DEBUG_IN(); delete inserter; #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) delete cohesive_distributed_synchronizer; delete facet_synchronizer; delete facet_stress_synchronizer; #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::setTimeStep(Real time_step) { SolidMechanicsModel::setTimeStep(time_step); #if defined(AKANTU_USE_IOHELPER) this->mesh.getDumper("cohesive elements").setTimeStep(time_step); #endif } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initFull(const ModelOptions & options) { AKANTU_DEBUG_IN(); const SolidMechanicsModelCohesiveOptions & smmc_options = dynamic_cast(options); this->is_extrinsic = smmc_options.extrinsic; if (!inserter) inserter = new CohesiveElementInserter(mesh, is_extrinsic, synch_parallel, id+":cohesive_element_inserter"); SolidMechanicsModel::initFull(options); -#if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) - if (facet_synchronizer != NULL) - inserter->initParallel(facet_synchronizer); -#endif - - if (is_extrinsic) - initAutomaticInsertion(); - AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initMaterials() { AKANTU_DEBUG_IN(); // make sure the material are instantiated if(!are_materials_instantiated) instantiateMaterials(); /// find the first cohesive material UInt cohesive_index = 0; while ((dynamic_cast(materials[cohesive_index]) == NULL) && cohesive_index <= materials.size()) ++cohesive_index; AKANTU_DEBUG_ASSERT(cohesive_index != materials.size(), "No cohesive materials in the material input file"); material_selector->setFallback(cohesive_index); // set the facet information in the material in case of dynamic insertion if (is_extrinsic) { const Mesh & mesh_facets = inserter->getMeshFacets(); mesh_facets.initElementTypeMapArray(facet_material, 1, spatial_dimension - 1); Element element; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { element.ghost_type = *gt; Mesh::type_iterator first = mesh_facets.firstType(spatial_dimension - 1, *gt); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1, *gt); for(;first != last; ++first) { element.type = *first; Array & f_material = facet_material(*first, *gt); UInt nb_element = mesh_facets.getNbElement(*first, *gt); f_material.resize(nb_element); f_material.set(cohesive_index); for (UInt el = 0; el < nb_element; ++el) { element.element = el; UInt mat_index = (*material_selector)(element); f_material(el) = mat_index; MaterialCohesive & mat = dynamic_cast(*materials[mat_index]); mat.addFacet(element); } } } } else { for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { Mesh::type_iterator first = mesh.firstType(spatial_dimension, *gt, _ek_cohesive); Mesh::type_iterator last = mesh.lastType(spatial_dimension, *gt, _ek_cohesive); for(;first != last; ++first) { Array & mat_indexes = this->material_index(*first, *gt); Array & mat_loc_num = this->material_local_numbering(*first, *gt); mat_indexes.set(cohesive_index); mat_loc_num.clear(); } } } SolidMechanicsModel::initMaterials(); +#if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) + if (facet_synchronizer != NULL) + inserter->initParallel(facet_synchronizer); +#endif + + if (is_extrinsic) + initAutomaticInsertion(); + + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Initialize the model,basically it pre-compute the shapes, shapes derivatives * and jacobian * */ void SolidMechanicsModelCohesive::initModel() { AKANTU_DEBUG_IN(); SolidMechanicsModel::initModel(); registerFEEngineObject("CohesiveFEEngine", mesh, spatial_dimension); /// add cohesive type connectivity ElementType type = _not_defined; for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType type_ghost = *gt; Mesh::type_iterator it = mesh.firstType(spatial_dimension, type_ghost); Mesh::type_iterator last = mesh.lastType(spatial_dimension, type_ghost); for (; it != last; ++it) { const Array & connectivity = mesh.getConnectivity(*it, type_ghost); if (connectivity.getSize() != 0) { type = *it; ElementType type_facet = Mesh::getFacetType(type); ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet); mesh.addConnectivityType(type_cohesive, type_ghost); } } } AKANTU_DEBUG_ASSERT(type != _not_defined, "No elements in the mesh"); getFEEngine("CohesiveFEEngine").initShapeFunctions(_not_ghost); getFEEngine("CohesiveFEEngine").initShapeFunctions(_ghost); registerFEEngineObject("FacetsFEEngine", mesh.getMeshFacets(), spatial_dimension - 1); if (is_extrinsic) { getFEEngine("FacetsFEEngine").initShapeFunctions(_not_ghost); getFEEngine("FacetsFEEngine").initShapeFunctions(_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::limitInsertion(BC::Axis axis, Real first_limit, Real second_limit) { AKANTU_DEBUG_IN(); inserter->setLimit(axis, first_limit, second_limit); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::insertIntrinsicElements() { AKANTU_DEBUG_IN(); inserter->insertIntrinsicElements(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initAutomaticInsertion() { AKANTU_DEBUG_IN(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_stress_synchronizer != NULL) { DataAccessor * data_accessor = this; const ElementTypeMapArray & rank_to_element = synch_parallel->getPrankToElement(); facet_stress_synchronizer->updateFacetStressSynchronizer(*inserter, rank_to_element, *data_accessor); } #endif inserter->getMeshFacets().initElementTypeMapArray(facet_stress, 2 * spatial_dimension * spatial_dimension, spatial_dimension - 1); resizeFacetStress(); /// compute normals on facets computeNormals(); initStressInterpolation(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::updateAutomaticInsertion() { AKANTU_DEBUG_IN(); inserter->limitCheckFacets(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (facet_stress_synchronizer != NULL) { DataAccessor * data_accessor = this; const ElementTypeMapArray & rank_to_element = synch_parallel->getPrankToElement(); facet_stress_synchronizer->updateFacetStressSynchronizer(*inserter, rank_to_element, *data_accessor); } #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::initStressInterpolation() { Mesh & mesh_facets = inserter->getMeshFacets(); /// compute quadrature points coordinates on facets Array & position = mesh.getNodes(); ElementTypeMapArray quad_facets("quad_facets", id); mesh_facets.initElementTypeMapArray(quad_facets, spatial_dimension, spatial_dimension - 1); getFEEngine("FacetsFEEngine").interpolateOnQuadraturePoints(position, quad_facets); /// compute elements quadrature point positions and build /// element-facet quadrature points data structure ElementTypeMapArray elements_quad_facets("elements_quad_facets", id); mesh.initElementTypeMapArray(elements_quad_facets, spatial_dimension, spatial_dimension); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType elem_gt = *gt; Mesh::type_iterator it = mesh.firstType(spatial_dimension, elem_gt); Mesh::type_iterator last = mesh.lastType(spatial_dimension, elem_gt); for (; it != last; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type, elem_gt); if (nb_element == 0) continue; /// compute elements' quadrature points and list of facet /// quadrature points positions by element Array & facet_to_element = mesh_facets.getSubelementToElement(type, elem_gt); UInt nb_facet_per_elem = facet_to_element.getNbComponent(); Array & el_q_facet = elements_quad_facets(type, elem_gt); ElementType facet_type = Mesh::getFacetType(type); UInt nb_quad_per_facet = getFEEngine("FacetsFEEngine").getNbQuadraturePoints(facet_type); el_q_facet.resize(nb_element * nb_facet_per_elem * nb_quad_per_facet); for (UInt el = 0; el < nb_element; ++el) { for (UInt f = 0; f < nb_facet_per_elem; ++f) { Element global_facet_elem = facet_to_element(el, f); UInt global_facet = global_facet_elem.element; GhostType facet_gt = global_facet_elem.ghost_type; const Array & quad_f = quad_facets(facet_type, facet_gt); for (UInt q = 0; q < nb_quad_per_facet; ++q) { for (UInt s = 0; s < spatial_dimension; ++s) { el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet + f * nb_quad_per_facet + q, s) = quad_f(global_facet * nb_quad_per_facet + q, s); } } } } } } /// loop over non cohesive materials for (UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat __attribute__((unused)) = dynamic_cast(*materials[m]); } catch(std::bad_cast&) { /// initialize the interpolation function materials[m]->initElementalFieldInterpolation(elements_quad_facets); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::updateResidual(bool need_initialize) { AKANTU_DEBUG_IN(); if (need_initialize) initializeUpdateResidualData(); // f -= fint std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { try { MaterialCohesive & mat = dynamic_cast(**mat_it); mat.computeTraction(_not_ghost); } catch (std::bad_cast & bce) { } } SolidMechanicsModel::updateResidual(false); for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { try { MaterialCohesive & mat = dynamic_cast(**mat_it); mat.computeEnergies(); } catch (std::bad_cast & bce) { } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::computeNormals() { AKANTU_DEBUG_IN(); - Mesh & mesh_facets = inserter->getMeshFacets(); - getFEEngine("FacetsFEEngine").computeNormalsOnControlPoints(_not_ghost); + Mesh & mesh_facets = this->inserter->getMeshFacets(); + this->getFEEngine("FacetsFEEngine").computeNormalsOnControlPoints(_not_ghost); /** * @todo store tangents while computing normals instead of * recomputing them as follows: */ /* ------------------------------------------------------------------------ */ UInt tangent_components = spatial_dimension * (spatial_dimension - 1); mesh_facets.initElementTypeMapArray(tangents, tangent_components, spatial_dimension - 1); Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1); Mesh::type_iterator last = mesh_facets.lastType(spatial_dimension - 1); for (; it != last; ++it) { ElementType facet_type = *it; const Array & normals = - getFEEngine("FacetsFEEngine").getNormalsOnQuadPoints(facet_type); - - UInt nb_quad = normals.getSize(); - - Array & tang = tangents(facet_type); - tang.resize(nb_quad); - - Real * normal_it = normals.storage(); - Real * tangent_it = tang.storage(); + this->getFEEngine("FacetsFEEngine").getNormalsOnQuadPoints(facet_type); - /// compute first tangent - for (UInt q = 0; q < nb_quad; ++q) { + Array & tangents = this->tangents(facet_type); - /// if normal is orthogonal to xy plane, arbitrarly define tangent - if ( Math::are_float_equal(Math::norm2(normal_it), 0) ) - tangent_it[0] = 1; - else - Math::normal2(normal_it, tangent_it); - - normal_it += spatial_dimension; - tangent_it += tangent_components; - } - - /// compute second tangent (3D case) - if (spatial_dimension == 3) { - normal_it = normals.storage(); - tangent_it = tang.storage(); - - for (UInt q = 0; q < nb_quad; ++q) { - Math::normal3(normal_it, tangent_it, tangent_it + spatial_dimension); - normal_it += spatial_dimension; - tangent_it += tangent_components; - } - } + Math::compute_tangents(normals, tangents); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::interpolateStress() { for (UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat __attribute__((unused)) = dynamic_cast(*materials[m]); } catch(std::bad_cast&) { /// interpolate stress on facet quadrature points positions materials[m]->interpolateStressOnFacets(facet_stress); } } #if defined(AKANTU_DEBUG_TOOLS) debug::element_manager.printData(debug::_dm_model_cohesive, "Interpolated stresses before", facet_stress); #endif synch_registry->synchronize(_gst_smmc_facets_stress); #if defined(AKANTU_DEBUG_TOOLS) debug::element_manager.printData(debug::_dm_model_cohesive, "Interpolated stresses", facet_stress); #endif } /* -------------------------------------------------------------------------- */ UInt SolidMechanicsModelCohesive::checkCohesiveStress() { interpolateStress(); for (UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat_cohesive = dynamic_cast(*materials[m]); /// check which not ghost cohesive elements are to be created mat_cohesive.checkInsertion(); } catch(std::bad_cast&) { } } /* if(static and extrinsic) { check max mean stresses and change inserter.getInsertionFacets(type_facet); } */ /// communicate data among processors synch_registry->synchronize(_gst_smmc_facets); /// insert cohesive elements return inserter->insertElements(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onElementsAdded(const Array & element_list, const NewElementsEvent & event) { AKANTU_DEBUG_IN(); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) updateCohesiveSynchronizers(); #endif SolidMechanicsModel::onElementsAdded(element_list, event); #if defined(AKANTU_PARALLEL_COHESIVE_ELEMENT) if (cohesive_distributed_synchronizer != NULL) cohesive_distributed_synchronizer->computeAllBufferSizes(*this); #endif /// update shape functions getFEEngine("CohesiveFEEngine").initShapeFunctions(_not_ghost); getFEEngine("CohesiveFEEngine").initShapeFunctions(_ghost); if (is_extrinsic) resizeFacetStress(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onNodesAdded(const Array & doubled_nodes, __attribute__((unused)) const NewNodesEvent & event) { AKANTU_DEBUG_IN(); UInt nb_new_nodes = doubled_nodes.getSize(); Array nodes_list(nb_new_nodes); for (UInt n = 0; n < nb_new_nodes; ++n) nodes_list(n) = doubled_nodes(n, 1); SolidMechanicsModel::onNodesAdded(nodes_list, event); for (UInt n = 0; n < nb_new_nodes; ++n) { UInt old_node = doubled_nodes(n, 0); UInt new_node = doubled_nodes(n, 1); for (UInt dim = 0; dim < spatial_dimension; ++dim) { (*displacement)(new_node, dim) = (*displacement)(old_node, dim); (*velocity) (new_node, dim) = (*velocity) (old_node, dim); (*acceleration)(new_node, dim) = (*acceleration)(old_node, dim); (*blocked_dofs)(new_node, dim) = (*blocked_dofs)(old_node, dim); if (current_position) (*current_position)(new_node, dim) = (*current_position)(old_node, dim); if (increment_acceleration) (*increment_acceleration)(new_node, dim) = (*increment_acceleration)(old_node, dim); if (increment) (*increment)(new_node, dim) = (*increment)(old_node, dim); if (previous_displacement) (*previous_displacement)(new_node, dim) = (*previous_displacement)(old_node, dim); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onEndSolveStep(const AnalysisMethod & method) { AKANTU_DEBUG_IN(); /****************************************************************************** This is required because the Cauchy stress is the stress measure that is used to check the insertion of cohesive elements ******************************************************************************/ std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { Material & mat = **mat_it; if(mat.isFiniteDeformation()) mat.computeAllCauchyStresses(_not_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "SolidMechanicsModelCohesive [" << std::endl; SolidMechanicsModel::printself(stream, indent + 1); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::resizeFacetStress() { AKANTU_DEBUG_IN(); Mesh & mesh_facets = inserter->getMeshFacets(); for (ghost_type_t::iterator gt = ghost_type_t::begin(); gt != ghost_type_t::end(); ++gt) { GhostType ghost_type = *gt; Mesh::type_iterator it = mesh_facets.firstType(spatial_dimension - 1, ghost_type); Mesh::type_iterator end = mesh_facets.lastType(spatial_dimension - 1, ghost_type); for(; it != end; ++it) { ElementType type = *it; UInt nb_facet = mesh_facets.getNbElement(type, ghost_type); UInt nb_quadrature_points = getFEEngine("FacetsFEEngine").getNbQuadraturePoints(type, ghost_type); UInt new_size = nb_facet * nb_quadrature_points; facet_stress(type, ghost_type).resize(new_size); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::addDumpGroupFieldToDumper(const std::string & dumper_name, const std::string & field_id, const std::string & group_name, const ElementKind & element_kind, bool padding_flag) { AKANTU_DEBUG_IN(); ElementKind _element_kind = element_kind; if (dumper_name == "cohesive elements") { _element_kind = _ek_cohesive; } SolidMechanicsModel::addDumpGroupFieldToDumper(dumper_name, field_id, group_name, _element_kind, padding_flag); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModelCohesive::onDump(){ this->flattenAllRegisteredInternals(_ek_cohesive); SolidMechanicsModel::onDump(); } /* -------------------------------------------------------------------------- */ __END_AKANTU__ 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 9447f3f2c..09c648b73 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,263 +1,261 @@ /** * @file solid_mechanics_model_cohesive_inline_impl.cc * * @author Mauro Corrado * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include -#include "shape_cohesive.hh" -#include "solid_mechanics_model_cohesive.hh" #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 bool SolidMechanicsModelCohesive::solveStepCohesive(Real tolerance, Real & error, UInt max_iteration, UInt cont, bool do_not_factorize) { EventManager::sendEvent(SolidMechanicsModelEvent::BeforeSolveStepEvent(method)); this->implicitPred(); bool insertion_new_element = true; bool converged = false; Array * displacement_tmp = NULL; Array * velocity_tmp = NULL; Array * 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 * tmp_swap; if(!displacement_tmp) { displacement_tmp = new Array(*(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(*(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(*(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 (tolerance, error); if(converged) return converged; } do { if (cmethod == _scm_newton_raphson_tangent) this->assembleStiffnessMatrix(); solve (*increment, 1., need_factorize); this->implicitCorr(); this->updateResidual(); converged = this->testConvergence (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 * 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){ // || 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_cohesive_elements = checkCohesiveStress(); // 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); // 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 << "No. cohesive elements inserted = " << new_cohesive_elements << std::endl; } } } if (!converged){ // && !load_reduction){ insertion_new_element = false; for (UInt m = 0; m < materials.size(); ++m) { try { MaterialCohesive & mat = dynamic_cast(*materials[m]); mat.checkDeltaMax(_not_ghost); } catch(std::bad_cast&) { } } } } //end while insertion_new_element 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/CMakeLists.txt b/test/CMakeLists.txt index be0c5088a..09c9fcf25 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,88 +1,87 @@ #=============================================================================== # @file CMakeLists.txt # # @author Guillaume Anciaux # @author Alejandro M. Aragón # @author Nicolas Richart # # @date creation: Fri Sep 03 2010 # @date last modification: Thu Jul 03 2014 # # @brief configuration for 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 . # # @section DESCRIPTION # #=============================================================================== include_directories( ${AKANTU_INCLUDE_DIRS} ${AKANTU_EXTERNAL_LIB_INCLUDE_DIR} ) set(AKANTU_TESTS_FILES CACHE INTERNAL "") #=============================================================================== # List of tests #=============================================================================== add_akantu_test(test_common "Test the common part of Akantu") add_akantu_test(test_static_memory "Test static memory") add_akantu_test(test_fem "Test finite element functionalties") add_akantu_test(test_mesh_utils "Test mesh utils") add_akantu_test(test_model "Test model objects") add_akantu_test(test_solver "Test solver function") add_akantu_test(test_io "Test the IO modules") add_akantu_test(test_contact "Test the contact part of Akantu") add_akantu_test(test_geometry "Test the geometry module of Akantu") -add_akantu_test(test_surface_extraction "Test mesh utils surface extraction") add_akantu_test(test_synchronizer "Test synchronizers") file(GLOB_RECURSE __all_files "*.*") set(_all_files) foreach(_file ${__all_files}) if("${_file}" MATCHES "${PROJECT_SOURCE_DIR}/test") file(RELATIVE_PATH __file ${PROJECT_SOURCE_DIR} ${_file}) list(APPEND _all_files ${__file}) endif() endforeach() file(GLOB_RECURSE __all_files "*CMakeLists.txt") foreach(_file ${__all_files}) if("${_file}" MATCHES "${PROJECT_SOURCE_DIR}/test") file(RELATIVE_PATH __file ${PROJECT_SOURCE_DIR} ${_file}) list(APPEND _cmakes ${__file}) endif() endforeach() list(APPEND AKANTU_TESTS_FILES ${_cmakes}) foreach(_file ${_all_files}) list(FIND AKANTU_TESTS_FILES ${_file} _ret) if(_ret EQUAL -1) list(APPEND AKANTU_TESTS_EXCLUDE_FILES /${_file}) endif() endforeach() set(AKANTU_TESTS_EXCLUDE_FILES ${AKANTU_TESTS_EXCLUDE_FILES} PARENT_SCOPE) #foreach(f ${AKANTU_TESTS_EXCLUDE_FILES}) # message(${f}) #endforeach() diff --git a/test/test_common/CMakeLists.txt b/test/test_common/CMakeLists.txt index 2935e8141..134a7fbf1 100644 --- a/test/test_common/CMakeLists.txt +++ b/test/test_common/CMakeLists.txt @@ -1,40 +1,41 @@ #=============================================================================== # @file CMakeLists.txt # # @author Nicolas Richart # # @date creation: Mon Jul 30 2012 # @date last modification: Fri Feb 21 2014 # # @brief configurations for common 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 . # #=============================================================================== add_akantu_test(test_vector "Test akantu vector") add_mesh(test_grid_mesh circle.geo 2 1) register_test(test_csr test_csr.cc PACKAGE core) register_test(test_grid test_grid.cc DEPENDENCIES test_grid_mesh PACKAGE core) -register_test(test_math test_math.cc PACKAGE core) \ No newline at end of file +register_test(test_math test_math.cc PACKAGE core) +register_test(test_types test_types.cc PACKAGE core) \ No newline at end of file diff --git a/test/test_common/test_types.cc b/test/test_common/test_types.cc new file mode 100644 index 000000000..53bb2dcc5 --- /dev/null +++ b/test/test_common/test_types.cc @@ -0,0 +1,348 @@ +/** + * @file test_types.cc + * + * @author Nicolas Richart + * + * @date Mon May 4 14:02:59 2015 + * + * @brief Test the types declared in aka_types.hh + * + * @section LICENSE + * + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see . + * + */ + +/* -------------------------------------------------------------------------- */ +#include "aka_common.hh" +#include "aka_types.hh" + +#include +#include +#include + +using namespace akantu; + + +const Real tolerance = 1e-15; + +std::string itoa(UInt a) { + std::stringstream sstr; + sstr << a; + return sstr.str(); +} + +UInt testcounter = 0; + +struct wrap_error : std::runtime_error { + wrap_error(const std::string & msg) : std::runtime_error(msg) {} +}; + +struct size_error : std::runtime_error { + size_error(const std::string & msg) : std::runtime_error(msg) {} +}; + +struct data_error : std::runtime_error { + data_error(const std::string & msg, UInt i) : std::runtime_error(msg), index(i) {} + UInt index; +}; + + +template +void compare_storages_with_ref(const type & a, Real * ref, UInt size, UInt line, const std::string & txt) { + std::cout << std::setw(3) << (testcounter++) << ": " << std::setw(10) << txt << " - " << a + << " - wrapped: " << std::boolalpha << a.isWrapped() << std::endl; + + if (a.size() != size) + throw size_error("the size is not correct " + itoa(a.size()) + + " instead of " + itoa(size) + + " [Test at line: " + itoa(line) + "]"); + + Real * a_ptr = a.storage(); + for (UInt i = 0; i < a.size(); ++i) { + if (!((std::abs(a_ptr[i]) < tolerance && std::abs(ref[i]) < tolerance) || + std::abs((a_ptr[i] - ref[i])/ a_ptr[i]) < tolerance)) { + std::stringstream txt; + txt << " std::abs(" << a_ptr[i] << " - " << ref[i] + << " [= " << std::abs(a_ptr[i] - ref[i]) << "] ) > " << tolerance; + throw data_error("storage differs at index " + itoa(i) + + " [Test at line: " + itoa(line) + "]" + txt.str(), + i); + } + } + + if (a_ptr == ref && !a.isWrapped()) + throw wrap_error("the storage should be wrapped but it is not [Test at line: " + itoa(line) + "]"); + if (a_ptr != ref && a.isWrapped()) + throw wrap_error("the storage should not be wrapped but it is [Test at line: " + itoa(line) + "]"); +} + +#define COMPARE(a, aref, txt) \ + compare_storages_with_ref(a, \ + aref, \ + sizeof(aref)/sizeof(aref[0]), \ + __LINE__, \ + txt) +#define COMPARE_STORAGE(a, aref, txt) \ + compare_storages_with_ref(a, \ + aref.storage(), \ + aref.size(), \ + __LINE__, \ + txt) + +const UInt ref_size = 10; + +/* -------------------------------------------------------------------------- */ +void test_constructor() { + std::cout << "=== Test constructors ===" << std::endl; + Real ref1[ref_size] = { 0. }; + Real ref2[ref_size] = { 1563.58, 1563.58, 1563.58, 1563.58, 1563.58, 1563.58, 1563.58, 1563.58, 1563.58, 1563.58 }; + Real ref3[ref_size] = { 23.1594, 79.6184, 77.9052, 47.9922, 12.8674, 37.1445, 64.8991, 80.3364, 98.4064, 73.7858 }; + + std::cout << "-- Vectors: " << std::endl; + Vector v1(ref_size); COMPARE ( v1, ref1, "normal" ); + Vector v2(ref_size, 1563.58); COMPARE ( v2, ref2, "defval" ); + Vector v3(ref3, ref_size); COMPARE ( v3, ref3, "wrapped" ); + Vector v3dcw(v3); COMPARE ( v3dcw, ref3, "wdeepcopy" ); + Vector v3scw(v3, false); COMPARE ( v3scw, ref3, "wshallow" ); + Vector v3dc(v3dcw); COMPARE_STORAGE( v3dc, v3dcw, "deepcopy" ); + Vector v3sc(v3dcw, false); COMPARE_STORAGE( v3sc, v3dcw, "shallow" ); + VectorProxy vp1(ref3, ref_size); + Vector v4(vp1); COMPARE ( v4, ref3, "proxyptr" ); + VectorProxy vp2(v3dcw); + Vector v5(vp2); COMPARE_STORAGE( v5, v3dcw, "proxyvdc" ); + VectorProxy vp3(v3scw); + Vector v6(vp3); COMPARE ( v6, ref3, "proxyvsc" ); + + /* ------------------------------------------------------------------------ */ + std::cout << "-- Matrices: " << std::endl; + Matrix m1(5, 2); COMPARE ( m1, ref1 , "normal" ); + Matrix m1t(2, 5); COMPARE ( m1t, ref1 , "tnormal" ); + Matrix m2(5, 2, 1563.58); COMPARE ( m2, ref2 , "defval" ); + Matrix m2t(2, 5, 1563.58); COMPARE ( m2t, ref2 , "tdefval" ); + Matrix m3(ref3, 5, 2); COMPARE ( m3, ref3 , "wrapped" ); + Matrix m3t(ref3, 2, 5); COMPARE ( m3t, ref3 , "twrapped" ); + Matrix m3dcw(m3); COMPARE ( m3dcw, ref3 , "wdeepcopy" ); + Matrix m3scw(m3, false); COMPARE ( m3scw, ref3 , "wshallow" ); + Matrix m3dc(m3dcw); COMPARE_STORAGE( m3dc, m3dcw , "deepcopy" ); + Matrix m3sc(m3dcw, false); COMPARE_STORAGE( m3sc, m3dcw , "shallow" ); + Matrix m3tdcw(m3t); COMPARE (m3tdcw, ref3 , "twdeepcopy"); + Matrix m3tscw(m3t, false); COMPARE (m3tscw, ref3 , "twshallow" ); + Matrix m3tdc(m3tdcw); COMPARE_STORAGE( m3tdc, m3tdcw, "tdeepcopy" ); + Matrix m3tsc(m3tdcw, false); COMPARE_STORAGE( m3tsc, m3tdcw, "tshallow" ); + MatrixProxy mp1(ref3, 5, 2); + Matrix m4(mp1); COMPARE ( m4, ref3, "proxyptr" ); + MatrixProxy mp2(m3dcw); + Matrix m5(mp2); COMPARE_STORAGE( m5, m3dcw, "proxyvdc" ); + MatrixProxy mp3(m3scw); + Matrix m6(mp3); COMPARE ( m6, ref3, "proxyvsc" ); + MatrixProxy mp1t(ref3, 2, 5); + Matrix m4t(mp1t); COMPARE ( m4t, ref3, "tproxyptr" ); + MatrixProxy mp2t(m3tdcw); + Matrix m5t(mp2t); COMPARE_STORAGE( m5t, m3tdcw, "tproxyvdc" ); + MatrixProxy mp3t(m3tscw); + Matrix m6t(mp3t); COMPARE ( m6t, ref3, "tproxyvsc" ); +} + +/* -------------------------------------------------------------------------- */ +void test_equal_and_accessors() { + std::cout << "=== Test operator=() ===" << std::endl; + Real ref[ref_size] = { 23.1594, 79.6184, 77.9052, 47.9922, 12.8674, 37.1445, 64.8991, 80.3364, 98.4064, 73.7858 }; + Real mod[ref_size] = { 98.7982, 72.1227, 19.7815, 57.6722, 47.1088, 14.9865, 13.3171, 62.7973, 33.9493, 98.3052 }; + + std::cout << "-- Vectors: " << std::endl; + Vector v (ref, ref_size); + Vector vm(mod, ref_size); + Vector vref1(v); + Vector v1; + v1 = vref1; COMPARE_STORAGE(v1, vref1, "simple=" ); + for (UInt i = 0; i < ref_size; ++i) v1 (i) = mod[i]; COMPARE (v1, mod, "s_acces" ); + COMPARE_STORAGE(vref1, v, "refcheck1"); + + Vector v2 = vref1; COMPARE_STORAGE(v2, vref1, "construc="); + for (UInt i = 0; i < ref_size; ++i) v2 (i) = mod[i]; COMPARE (v2, mod, "c_acces" ); + COMPARE_STORAGE(vref1, v, "refcheck2"); + + Vector vref2(vref1, false); + Vector v1w; + v1w = vref2; COMPARE_STORAGE(v1w, vref1, "w_simple=" ); + for (UInt i = 0; i < ref_size; ++i) v1w(i) = mod[i]; COMPARE (v1w, mod, "ws_acces" ); + try { COMPARE(vref2, ref, "refcheck3"); } catch(wrap_error &) {} + + Vector v2w = vref2; COMPARE_STORAGE(v2w, vref1, "w_constru="); + for (UInt i = 0; i < ref_size; ++i) v2w(i) = mod[i]; COMPARE (v2w, mod, "wc_acces" ); + try { COMPARE(vref2, ref, "refcheck4"); } catch(wrap_error &) {} + + VectorProxy vp1(vref1); + Vector v3; + v3 = vp1; COMPARE_STORAGE(v3, vref1, "p_simple=" ); + for (UInt i = 0; i < ref_size; ++i) v3(i) = mod[i]; COMPARE (v3, mod, "ps_acces" ); + COMPARE_STORAGE(vref1, v, "refcheck5"); + + Vector v4 = vp1; COMPARE_STORAGE(v4, vref1, "p_constru="); + for (UInt i = 0; i < ref_size; ++i) v4(i) = mod[i]; + try { COMPARE(v4, mod, "pc_acces" ); } catch (wrap_error &) {} + + COMPARE(vref1, mod, "refcheck6"); + try { COMPARE(vref2, mod, "refcheck7"); } catch(wrap_error &) {} + + vref2 = v; + + VectorProxy vp2(vref2); + Vector v3w; + v3w = vp2; COMPARE_STORAGE(v3w, vref1, "pw_simpl="); + for (UInt i = 0; i < ref_size; ++i) v3w(i) = mod[i]; COMPARE (v3w, mod, "pws_acces"); + try { COMPARE(vref2, ref, "refcheck8"); } catch(wrap_error &) {} + + Vector v4w = vp2; COMPARE_STORAGE( v4w, vref1, "pw_constr="); + for (UInt i = 0; i < ref_size; ++i) v4w(i) = mod[i]; + try { COMPARE(v4w, mod, "pwc_acces"); } catch (wrap_error &) {} + COMPARE_STORAGE(v4w, vref2, "refcheck9"); + try { COMPARE(vref2, mod, "refcheck10"); } catch(wrap_error &) {} + + vref1 = v; + + Real store[ref_size] = {0., 0., 0., 0., 0., 0., 0., 0., 0., 0.}; + Vector vs(store, 10); + VectorProxy vp3(vs); + vp3 = vref1; + try { COMPARE_STORAGE(vs, vref1, "vp_equal_v"); } catch(wrap_error &) {} + + Vector vref3(vm); + VectorProxy vp4(vref3); + vp3 = vp4; + try { COMPARE(vs, mod, "vp_equal_vp"); } catch(wrap_error &) {} + + /* ------------------------------------------------------------------------ */ + std::cout << "-- Matrices: " << std::endl; + + Matrix m (ref, 5, 2); + Matrix mt(ref, 2, 5); + + Matrix m1 (5, 2); + Matrix m1t(2, 5); + + for (UInt i = 0; i < 5; ++i) { + for (UInt j = 0; j < 2; ++j) { + m1(i, j) = ref[i + j*5]; + m1t(j, i) = ref[j + i*2]; + } + } + COMPARE_STORAGE( m1, m, "access" ); + COMPARE_STORAGE(m1t, m, "t_access"); + + Matrix mm (mod, 5, 2); + Matrix mmt(mod, 2, 5); + + Matrix m2(m); + Matrix m3(m); + for (UInt j = 0; j < 2; ++j) { + Vector v = m2(j); + for (UInt i = 0; i < 5; ++i) + v(i) = mm(i, j); + } + COMPARE_STORAGE(m2, mm, "slicing"); + + for (UInt j = 0; j < 2; ++j) + m3(j) = mm(j); + + COMPARE_STORAGE(m3, mm, "slic_slic"); + COMPARE(mm, mod, "refcheck"); + + + Real mod_1[ref_size] = { 98.7982, 72.1227, 197.815, 57.6722, 47.1088, 14.9865, 13.3171, 627.973, 33.9493, 98.3052 }; + + Matrix m4 (mm); + m4 (2,0) = 197.815; + m4 (2,1) = 627.973; + COMPARE(m4, mod_1, "partial"); + + Matrix m4t(mmt); + m4t(0,1) = 197.815; + m4t(1,3) = 627.973; + COMPARE(m4t, mod_1, "t_partial"); +} + +/* -------------------------------------------------------------------------- */ +void test_simple_operators() { + std::cout << "=== Test simple operation ===" << std::endl; + Real ref[ref_size] = { 23.1594, 79.6184, 77.9052, 47.9922, 12.8674, 37.1445, 64.8991, 80.3364, 98.4064, 73.7858 }; + Real mod[ref_size] = { 98.7982, 72.1227, 19.7815, 57.6722, 47.1088, 14.9865, 13.3171, 62.7973, 33.9493, 98.3052 }; + + Real ref_div[ref_size] = { 1.163905920192984e+00, 4.001326766509196e+00, + 3.915227661071464e+00, 2.411910744798472e+00, + 6.466680068348578e-01, 1.866745401547894e+00, + 3.261589104432606e+00, 4.037410795054780e+00, + 4.945542265554328e+00, 3.708201829329581e+00 }; + Real ref_tim[ref_size] = { 4.608257412000000e+02, 1.584246923200000e+03, + 1.550157669600000e+03, 9.549487955999999e+02, + 2.560355252000000e+02, 7.391012610000000e+02, + 1.291362291800000e+03, 1.598533687200000e+03, + 1.958090547200000e+03, 1.468189848400000e+03 }; + Real ref_p_mod[ref_size] = { 1.219576000000000e+02, 1.517411000000000e+02, + 9.768670000000000e+01, 1.056644000000000e+02, + 5.997620000000001e+01, 5.213100000000000e+01, + 7.821620000000000e+01, 1.431337000000000e+02, + 1.323557000000000e+02, 1.720910000000000e+02 }; + Real ref_m_mod[ref_size] = { -7.563879999999999e+01, 7.495699999999999e+00, + 5.812369999999999e+01, -9.680000000000000e+00, + -3.424140000000000e+01, 2.215800000000000e+01, + 5.158200000000001e+01, 1.753910000000000e+01, + 6.445710000000000e+01, -2.451940000000000e+01 }; + std::cout << "-- Vectors: " << std::endl; + Vector v (ref, ref_size); + Vector vm(mod, ref_size); + Vector vref(v); + Vector vmod(vm); + + Vector v1 = vref / 19.898; COMPARE(v1, ref_div, "v / s" ); + Vector v2 = vref * 19.898; COMPARE(v2, ref_tim, "v * s" ); + Vector v3 = 19.898 * vref; COMPARE(v3, ref_tim, "s * v" ); + Vector v4 = vref + vmod; COMPARE(v4, ref_p_mod, "v1 + v2" ); + Vector v5 = vref - vmod; COMPARE(v5, ref_m_mod, "v1 - v2" ); + Vector v6 = vref; v6 *= 19.898; COMPARE(v6, ref_tim, "v *= s" ); + Vector v7 = vref; v7 /= 19.898; COMPARE(v7, ref_div, "v /= s" ); + Vector v8 = vref; v8 += vmod; COMPARE(v8, ref_p_mod, "v1 += v2"); + Vector v9 = vref; v9 -= vmod; COMPARE(v9, ref_m_mod, "v1 -= v2"); + + std::cout << "-- Matrices: " << std::endl; + Matrix m (ref, 5, 2); + Matrix mm(mod, 5, 2); + Matrix mref(m); + Matrix mmod(mm); + + Matrix m1 = mref / 19.898; COMPARE(m1, ref_div, "m / s" ); + Matrix m2 = mref * 19.898; COMPARE(m2, ref_tim, "m * s" ); + Matrix m3 = 19.898 * mref; COMPARE(m3, ref_tim, "s * m" ); + Matrix m4 = mref + mmod; COMPARE(m4, ref_p_mod, "m1 + m2" ); + Matrix m5 = mref - mmod; COMPARE(m5, ref_m_mod, "m1 - m2" ); + Matrix m6 = mref; m6 *= 19.898; COMPARE(m6, ref_tim, "m *= s" ); + Matrix m7 = mref; m7 /= 19.898; COMPARE(m7, ref_div, "m /= s" ); + Matrix m8 = mref; m8 += mmod; COMPARE(m8, ref_p_mod, "m1 += m2"); + Matrix m9 = mref; m9 -= mmod; COMPARE(m9, ref_m_mod, "m1 -= m2"); +} + + +/* -------------------------------------------------------------------------- */ +int main(int argc, char *argv[]) { + test_constructor(); + test_equal_and_accessors(); + test_simple_operators(); + + + return 0; +} diff --git a/test/test_fem/CMakeLists.txt b/test/test_fem/CMakeLists.txt index b685a2514..c48f29e32 100644 --- a/test/test_fem/CMakeLists.txt +++ b/test/test_fem/CMakeLists.txt @@ -1,98 +1,100 @@ #=============================================================================== # @file CMakeLists.txt # # @author Guillaume Anciaux # # @date creation: Fri Sep 03 2010 # @date last modification: Fri May 30 2014 # # @brief configuration for FEM 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 . # # @section DESCRIPTION # #=============================================================================== #=============================================================================== macro(register_fem_test operation type) set(_target test_${operation}_${_type}) register_test(${_target} SOURCES test_${operation}.cc FILES_TO_COPY _${type}.msh COMPILE_OPTIONS TYPE=_${_type} PACKAGE core ) endmacro() #=============================================================================== set(LIST_TYPES segment_2 segment_3 triangle_3 triangle_6 quadrangle_4 quadrangle_8 tetrahedron_4 tetrahedron_10 hexahedron_8 hexahedron_20 + pentahedron_6 + pentahedron_15 ) foreach(_type ${LIST_TYPES}) register_fem_test(interpolate ${_type}) register_fem_test(gradient ${_type}) register_fem_test(integrate ${_type}) register_fem_test(inverse_map ${_type}) endforeach() #register_test(test_interpolate_bernoulli_beam_2 test_interpolate_bernoulli_beam_2.cc) #add_mesh(test_fem_circle_1_mesh circle.geo 2 1 OUTPUT circle1.msh) #add_mesh(test_fem_circle_2_mesh circle.geo 2 2 OUTPUT circle2.msh) # Tests for class MeshData macro(register_typed_test test_name type value1 value2) set(target test_${test_name}_${type}) register_test(${target} SOURCES test_${test_name}.cc COMPILE_OPTIONS "TYPE=${type};VALUE1=${value1};VALUE2=${value2}" PACKAGE core ) endmacro() register_typed_test(mesh_data string \"5\" \"10\") register_typed_test(mesh_data UInt 5 10) add_mesh(test_boundary_msh cube.geo 3 1) add_mesh(test_boundary_msh_physical_names cube_physical_names.geo 3 1) register_test(test_mesh_boundary SOURCES test_mesh_boundary.cc DEPENDENCIES test_boundary_msh test_boundary_msh_physical_names PACKAGE core) register_test(test_facet_element_mapping SOURCES test_facet_element_mapping.cc DEPENDENCIES test_boundary_msh_physical_names PACKAGE core) register_test(test_igfem_integrate SOURCES test_igfem_integrate.cc PACKAGE igfem) diff --git a/test/test_fem/_pentahedron_15.msh b/test/test_fem/_pentahedron_15.msh new file mode 100755 index 000000000..a75af84a5 --- /dev/null +++ b/test/test_fem/_pentahedron_15.msh @@ -0,0 +1,74 @@ +$MeshFormat +2.2 0 8 +$EndMeshFormat +$Nodes +57 +1 0 0 -1 +2 1 0 -1 +3 0 1 -1 +4 0 0 1 +5 1 0 1 +6 0 1 1 +7 0.5 0 -1 +8 0 0.5 -1 +9 0 0 0 +10 0.5 0.5 -1 +11 1 0 0 +12 0 1 0 +13 0.5 0 1 +14 0 0.5 1 +15 0.5 0.5 1 +16 0.5 0 0 +17 0 0.5 0 +18 0.5 0.5 0 +19 0.25 0 -1 +20 0 0.25 -1 +21 0 0 -0.5 +22 0.25 0.25 -1 +23 0.5 0 -0.5 +24 0 0.5 -0.5 +25 0.25 0 0 +26 0 0.25 0 +27 0.25 0.25 0 +28 0 0 0.5 +29 0.5 0 0.5 +30 0 0.5 0.5 +31 0.25 0 1 +32 0 0.25 1 +33 0.25 0.25 1 +34 0.75 0 -1 +35 0.5 0.25 -1 +36 0.75 0.25 -1 +37 1 0 -0.5 +38 0.5 0.5 -0.5 +39 0.75 0 0 +40 0.5 0.25 0 +41 0.75 0.25 0 +42 1 0 0.5 +43 0.5 0.5 0.5 +44 0.75 0 1 +45 0.5 0.25 1 +46 0.75 0.25 1 +47 0.25 0.5 -1 +48 0 0.75 -1 +49 0.25 0.75 -1 +50 0 1 -0.5 +51 0.25 0.5 0 +52 0 0.75 0 +53 0.25 0.75 0 +54 0 1 0.5 +55 0.25 0.5 1 +56 0 0.75 1 +57 0.25 0.75 1 +$EndNodes +$Elements +8 +1 18 2 1 1 1 7 8 9 16 17 19 20 21 22 23 24 25 26 27 +2 18 2 1 1 9 16 17 4 13 14 25 26 28 27 29 30 31 32 33 +3 18 2 1 1 7 2 10 16 11 18 34 35 23 36 37 38 39 40 41 +4 18 2 1 1 16 11 18 13 5 15 39 40 29 41 42 43 44 45 46 +5 18 2 1 1 8 10 3 17 18 12 47 48 24 49 38 50 51 52 53 +6 18 2 1 1 17 18 12 14 15 6 51 52 30 53 43 54 55 56 57 +7 18 2 1 1 10 8 7 18 17 16 47 35 38 22 24 23 51 40 27 +8 18 2 1 1 18 17 16 15 14 13 51 40 43 27 30 29 55 45 33 +$EndElements diff --git a/test/test_fem/_pentahedron_6.msh b/test/test_fem/_pentahedron_6.msh new file mode 100755 index 000000000..a8f6ef2cf --- /dev/null +++ b/test/test_fem/_pentahedron_6.msh @@ -0,0 +1,148 @@ +$MeshFormat +2.2 0 8 +$EndMeshFormat +$Nodes +75 +1 0 0 -1 +2 1 0 -1 +3 0 1 -1 +4 0 0 1 +5 1 0 1 +6 0 1 1 +7 0.5 0 -1 +8 0 0.5 -1 +9 0 0 0 +10 0.5 0.5 -1 +11 1 0 0 +12 0 1 0 +13 0.5 0 1 +14 0 0.5 1 +15 0.5 0.5 1 +16 0.5 0 0 +17 0 0.5 0 +18 0.5 0.5 0 +19 0.25 0 -1 +20 0 0.25 -1 +21 0 0 -0.5 +22 0.25 0.25 -1 +23 0.5 0 -0.5 +24 0 0.5 -0.5 +25 0.25 0 0 +26 0 0.25 0 +27 0.25 0.25 0 +28 0.25 0 -0.5 +29 0 0.25 -0.5 +30 0.25 0.25 -0.5 +31 0 0 0.5 +32 0.5 0 0.5 +33 0 0.5 0.5 +34 0.25 0 1 +35 0 0.25 1 +36 0.25 0.25 1 +37 0.25 0 0.5 +38 0 0.25 0.5 +39 0.25 0.25 0.5 +40 0.75 0 -1 +41 0.5 0.25 -1 +42 0.75 0.25 -1 +43 1 0 -0.5 +44 0.5 0.5 -0.5 +45 0.75 0 0 +46 0.5 0.25 0 +47 0.75 0.25 0 +48 0.75 0 -0.5 +49 0.5 0.25 -0.5 +50 0.75 0.25 -0.5 +51 1 0 0.5 +52 0.5 0.5 0.5 +53 0.75 0 1 +54 0.5 0.25 1 +55 0.75 0.25 1 +56 0.75 0 0.5 +57 0.5 0.25 0.5 +58 0.75 0.25 0.5 +59 0.25 0.5 -1 +60 0 0.75 -1 +61 0.25 0.75 -1 +62 0 1 -0.5 +63 0.25 0.5 0 +64 0 0.75 0 +65 0.25 0.75 0 +66 0.25 0.5 -0.5 +67 0 0.75 -0.5 +68 0.25 0.75 -0.5 +69 0 1 0.5 +70 0.25 0.5 1 +71 0 0.75 1 +72 0.25 0.75 1 +73 0.25 0.5 0.5 +74 0 0.75 0.5 +75 0.25 0.75 0.5 +$EndNodes +$Elements +64 +1 6 2 1 1 1 19 20 21 28 29 +2 6 2 1 1 21 28 29 9 25 26 +3 6 2 1 1 19 7 22 28 23 30 +4 6 2 1 1 28 23 30 25 16 27 +5 6 2 1 1 20 22 8 29 30 24 +6 6 2 1 1 29 30 24 26 27 17 +7 6 2 1 1 22 20 19 30 29 28 +8 6 2 1 1 30 29 28 27 26 25 +9 6 2 1 1 9 25 26 31 37 38 +10 6 2 1 1 31 37 38 4 34 35 +11 6 2 1 1 25 16 27 37 32 39 +12 6 2 1 1 37 32 39 34 13 36 +13 6 2 1 1 26 27 17 38 39 33 +14 6 2 1 1 38 39 33 35 36 14 +15 6 2 1 1 27 26 25 39 38 37 +16 6 2 1 1 39 38 37 36 35 34 +17 6 2 1 1 7 40 41 23 48 49 +18 6 2 1 1 23 48 49 16 45 46 +19 6 2 1 1 40 2 42 48 43 50 +20 6 2 1 1 48 43 50 45 11 47 +21 6 2 1 1 41 42 10 49 50 44 +22 6 2 1 1 49 50 44 46 47 18 +23 6 2 1 1 42 41 40 50 49 48 +24 6 2 1 1 50 49 48 47 46 45 +25 6 2 1 1 16 45 46 32 56 57 +26 6 2 1 1 32 56 57 13 53 54 +27 6 2 1 1 45 11 47 56 51 58 +28 6 2 1 1 56 51 58 53 5 55 +29 6 2 1 1 46 47 18 57 58 52 +30 6 2 1 1 57 58 52 54 55 15 +31 6 2 1 1 47 46 45 58 57 56 +32 6 2 1 1 58 57 56 55 54 53 +33 6 2 1 1 8 59 60 24 66 67 +34 6 2 1 1 24 66 67 17 63 64 +35 6 2 1 1 59 10 61 66 44 68 +36 6 2 1 1 66 44 68 63 18 65 +37 6 2 1 1 60 61 3 67 68 62 +38 6 2 1 1 67 68 62 64 65 12 +39 6 2 1 1 61 60 59 68 67 66 +40 6 2 1 1 68 67 66 65 64 63 +41 6 2 1 1 17 63 64 33 73 74 +42 6 2 1 1 33 73 74 14 70 71 +43 6 2 1 1 63 18 65 73 52 75 +44 6 2 1 1 73 52 75 70 15 72 +45 6 2 1 1 64 65 12 74 75 69 +46 6 2 1 1 74 75 69 71 72 6 +47 6 2 1 1 65 64 63 75 74 73 +48 6 2 1 1 75 74 73 72 71 70 +49 6 2 1 1 10 59 41 44 66 49 +50 6 2 1 1 44 66 49 18 63 46 +51 6 2 1 1 59 8 22 66 24 30 +52 6 2 1 1 66 24 30 63 17 27 +53 6 2 1 1 41 22 7 49 30 23 +54 6 2 1 1 49 30 23 46 27 16 +55 6 2 1 1 22 41 59 30 49 66 +56 6 2 1 1 30 49 66 27 46 63 +57 6 2 1 1 18 63 46 52 73 57 +58 6 2 1 1 52 73 57 15 70 54 +59 6 2 1 1 63 17 27 73 33 39 +60 6 2 1 1 73 33 39 70 14 36 +61 6 2 1 1 46 27 16 57 39 32 +62 6 2 1 1 57 39 32 54 36 13 +63 6 2 1 1 27 46 63 39 57 73 +64 6 2 1 1 39 57 73 36 54 70 +$EndElements diff --git a/test/test_fem/test_gradient_hexahedron_20.verified b/test/test_fem/test_gradient_hexahedron_20.verified index e69de29bb..0bba1973e 100644 --- a/test/test_fem/test_gradient_hexahedron_20.verified +++ b/test/test_fem/test_gradient_hexahedron_20.verified @@ -0,0 +1,76 @@ +Epsilon : 1e-12 +FEEngine [ + + id : my_fem + + element dimension : 3 + + mesh [ + Mesh [ + + id : mesh + + spatial dimension : 3 + + nodes [ + Array [ + + id : mesh:coordinates + + size : 81 + + nb_component : 3 + + allocated size : 2000 + + memory size : 46.88KiByte + + values : {{-0.5, -0.5, -0.5}, {0.5, -0.5, -0.5}, {-0.5, 0.5, -0.5}, {0.5, 0.5, -0.5}, {-0.5, -0.5, 0.5}, {0.5, -0.5, 0.5}, {0.5, 0.5, 0.5}, {-0.5, 0.5, 0.5}, {0, -0.5, -0.5}, {-0.25, -0.5, -0.5}, {0.25, -0.5, -0.5}, {0, 0.5, -0.5}, {-0.25, 0.5, -0.5}, {0.25, 0.5, -0.5}, {-0.5, 0, -0.5}, {-0.5, -0.25, -0.5}, {-0.5, 0.25, -0.5}, {0.5, 0, -0.5}, {0.5, -0.25, -0.5}, {0.5, 0.25, -0.5}, {0, -0.5, 0.5}, {-0.25, -0.5, 0.5}, {0.25, -0.5, 0.5}, {0.5, 0, 0.5}, {0.5, -0.25, 0.5}, {0.5, 0.25, 0.5}, {0, 0.5, 0.5}, {0.25, 0.5, 0.5}, {-0.25, 0.5, 0.5}, {-0.5, 0, 0.5}, {-0.5, 0.25, 0.5}, {-0.5, -0.25, 0.5}, {-0.5, -0.5, 0}, {-0.5, -0.5, -0.25}, {-0.5, -0.5, 0.25}, {0.5, -0.5, 0}, {0.5, -0.5, -0.25}, {0.5, -0.5, 0.25}, {0.5, 0.5, 0}, {0.5, 0.5, -0.25}, {0.5, 0.5, 0.25}, {-0.5, 0.5, 0}, {-0.5, 0.5, -0.25}, {-0.5, 0.5, 0.25}, {0, 0, -0.5}, {0, -0.25, -0.5}, {-0.25, 0, -0.5}, {0, 0.25, -0.5}, {0.25, 0, -0.5}, {0, -0.5, 0}, {0, -0.5, -0.25}, {-0.25, -0.5, 0}, {0, -0.5, 0.25}, {0.25, -0.5, 0}, {0.5, 0, 0}, {0.5, 0, -0.25}, {0.5, -0.25, 0}, {0.5, 0, 0.25}, {0.5, 0.25, 0}, {0, 0.5, 0}, {-0.25, 0.5, 0}, {0, 0.5, -0.25}, {0, 0.5, 0.25}, {0.25, 0.5, 0}, {-0.5, 0, 0}, {-0.5, -0.25, 0}, {-0.5, 0, -0.25}, {-0.5, 0, 0.25}, {-0.5, 0.25, 0}, {0, 0, 0.5}, {0, -0.25, 0.5}, {-0.25, 0, 0.5}, {0, 0.25, 0.5}, {0.25, 0, 0.5}, {0, 0, 0}, {0, 0, -0.25}, {0, -0.25, 0}, {-0.25, 0, 0}, {0, 0, 0.25}, {0, 0.25, 0}, {0.25, 0, 0}} + ] + + connectivities [ + ElementTypeMapArray [ + (not_ghost:_point_1) [ + Array [ + + id : mesh:connectivities:_point_1 + + size : 8 + + nb_component : 1 + + allocated size : 2000 + + memory size : 7.81KiByte + + values : {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}} + ] + ] + (not_ghost:_segment_3) [ + Array [ + + id : mesh:connectivities:_segment_3 + + size : 24 + + nb_component : 3 + + allocated size : 2000 + + memory size : 23.44KiByte + + values : {{0, 8, 9}, {8, 1, 10}, {2, 11, 12}, {11, 3, 13}, {0, 14, 15}, {14, 2, 16}, {1, 17, 18}, {17, 3, 19}, {4, 20, 21}, {20, 5, 22}, {5, 23, 24}, {23, 6, 25}, {6, 26, 27}, {26, 7, 28}, {7, 29, 30}, {29, 4, 31}, {0, 32, 33}, {32, 4, 34}, {1, 35, 36}, {35, 5, 37}, {3, 38, 39}, {38, 6, 40}, {2, 41, 42}, {41, 7, 43}} + ] + ] + (not_ghost:_quadrangle_8) [ + Array [ + + id : mesh:connectivities:_quadrangle_8 + + size : 24 + + nb_component : 8 + + allocated size : 2000 + + memory size : 62.50KiByte + + values : {{0, 8, 44, 14, 9, 45, 46, 15}, {14, 44, 11, 2, 46, 47, 12, 16}, {8, 1, 17, 44, 10, 18, 48, 45}, {44, 17, 3, 11, 48, 19, 13, 47}, {0, 8, 49, 32, 9, 50, 51, 33}, {32, 49, 20, 4, 51, 52, 21, 34}, {8, 1, 35, 49, 10, 36, 53, 50}, {49, 35, 5, 20, 53, 37, 22, 52}, {1, 17, 54, 35, 18, 55, 56, 36}, {35, 54, 23, 5, 56, 57, 24, 37}, {17, 3, 38, 54, 19, 39, 58, 55}, {54, 38, 6, 23, 58, 40, 25, 57}, {2, 41, 59, 11, 42, 60, 61, 12}, {41, 7, 26, 59, 43, 28, 62, 60}, {11, 59, 38, 3, 61, 63, 39, 13}, {59, 26, 6, 38, 62, 27, 40, 63}, {0, 32, 64, 14, 33, 65, 66, 15}, {32, 4, 29, 64, 34, 31, 67, 65}, {14, 64, 41, 2, 66, 68, 42, 16}, {64, 29, 7, 41, 67, 30, 43, 68}, {4, 20, 69, 29, 21, 70, 71, 31}, {29, 69, 26, 7, 71, 72, 28, 30}, {20, 5, 23, 69, 22, 24, 73, 70}, {69, 23, 6, 26, 73, 25, 27, 72}} + ] + ] + (not_ghost:_hexahedron_20) [ + Array [ + + id : mesh:connectivities:_hexahedron_20 + + size : 8 + + nb_component : 20 + + allocated size : 2000 + + memory size : 156.25KiByte + + values : {{0, 8, 44, 14, 32, 49, 74, 64, 9, 45, 46, 15, 33, 50, 75, 66, 51, 76, 77, 65}, {32, 49, 74, 64, 4, 20, 69, 29, 51, 76, 77, 65, 34, 52, 78, 67, 21, 70, 71, 31}, {14, 44, 11, 2, 64, 74, 59, 41, 46, 47, 12, 16, 66, 75, 61, 42, 77, 79, 60, 68}, {64, 74, 59, 41, 29, 69, 26, 7, 77, 79, 60, 68, 67, 78, 62, 43, 71, 72, 28, 30}, {8, 1, 17, 44, 49, 35, 54, 74, 10, 18, 48, 45, 50, 36, 55, 75, 53, 56, 80, 76}, {49, 35, 54, 74, 20, 5, 23, 69, 53, 56, 80, 76, 52, 37, 57, 78, 22, 24, 73, 70}, {44, 17, 3, 11, 74, 54, 38, 59, 48, 19, 13, 47, 75, 55, 39, 61, 80, 58, 63, 79}, {74, 54, 38, 59, 69, 23, 6, 26, 80, 58, 63, 79, 78, 57, 40, 62, 73, 25, 27, 72}} + ] + ] + ] + ] + GroupManager [ + ] + ] + ] +] + +Array [ + + id : grad_on_quad + + size : 64 + + nb_component : 6 + + allocated size : 64 + + memory size : 3.00KiByte + + values : {{13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}, {13, 11, 23, 7, 31, 5}} +] + diff --git a/test/test_fem/test_integrate_hexahedron_20.verified b/test/test_fem/test_integrate_hexahedron_20.verified index e69de29bb..6fb4268cb 100644 --- a/test/test_fem/test_integrate_hexahedron_20.verified +++ b/test/test_fem/test_integrate_hexahedron_20.verified @@ -0,0 +1,67 @@ +Epsilon : 3e-13 +FEEngine [ + + id : my_fem + + element dimension : 3 + + mesh [ + Mesh [ + + id : mesh + + spatial dimension : 3 + + nodes [ + Array [ + + id : mesh:coordinates + + size : 81 + + nb_component : 3 + + allocated size : 2000 + + memory size : 46.88KiByte + + values : {{-0.5, -0.5, -0.5}, {0.5, -0.5, -0.5}, {-0.5, 0.5, -0.5}, {0.5, 0.5, -0.5}, {-0.5, -0.5, 0.5}, {0.5, -0.5, 0.5}, {0.5, 0.5, 0.5}, {-0.5, 0.5, 0.5}, {0, -0.5, -0.5}, {-0.25, -0.5, -0.5}, {0.25, -0.5, -0.5}, {0, 0.5, -0.5}, {-0.25, 0.5, -0.5}, {0.25, 0.5, -0.5}, {-0.5, 0, -0.5}, {-0.5, -0.25, -0.5}, {-0.5, 0.25, -0.5}, {0.5, 0, -0.5}, {0.5, -0.25, -0.5}, {0.5, 0.25, -0.5}, {0, -0.5, 0.5}, {-0.25, -0.5, 0.5}, {0.25, -0.5, 0.5}, {0.5, 0, 0.5}, {0.5, -0.25, 0.5}, {0.5, 0.25, 0.5}, {0, 0.5, 0.5}, {0.25, 0.5, 0.5}, {-0.25, 0.5, 0.5}, {-0.5, 0, 0.5}, {-0.5, 0.25, 0.5}, {-0.5, -0.25, 0.5}, {-0.5, -0.5, 0}, {-0.5, -0.5, -0.25}, {-0.5, -0.5, 0.25}, {0.5, -0.5, 0}, {0.5, -0.5, -0.25}, {0.5, -0.5, 0.25}, {0.5, 0.5, 0}, {0.5, 0.5, -0.25}, {0.5, 0.5, 0.25}, {-0.5, 0.5, 0}, {-0.5, 0.5, -0.25}, {-0.5, 0.5, 0.25}, {0, 0, -0.5}, {0, -0.25, -0.5}, {-0.25, 0, -0.5}, {0, 0.25, -0.5}, {0.25, 0, -0.5}, {0, -0.5, 0}, {0, -0.5, -0.25}, {-0.25, -0.5, 0}, {0, -0.5, 0.25}, {0.25, -0.5, 0}, {0.5, 0, 0}, {0.5, 0, -0.25}, {0.5, -0.25, 0}, {0.5, 0, 0.25}, {0.5, 0.25, 0}, {0, 0.5, 0}, {-0.25, 0.5, 0}, {0, 0.5, -0.25}, {0, 0.5, 0.25}, {0.25, 0.5, 0}, {-0.5, 0, 0}, {-0.5, -0.25, 0}, {-0.5, 0, -0.25}, {-0.5, 0, 0.25}, {-0.5, 0.25, 0}, {0, 0, 0.5}, {0, -0.25, 0.5}, {-0.25, 0, 0.5}, {0, 0.25, 0.5}, {0.25, 0, 0.5}, {0, 0, 0}, {0, 0, -0.25}, {0, -0.25, 0}, {-0.25, 0, 0}, {0, 0, 0.25}, {0, 0.25, 0}, {0.25, 0, 0}} + ] + + connectivities [ + ElementTypeMapArray [ + (not_ghost:_point_1) [ + Array [ + + id : mesh:connectivities:_point_1 + + size : 8 + + nb_component : 1 + + allocated size : 2000 + + memory size : 7.81KiByte + + values : {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}} + ] + ] + (not_ghost:_segment_3) [ + Array [ + + id : mesh:connectivities:_segment_3 + + size : 24 + + nb_component : 3 + + allocated size : 2000 + + memory size : 23.44KiByte + + values : {{0, 8, 9}, {8, 1, 10}, {2, 11, 12}, {11, 3, 13}, {0, 14, 15}, {14, 2, 16}, {1, 17, 18}, {17, 3, 19}, {4, 20, 21}, {20, 5, 22}, {5, 23, 24}, {23, 6, 25}, {6, 26, 27}, {26, 7, 28}, {7, 29, 30}, {29, 4, 31}, {0, 32, 33}, {32, 4, 34}, {1, 35, 36}, {35, 5, 37}, {3, 38, 39}, {38, 6, 40}, {2, 41, 42}, {41, 7, 43}} + ] + ] + (not_ghost:_quadrangle_8) [ + Array [ + + id : mesh:connectivities:_quadrangle_8 + + size : 24 + + nb_component : 8 + + allocated size : 2000 + + memory size : 62.50KiByte + + values : {{0, 8, 44, 14, 9, 45, 46, 15}, {14, 44, 11, 2, 46, 47, 12, 16}, {8, 1, 17, 44, 10, 18, 48, 45}, {44, 17, 3, 11, 48, 19, 13, 47}, {0, 8, 49, 32, 9, 50, 51, 33}, {32, 49, 20, 4, 51, 52, 21, 34}, {8, 1, 35, 49, 10, 36, 53, 50}, {49, 35, 5, 20, 53, 37, 22, 52}, {1, 17, 54, 35, 18, 55, 56, 36}, {35, 54, 23, 5, 56, 57, 24, 37}, {17, 3, 38, 54, 19, 39, 58, 55}, {54, 38, 6, 23, 58, 40, 25, 57}, {2, 41, 59, 11, 42, 60, 61, 12}, {41, 7, 26, 59, 43, 28, 62, 60}, {11, 59, 38, 3, 61, 63, 39, 13}, {59, 26, 6, 38, 62, 27, 40, 63}, {0, 32, 64, 14, 33, 65, 66, 15}, {32, 4, 29, 64, 34, 31, 67, 65}, {14, 64, 41, 2, 66, 68, 42, 16}, {64, 29, 7, 41, 67, 30, 43, 68}, {4, 20, 69, 29, 21, 70, 71, 31}, {29, 69, 26, 7, 71, 72, 28, 30}, {20, 5, 23, 69, 22, 24, 73, 70}, {69, 23, 6, 26, 73, 25, 27, 72}} + ] + ] + (not_ghost:_hexahedron_20) [ + Array [ + + id : mesh:connectivities:_hexahedron_20 + + size : 8 + + nb_component : 20 + + allocated size : 2000 + + memory size : 156.25KiByte + + values : {{0, 8, 44, 14, 32, 49, 74, 64, 9, 45, 46, 15, 33, 50, 75, 66, 51, 76, 77, 65}, {32, 49, 74, 64, 4, 20, 69, 29, 51, 76, 77, 65, 34, 52, 78, 67, 21, 70, 71, 31}, {14, 44, 11, 2, 64, 74, 59, 41, 46, 47, 12, 16, 66, 75, 61, 42, 77, 79, 60, 68}, {64, 74, 59, 41, 29, 69, 26, 7, 77, 79, 60, 68, 67, 78, 62, 43, 71, 72, 28, 30}, {8, 1, 17, 44, 49, 35, 54, 74, 10, 18, 48, 45, 50, 36, 55, 75, 53, 56, 80, 76}, {49, 35, 54, 74, 20, 5, 23, 69, 53, 56, 80, 76, 52, 37, 57, 78, 22, 24, 73, 70}, {44, 17, 3, 11, 74, 54, 38, 59, 48, 19, 13, 47, 75, 55, 39, 61, 80, 58, 63, 79}, {74, 54, 38, 59, 69, 23, 6, 26, 80, 58, 63, 79, 78, 57, 40, 62, 73, 25, 27, 72}} + ] + ] + ] + ] + GroupManager [ + ] + ] + ] +] + diff --git a/test/test_fem/test_interpolate_hexahedron_20.verified b/test/test_fem/test_interpolate_hexahedron_20.verified index e69de29bb..6fb4268cb 100644 --- a/test/test_fem/test_interpolate_hexahedron_20.verified +++ b/test/test_fem/test_interpolate_hexahedron_20.verified @@ -0,0 +1,67 @@ +Epsilon : 3e-13 +FEEngine [ + + id : my_fem + + element dimension : 3 + + mesh [ + Mesh [ + + id : mesh + + spatial dimension : 3 + + nodes [ + Array [ + + id : mesh:coordinates + + size : 81 + + nb_component : 3 + + allocated size : 2000 + + memory size : 46.88KiByte + + values : {{-0.5, -0.5, -0.5}, {0.5, -0.5, -0.5}, {-0.5, 0.5, -0.5}, {0.5, 0.5, -0.5}, {-0.5, -0.5, 0.5}, {0.5, -0.5, 0.5}, {0.5, 0.5, 0.5}, {-0.5, 0.5, 0.5}, {0, -0.5, -0.5}, {-0.25, -0.5, -0.5}, {0.25, -0.5, -0.5}, {0, 0.5, -0.5}, {-0.25, 0.5, -0.5}, {0.25, 0.5, -0.5}, {-0.5, 0, -0.5}, {-0.5, -0.25, -0.5}, {-0.5, 0.25, -0.5}, {0.5, 0, -0.5}, {0.5, -0.25, -0.5}, {0.5, 0.25, -0.5}, {0, -0.5, 0.5}, {-0.25, -0.5, 0.5}, {0.25, -0.5, 0.5}, {0.5, 0, 0.5}, {0.5, -0.25, 0.5}, {0.5, 0.25, 0.5}, {0, 0.5, 0.5}, {0.25, 0.5, 0.5}, {-0.25, 0.5, 0.5}, {-0.5, 0, 0.5}, {-0.5, 0.25, 0.5}, {-0.5, -0.25, 0.5}, {-0.5, -0.5, 0}, {-0.5, -0.5, -0.25}, {-0.5, -0.5, 0.25}, {0.5, -0.5, 0}, {0.5, -0.5, -0.25}, {0.5, -0.5, 0.25}, {0.5, 0.5, 0}, {0.5, 0.5, -0.25}, {0.5, 0.5, 0.25}, {-0.5, 0.5, 0}, {-0.5, 0.5, -0.25}, {-0.5, 0.5, 0.25}, {0, 0, -0.5}, {0, -0.25, -0.5}, {-0.25, 0, -0.5}, {0, 0.25, -0.5}, {0.25, 0, -0.5}, {0, -0.5, 0}, {0, -0.5, -0.25}, {-0.25, -0.5, 0}, {0, -0.5, 0.25}, {0.25, -0.5, 0}, {0.5, 0, 0}, {0.5, 0, -0.25}, {0.5, -0.25, 0}, {0.5, 0, 0.25}, {0.5, 0.25, 0}, {0, 0.5, 0}, {-0.25, 0.5, 0}, {0, 0.5, -0.25}, {0, 0.5, 0.25}, {0.25, 0.5, 0}, {-0.5, 0, 0}, {-0.5, -0.25, 0}, {-0.5, 0, -0.25}, {-0.5, 0, 0.25}, {-0.5, 0.25, 0}, {0, 0, 0.5}, {0, -0.25, 0.5}, {-0.25, 0, 0.5}, {0, 0.25, 0.5}, {0.25, 0, 0.5}, {0, 0, 0}, {0, 0, -0.25}, {0, -0.25, 0}, {-0.25, 0, 0}, {0, 0, 0.25}, {0, 0.25, 0}, {0.25, 0, 0}} + ] + + connectivities [ + ElementTypeMapArray [ + (not_ghost:_point_1) [ + Array [ + + id : mesh:connectivities:_point_1 + + size : 8 + + nb_component : 1 + + allocated size : 2000 + + memory size : 7.81KiByte + + values : {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}} + ] + ] + (not_ghost:_segment_3) [ + Array [ + + id : mesh:connectivities:_segment_3 + + size : 24 + + nb_component : 3 + + allocated size : 2000 + + memory size : 23.44KiByte + + values : {{0, 8, 9}, {8, 1, 10}, {2, 11, 12}, {11, 3, 13}, {0, 14, 15}, {14, 2, 16}, {1, 17, 18}, {17, 3, 19}, {4, 20, 21}, {20, 5, 22}, {5, 23, 24}, {23, 6, 25}, {6, 26, 27}, {26, 7, 28}, {7, 29, 30}, {29, 4, 31}, {0, 32, 33}, {32, 4, 34}, {1, 35, 36}, {35, 5, 37}, {3, 38, 39}, {38, 6, 40}, {2, 41, 42}, {41, 7, 43}} + ] + ] + (not_ghost:_quadrangle_8) [ + Array [ + + id : mesh:connectivities:_quadrangle_8 + + size : 24 + + nb_component : 8 + + allocated size : 2000 + + memory size : 62.50KiByte + + values : {{0, 8, 44, 14, 9, 45, 46, 15}, {14, 44, 11, 2, 46, 47, 12, 16}, {8, 1, 17, 44, 10, 18, 48, 45}, {44, 17, 3, 11, 48, 19, 13, 47}, {0, 8, 49, 32, 9, 50, 51, 33}, {32, 49, 20, 4, 51, 52, 21, 34}, {8, 1, 35, 49, 10, 36, 53, 50}, {49, 35, 5, 20, 53, 37, 22, 52}, {1, 17, 54, 35, 18, 55, 56, 36}, {35, 54, 23, 5, 56, 57, 24, 37}, {17, 3, 38, 54, 19, 39, 58, 55}, {54, 38, 6, 23, 58, 40, 25, 57}, {2, 41, 59, 11, 42, 60, 61, 12}, {41, 7, 26, 59, 43, 28, 62, 60}, {11, 59, 38, 3, 61, 63, 39, 13}, {59, 26, 6, 38, 62, 27, 40, 63}, {0, 32, 64, 14, 33, 65, 66, 15}, {32, 4, 29, 64, 34, 31, 67, 65}, {14, 64, 41, 2, 66, 68, 42, 16}, {64, 29, 7, 41, 67, 30, 43, 68}, {4, 20, 69, 29, 21, 70, 71, 31}, {29, 69, 26, 7, 71, 72, 28, 30}, {20, 5, 23, 69, 22, 24, 73, 70}, {69, 23, 6, 26, 73, 25, 27, 72}} + ] + ] + (not_ghost:_hexahedron_20) [ + Array [ + + id : mesh:connectivities:_hexahedron_20 + + size : 8 + + nb_component : 20 + + allocated size : 2000 + + memory size : 156.25KiByte + + values : {{0, 8, 44, 14, 32, 49, 74, 64, 9, 45, 46, 15, 33, 50, 75, 66, 51, 76, 77, 65}, {32, 49, 74, 64, 4, 20, 69, 29, 51, 76, 77, 65, 34, 52, 78, 67, 21, 70, 71, 31}, {14, 44, 11, 2, 64, 74, 59, 41, 46, 47, 12, 16, 66, 75, 61, 42, 77, 79, 60, 68}, {64, 74, 59, 41, 29, 69, 26, 7, 77, 79, 60, 68, 67, 78, 62, 43, 71, 72, 28, 30}, {8, 1, 17, 44, 49, 35, 54, 74, 10, 18, 48, 45, 50, 36, 55, 75, 53, 56, 80, 76}, {49, 35, 54, 74, 20, 5, 23, 69, 53, 56, 80, 76, 52, 37, 57, 78, 22, 24, 73, 70}, {44, 17, 3, 11, 74, 54, 38, 59, 48, 19, 13, 47, 75, 55, 39, 61, 80, 58, 63, 79}, {74, 54, 38, 59, 69, 23, 6, 26, 80, 58, 63, 79, 78, 57, 40, 62, 73, 25, 27, 72}} + ] + ] + ] + ] + GroupManager [ + ] + ] + ] +] + diff --git a/test/test_fem/test_inverse_map_hexahedron_20.verified b/test/test_fem/test_inverse_map_hexahedron_20.verified index e69de29bb..2e23c245e 100644 --- a/test/test_fem/test_inverse_map_hexahedron_20.verified +++ b/test/test_fem/test_inverse_map_hexahedron_20.verified @@ -0,0 +1 @@ +inverse completed over 8 elements diff --git a/test/test_io/test_parser/input_file.dat b/test/test_io/test_parser/input_file.dat index 26cce7d3b..e83f1dc28 100644 --- a/test/test_io/test_parser/input_file.dat +++ b/test/test_io/test_parser/input_file.dat @@ -1,32 +1,32 @@ seed = 123456 debug_level = 1 material elastic opt1 [ name = toto E = 1 X135 = 1 + 3* debug_level #toto # tptp yop = yop # a = b a = c rules material [ name = toto E = 1 X135 = 1 + 1 #toto # tptp yop = yop # a = b ] ] general = 50 toto = 2*pi + max(2, general) vect = [ 1, 23+2, 5, toto ] mat = [[ 1, 23+2, 5, toto ],\ - vect ] + [ 0, 10, general, 5+8] ] rand1 = 10 uniform [0.2, 0.5 ] rand2 = 10 weibull [0.2, 0.5 ] rand3 = 10 diff --git a/test/test_io/test_parser/test_parser.verified b/test/test_io/test_parser/test_parser.verified index 4ddbf1b92..570ad7a06 100644 --- a/test/test_io/test_parser/test_parser.verified +++ b/test/test_io/test_parser/test_parser.verified @@ -1,44 +1,44 @@ 123456==123456 Section(_st_global) global [ Parameters [ + debug_level: 1 (input_file.dat:2:1) + general: 50 (input_file.dat:22:1) - + mat: [[ 1, 23+2, 5, toto ],vect ] (input_file.dat:27:1) + + mat: [[ 1, 23+2, 5, toto ],[ 0, 10, general, 5+8] ] (input_file.dat:27:1) + rand1: 10 uniform [0.2, 0.5 ] (input_file.dat:30:1) + rand2: 10 weibull [0.2, 0.5 ] (input_file.dat:31:1) + rand3: 10 (input_file.dat:32:1) + seed: 123456 (input_file.dat:1:1) + toto: 2*pi + max(2, general) (input_file.dat:24:1) + vect: [ 1, 23+2, 5, toto ] (input_file.dat:26:1) ] Subsections [ Section(_st_material) elastic opt1 [ Parameters [ + E: 1 (input_file.dat:5:6) + X135: 1 + 3* debug_level (input_file.dat:6:6) + a: c (input_file.dat:11:6) + name: toto (input_file.dat:4:6) + yop: yop (input_file.dat:9:6) ] Subsections [ Section(_st_rules) material [ Parameters [ + E: 1 (input_file.dat:15:11) + X135: 1 + 1 (input_file.dat:16:11) + name: toto (input_file.dat:14:11) + yop: yop (input_file.dat:18:11) ] ] ] ] ] ] 56.2832==56.2832 -Vector(4) : [1, 25, 5, 56.2832] -Matrix(2,4) :[[1, 25, 5, 56.2832], [1, 25, 5, 56.2832]] +[1, 25, 5, 56.2832] +[[1, 25, 5, 56.2832], [0, 10, 50, 13]] 10 Uniform [ min=0.2, max=0.5 ] 10 Weibull [ shape=0.5, scale=0.2] 10 diff --git a/test/test_mesh_utils/CMakeLists.txt b/test/test_mesh_utils/CMakeLists.txt index 398a8eb47..2226ea5c9 100644 --- a/test/test_mesh_utils/CMakeLists.txt +++ b/test/test_mesh_utils/CMakeLists.txt @@ -1,48 +1,48 @@ #=============================================================================== # @file CMakeLists.txt # # @author Nicolas Richart # # @date creation: Mon Feb 07 2011 # @date last modification: Tue Nov 06 2012 # # @brief configuration for MeshUtils 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 . # # @section DESCRIPTION # #=============================================================================== #=============================================================================== # List of tests #=============================================================================== add_akantu_test(test_mesh_io "Test mesh io object") -add_akantu_test(test_facet_extraction "Test mesh utils facet extraction") add_akantu_test(test_pbc_tweak "Test pbc facilities") +add_akantu_test(test_buildfacets "Tests for the generation of facets") register_test(test_purify_mesh SOURCES test_purify_mesh.cc FILES_TO_COPY purify_mesh.msh PACKAGE core ) add_akantu_test(test_mesh_partitionate "Test mesh partition creation") diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfacets/CMakeLists.txt b/test/test_mesh_utils/test_buildfacets/CMakeLists.txt similarity index 79% rename from test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfacets/CMakeLists.txt rename to test/test_mesh_utils/test_buildfacets/CMakeLists.txt index 9ccc985cc..25a03db1c 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfacets/CMakeLists.txt +++ b/test/test_mesh_utils/test_buildfacets/CMakeLists.txt @@ -1,45 +1,42 @@ #=============================================================================== # @file CMakeLists.txt # # @author Marco Vocialta # # @date Tue May 08 13:01:18 2012 # # @brief configuration for build facets test # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== -register_test(test_cohesive_buildfacets_tetrahedron - SOURCES test_cohesive_buildfacets_tetrahedron.cc +register_test(test_buildfacets_tetrahedron + SOURCES test_buildfacets_tetrahedron.cc FILES_TO_COPY tetrahedron.msh PACKAGE cohesive_element ) -register_test(test_cohesive_buildfacets_hexahedron - SOURCES test_cohesive_buildfacets_hexahedron.cc +register_test(test_buildfacets_hexahedron + SOURCES test_buildfacets_hexahedron.cc FILES_TO_COPY hexahedron.msh PACKAGE cohesive_element ) -#add_mesh(test_cohesive_buildfacets_mesh mesh.geo 3 2) -#add_dependencies(test_cohesive_buildfacets test_cohesive_buildfacets_mesh) - diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfacets/hexahedron.msh b/test/test_mesh_utils/test_buildfacets/hexahedron.msh similarity index 100% rename from test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfacets/hexahedron.msh rename to test/test_mesh_utils/test_buildfacets/hexahedron.msh diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfacets/test_cohesive_buildfacets_hexahedron.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron.cc similarity index 98% rename from test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfacets/test_cohesive_buildfacets_hexahedron.cc rename to test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron.cc index 8d1143306..c4d5024cb 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfacets/test_cohesive_buildfacets_hexahedron.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_hexahedron.cc @@ -1,228 +1,224 @@ /** * @file test_cohesive_buildfacets_hexahedron.cc * * @author Marco Vocialta * * @date Wed Oct 03 10:20:53 2012 * * @brief Test for cohesive elements * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" #include "mesh_utils.hh" -#include "solid_mechanics_model.hh" -#include "material.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 3; const ElementType type = _hexahedron_8; Mesh mesh(spatial_dimension); mesh.read("hexahedron.msh"); Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); MeshUtils::buildAllFacets(mesh, mesh_facets); // debug::setDebugLevel(dblDump); // std::cout << mesh << std::endl; // std::cout << mesh_facets << std::endl; const ElementType type_facet = mesh.getFacetType(type); const ElementType type_subfacet = mesh.getFacetType(type_facet); const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ const Array< std::vector > & el_to_subel3 = mesh_facets.getElementToSubelement(type_facet); const Array< std::vector > & el_to_subel2 = mesh_facets.getElementToSubelement(type_subfacet); const Array< std::vector > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subsubfacet); /// build vectors for comparison Array hexahedron(2); hexahedron(0).type = type; hexahedron(0).element = 0; hexahedron(1).type = type; hexahedron(1).element = 3; Array quadrangle(4); quadrangle(0).type = type_facet; quadrangle(0).element = 1; quadrangle(1).type = type_facet; quadrangle(1).element = 2; quadrangle(2).type = type_facet; quadrangle(2).element = 7; quadrangle(3).type = type_facet; quadrangle(3).element = 11; Array segment(5); segment(0).type = type_subfacet; segment(0).element = 0; segment(1).type = type_subfacet; segment(1).element = 1; segment(2).type = type_subfacet; segment(2).element = 4; segment(3).type = type_subfacet; segment(3).element = 15; segment(4).type = type_subfacet; segment(4).element = 22; /// comparison for (UInt i = 0; i < hexahedron.getSize(); ++i) { if (hexahedron(i).type != el_to_subel3(1)[i].type || hexahedron(i).element != el_to_subel3(1)[i].element) { std::cout << hexahedron(i).element << " " << el_to_subel3(4)[i].element << std::endl; std::cout << "The two hexahedrons connected to quadrangle 1 are wrong" << std::endl; return EXIT_FAILURE; } } for (UInt i = 0; i < quadrangle.getSize(); ++i) { if (quadrangle(i).type != el_to_subel2(4)[i].type || quadrangle(i).element != el_to_subel2(4)[i].element) { std::cout << "The quadrangles connected to segment 4 are wrong" << std::endl; return EXIT_FAILURE; } } for (UInt i = 0; i < segment.getSize(); ++i) { if (segment(i).type != el_to_subel1(1)[i].type || segment(i).element != el_to_subel1(1)[i].element) { std::cout << "The segments connected to point 1 are wrong" << std::endl; return EXIT_FAILURE; } } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array & subel_to_el3 = mesh_facets.getSubelementToElement(type); const Array & subel_to_el2 = mesh_facets.getSubelementToElement(type_facet); const Array & subel_to_el1 = mesh_facets.getSubelementToElement(type_subfacet); /// build vectors for comparison Array quadrangle2(mesh.getNbFacetsPerElement(type)); quadrangle2(0).type = type_facet; quadrangle2(0).element = 1; quadrangle2(1).type = type_facet; quadrangle2(1).element = 11; quadrangle2(2).type = type_facet; quadrangle2(2).element = 16; quadrangle2(3).type = type_facet; quadrangle2(3).element = 17; quadrangle2(4).type = type_facet; quadrangle2(4).element = 18; quadrangle2(5).type = type_facet; quadrangle2(5).element = 19; Array segment2(4); segment2(0).type = type_subfacet; segment2(0).element = 3; segment2(1).type = type_subfacet; segment2(1).element = 6; segment2(2).type = type_subfacet; segment2(2).element = 9; segment2(3).type = type_subfacet; segment2(3).element = 11; Array point(2); point(0).type = mesh.getFacetType(type_subfacet); point(0).element = 5; point(1).type = mesh.getFacetType(type_subfacet); point(1).element = 7; /// comparison for (UInt i = 0; i < quadrangle2.getSize(); ++i) { if (quadrangle2(i).type != subel_to_el3(3, i).type || quadrangle2(i).element != subel_to_el3(3, i).element) { std::cout << "The quadrangles connected to hexahedron 3 are wrong" << std::endl; return EXIT_FAILURE; } } for (UInt i = 0; i < segment2.getSize(); ++i) { if (segment2(i).type != subel_to_el2(4, i).type || segment2(i).element != subel_to_el2(4, i).element) { std::cout << "The segments connected to quadrangle 4 are wrong" << std::endl; return EXIT_FAILURE; } } for (UInt i = 0; i < point.getSize(); ++i) { if (point(i).type != subel_to_el1(11, i).type || point(i).element != subel_to_el1(11, i).element) { std::cout << "The points connected to segment 11 are wrong" << std::endl; return EXIT_FAILURE; } } finalize(); std::cout << "OK: test_cohesive_buildfacets was passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfacets/test_cohesive_buildfacets_tetrahedron.cc b/test/test_mesh_utils/test_buildfacets/test_buildfacets_tetrahedron.cc similarity index 98% rename from test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfacets/test_cohesive_buildfacets_tetrahedron.cc rename to test/test_mesh_utils/test_buildfacets/test_buildfacets_tetrahedron.cc index 33d46cb20..19ad0eccb 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfacets/test_cohesive_buildfacets_tetrahedron.cc +++ b/test/test_mesh_utils/test_buildfacets/test_buildfacets_tetrahedron.cc @@ -1,253 +1,249 @@ /** * @file test_cohesive_buildfacets_tetrahedron.cc * * @author Marco Vocialta * * @date Wed Oct 03 10:20:53 2012 * * @brief Test for cohesive elements * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" #include "mesh_utils.hh" -#include "solid_mechanics_model.hh" -#include "material.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize(argc, argv); const UInt spatial_dimension = 3; const ElementType type = _tetrahedron_10; Mesh mesh(spatial_dimension); mesh.read("tetrahedron.msh"); Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); MeshUtils::buildAllFacets(mesh, mesh_facets); // debug::setDebugLevel(dblDump); // std::cout << mesh << std::endl; // std::cout << mesh_facets << std::endl; const ElementType type_facet = mesh.getFacetType(type); const ElementType type_subfacet = mesh.getFacetType(type_facet); const ElementType type_subsubfacet = mesh.getFacetType(type_subfacet); /* ------------------------------------------------------------------------ */ /* Element to Subelement testing */ /* ------------------------------------------------------------------------ */ const Array< std::vector > & el_to_subel3 = mesh_facets.getElementToSubelement(type_facet); const Array< std::vector > & el_to_subel2 = mesh_facets.getElementToSubelement(type_subfacet); const Array< std::vector > & el_to_subel1 = mesh_facets.getElementToSubelement(type_subsubfacet); /// build vectors for comparison Array tetrahedron(2); tetrahedron(0).type = type; tetrahedron(0).element = 1; tetrahedron(1).type = type; tetrahedron(1).element = 11; Array triangle(8); triangle(0).type = type_facet; triangle(0).element = 0; triangle(1).type = type_facet; triangle(1).element = 2; triangle(2).type = type_facet; triangle(2).element = 4; triangle(3).type = type_facet; triangle(3).element = 7; triangle(4).type = type_facet; triangle(4).element = 16; triangle(5).type = type_facet; triangle(5).element = 18; triangle(6).type = type_facet; triangle(6).element = 24; triangle(7).type = type_facet; triangle(7).element = 26; Array segment(13); segment(0).type = type_subfacet; segment(0).element = 0; segment(1).type = type_subfacet; segment(1).element = 1; segment(2).type = type_subfacet; segment(2).element = 3; segment(3).type = type_subfacet; segment(3).element = 7; segment(4).type = type_subfacet; segment(4).element = 9; segment(5).type = type_subfacet; segment(5).element = 12; segment(6).type = type_subfacet; segment(6).element = 13; segment(7).type = type_subfacet; segment(7).element = 16; segment(8).type = type_subfacet; segment(8).element = 18; segment(9).type = type_subfacet; segment(9).element = 21; segment(10).type = type_subfacet; segment(10).element = 27; segment(11).type = type_subfacet; segment(11).element = 32; segment(12).type = type_subfacet; segment(12).element = 34; /// comparison for (UInt i = 0; i < tetrahedron.getSize(); ++i) { if (tetrahedron(i).type != el_to_subel3(4)[i].type || tetrahedron(i).element != el_to_subel3(4)[i].element) { std::cout << tetrahedron(i).element << " " << el_to_subel3(4)[i].element << std::endl; std::cout << "The two tetrahedrons connected to triangle 4 are wrong" << std::endl; return EXIT_FAILURE; } } for (UInt i = 0; i < triangle.getSize(); ++i) { if (triangle(i).type != el_to_subel2(0)[i].type || triangle(i).element != el_to_subel2(0)[i].element) { std::cout << "The triangles connected to segment 0 are wrong" << std::endl; return EXIT_FAILURE; } } for (UInt i = 0; i < segment.getSize(); ++i) { if (segment(i).type != el_to_subel1(1)[i].type || segment(i).element != el_to_subel1(1)[i].element) { std::cout << "The segments connected to point 1 are wrong" << std::endl; return EXIT_FAILURE; } } /* ------------------------------------------------------------------------ */ /* Subelement to Element testing */ /* ------------------------------------------------------------------------ */ const Array & subel_to_el3 = mesh_facets.getSubelementToElement(type); const Array & subel_to_el2 = mesh_facets.getSubelementToElement(type_facet); const Array & subel_to_el1 = mesh_facets.getSubelementToElement(type_subfacet); /// build vectors for comparison Array triangle2(mesh.getNbFacetsPerElement(type)); triangle2(0).type = type_facet; triangle2(0).element = 4; triangle2(1).type = type_facet; triangle2(1).element = 5; triangle2(2).type = type_facet; triangle2(2).element = 6; triangle2(3).type = type_facet; triangle2(3).element = 7; Array segment2(3); segment2(0).type = type_subfacet; segment2(0).element = 1; segment2(1).type = type_subfacet; segment2(1).element = 3; segment2(2).type = type_subfacet; segment2(2).element = 4; Array point(2); point(0).type = mesh.getFacetType(type_subfacet); point(0).element = 1; point(1).type = mesh.getFacetType(type_subfacet); point(1).element = 2; /// comparison for (UInt i = 0; i < triangle2.getSize(); ++i) { if (triangle2(i).type != subel_to_el3(1, i).type || triangle2(i).element != subel_to_el3(1, i).element) { std::cout << "The triangles connected to tetrahedron 1 are wrong" << std::endl; return EXIT_FAILURE; } } for (UInt i = 0; i < segment2.getSize(); ++i) { if (segment2(i).type != subel_to_el2(1, i).type || segment2(i).element != subel_to_el2(1, i).element) { std::cout << "The segments connected to triangle 1 are wrong" << std::endl; return EXIT_FAILURE; } } for (UInt i = 0; i < point.getSize(); ++i) { if (point(i).type != subel_to_el1(1, i).type || point(i).element != subel_to_el1(1, i).element) { std::cout << "The points connected to segment 1 are wrong" << std::endl; return EXIT_FAILURE; } } finalize(); std::cout << "OK: test_cohesive_buildfacets was passed!" << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfacets/tetrahedron.msh b/test/test_mesh_utils/test_buildfacets/tetrahedron.msh similarity index 100% rename from test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_buildfacets/tetrahedron.msh rename to test/test_mesh_utils/test_buildfacets/tetrahedron.msh diff --git a/test/test_mesh_utils/test_facet_extraction/CMakeLists.txt b/test/test_mesh_utils/test_facet_extraction/CMakeLists.txt deleted file mode 100644 index 2f04bc5b9..000000000 --- a/test/test_mesh_utils/test_facet_extraction/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -#=============================================================================== -# @file CMakeLists.txt -# -# @author Guillaume Anciaux -# -# @date creation: Fri Sep 03 2010 -# @date last modification: Tue Nov 06 2012 -# -# @brief configuration for facet extraction 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 . -# -# @section DESCRIPTION -# -#=============================================================================== - -#=============================================================================== -add_mesh(test_facet_square_mesh square.geo 2 2) - -register_test(test_facet_extraction_triangle_3 - SOURCES test_facet_extraction_triangle_3.cc - DEPENDENCIES test_facet_square_mesh - DIRECTORIES_TO_CREATE paraview - PACKAGE core - ) - -#=============================================================================== -add_mesh(test_facet_cube_mesh cube.geo 3 1) - -register_test(test_facet_extraction_tetrahedron_4 - SOURCES test_facet_extraction_tetrahedron_4.cc - DEPENDENCIES test_facet_cube_mesh - DIRECTORIES_TO_CREATE paraview - PACKAGE core - ) diff --git a/test/test_mesh_utils/test_facet_extraction/cube.geo b/test/test_mesh_utils/test_facet_extraction/cube.geo deleted file mode 100644 index 415cca7c4..000000000 --- a/test/test_mesh_utils/test_facet_extraction/cube.geo +++ /dev/null @@ -1,37 +0,0 @@ -h = 0.1; - -Point(1) = {0.0, 0.0, 0.0, h}; -Point(2) = {1.0, 0.0, 0.0, h}; -Point(3) = {0.0, 1.0, 0.0, h}; -Point(4) = {1.0, 1.0, 0.0, h}; -Point(5) = {0.0, 0.0, 1.0, h}; -Point(6) = {1.0, 0.0, 1.0, h}; -Point(7) = {0.0, 1.0, 1.0, h}; -Point(8) = {1.0, 1.0, 1.0, h}; - -Line(1) = {7, 8}; -Line(2) = {8, 4}; -Line(3) = {4, 3}; -Line(4) = {3, 7}; -Line(5) = {1, 5}; -Line(6) = {5, 6}; -Line(7) = {6, 2}; -Line(8) = {2, 1}; -Line(9) = {3, 1}; -Line(10) = {7, 5}; -Line(11) = {8, 6}; -Line(12) = {4, 2}; -Line Loop(13) = {1, 11, -6, -10}; -Plane Surface(14) = {13}; -Line Loop(15) = {3, 4, 1, 2}; -Plane Surface(16) = {15}; -Line Loop(17) = {6, 7, 8, 5}; -Plane Surface(18) = {17}; -Line Loop(19) = {3, 9, -8, -12}; -Plane Surface(20) = {19}; -Line Loop(21) = {4, 10, -5, -9}; -Plane Surface(22) = {21}; -Line Loop(23) = {11, 7, -12, -2}; -Plane Surface(24) = {23}; -Surface Loop(25) = {24, 14, 16, 20, 22, 18}; -Volume(26) = {25}; diff --git a/test/test_mesh_utils/test_facet_extraction/square.geo b/test/test_mesh_utils/test_facet_extraction/square.geo deleted file mode 100644 index 33d1d3cc2..000000000 --- a/test/test_mesh_utils/test_facet_extraction/square.geo +++ /dev/null @@ -1,11 +0,0 @@ -Point(1) = {0.0, 0.0, 0.0, .5}; -Point(2) = {1.0, 0.0, 0.0, .5}; -Point(3) = {0.0, 1.0, 0.0, .5}; -Point(4) = {1.0, 1.0, 0.0, .5}; - -Line(1) = {1, 2}; -Line(2) = {2, 4}; -Line(3) = {4, 3}; -Line(4) = {3, 1}; -Line Loop(1) = {1, 2, 3, 4}; -Plane Surface(1) = {1}; diff --git a/test/test_mesh_utils/test_facet_extraction/test_facet_extraction_tetrahedron_4.cc b/test/test_mesh_utils/test_facet_extraction/test_facet_extraction_tetrahedron_4.cc deleted file mode 100644 index e7ab326b1..000000000 --- a/test/test_mesh_utils/test_facet_extraction/test_facet_extraction_tetrahedron_4.cc +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @file test_facet_extraction_tetrahedron_4.cc - * - * @author Guillaume Anciaux - * @author Marco Vocialta - * - * @date creation: Fri Sep 03 2010 - * @date last modification: Tue Jan 07 2014 - * - * @brief test of internal facet extraction - * - * @section LICENSE - * - * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) - * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) - * - * Akantu is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Akantu. If not, see . - * - */ - -/* -------------------------------------------------------------------------- */ - -/* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" -#include "solid_mechanics_model.hh" -#include "material.hh" -/* -------------------------------------------------------------------------- */ -#ifdef AKANTU_USE_IOHELPER -# include "dumper_paraview.hh" -#endif //AKANTU_USE_IOHELPER - -using namespace akantu; - -int main(int argc, char *argv[]) -{ - akantu::initialize(argc, argv); - int dim = 3; - - Mesh mesh(dim); - MeshIOMSH mesh_io; - mesh_io.read("cube.msh", mesh); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); - - MeshUtils::buildAllFacets(mesh, mesh_facets); - -#ifdef AKANTU_USE_IOHELPER - DumperParaview dumper1("test-facet-extraction"); - dumper1.registerMesh(mesh, dim); - dumper1.dump(); - - DumperParaview dumper2("test-facet-extraction_boundary"); - dumper2.registerMesh(mesh, dim - 1); - dumper2.dump(); - - DumperParaview dumper3("test-facet-extraction_internal"); - dumper3.registerMesh(mesh_facets, dim); - dumper3.dump(); -#endif //AKANTU_USE_IOHELPER - - akantu::finalize(); - return EXIT_SUCCESS; -} diff --git a/test/test_mesh_utils/test_facet_extraction/test_facet_extraction_triangle_3.cc b/test/test_mesh_utils/test_facet_extraction/test_facet_extraction_triangle_3.cc deleted file mode 100644 index 5bf0d5d8f..000000000 --- a/test/test_mesh_utils/test_facet_extraction/test_facet_extraction_triangle_3.cc +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @file test_facet_extraction_triangle_3.cc - * - * @author Guillaume Anciaux - * @author Marco Vocialta - * - * @date creation: Fri Sep 03 2010 - * @date last modification: Tue Jan 07 2014 - * - * @brief test of internal facet extraction - * - * @section LICENSE - * - * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) - * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) - * - * Akantu is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Akantu. If not, see . - * - */ - -/* -------------------------------------------------------------------------- */ - -/* -------------------------------------------------------------------------- */ -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_utils.hh" -#include "material.hh" -/* -------------------------------------------------------------------------- */ -#ifdef AKANTU_USE_IOHELPER -# include "dumper_paraview.hh" -#endif //AKANTU_USE_IOHELPER - -using namespace akantu; - -int main(int argc, char *argv[]) -{ - akantu::initialize(argc, argv); - const ElementType type = _triangle_6; - int dim = ElementClass::getSpatialDimension(); - - Mesh mesh(dim); - mesh.read("square.msh"); - Mesh mesh_facets(mesh.initMeshFacets("mesh_facets")); - - MeshUtils::buildAllFacets(mesh, mesh_facets); - -#ifdef AKANTU_USE_IOHELPER - DumperParaview dumper1("test-facet-extraction"); - dumper1.registerMesh(mesh, dim); - dumper1.dump(); - - DumperParaview dumper2("test-facet-extraction_boundary"); - dumper2.registerMesh(mesh, dim - 1); - dumper2.dump(); - - DumperParaview dumper3("test-facet-extraction_internal"); - dumper3.registerMesh(mesh_facets, dim); - dumper3.dump(); -#endif //AKANTU_USE_IOHELPER - akantu::finalize(); - return EXIT_SUCCESS; -} diff --git a/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_mesh_data.cc b/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_mesh_data.cc index 03f152f39..ad680a112 100644 --- a/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_mesh_data.cc +++ b/test/test_mesh_utils/test_mesh_partitionate/test_mesh_partitionate_mesh_data.cc @@ -1,107 +1,116 @@ /** * @file test_mesh_partitionate_mesh_data.cc * * @author Dana Christen * * @date creation: Wed May 08 2013 * @date last modification: Fri Sep 05 2014 * * @brief test of manual partitioner * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_partition_mesh_data.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "dumper_paraview.hh" #include "dumper_elemental_field.hh" #endif //AKANTU_USE_IOHELPER using namespace akantu; /* -------------------------------------------------------------------------- */ /* Main */ /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { initialize(argc, argv); UInt dim = 2; UInt nb_partitions = 8; akantu::Mesh mesh(dim); mesh.read("quad.msh"); + ElementTypeMapArray partition; UInt nb_component = 1; + GhostType gt = _not_ghost; Mesh::type_iterator tit = mesh.firstType(dim, gt); Mesh::type_iterator tend = mesh.lastType(dim, gt); for(; tit != tend; ++tit) { UInt nb_element = mesh.getNbElement(*tit, gt); partition.alloc(nb_element, nb_component, *tit, gt); Array & type_partition_reference = partition(*tit, gt); for(UInt i(0); i < nb_element; ++i) { Real barycenter[dim]; mesh.getBarycenter(i, *tit, barycenter, gt); Real real_proc = barycenter[0] * nb_partitions; - if(real_proc-round(real_proc) < 10*std::numeric_limits::min()) { + if(std::abs(real_proc - round(real_proc)) < 10*std::numeric_limits::epsilon()) { type_partition_reference(i) = round(real_proc); } else { std::cout << "*"; type_partition_reference(i) = floor(real_proc); } std::cout << "Assigned proc " << type_partition_reference(i) << " to elem " << i << " (type " << *tit << ", barycenter x-coordinate " << barycenter[0] << ")" << std::endl; } } + akantu::MeshPartitionMeshData * partitioner = new akantu::MeshPartitionMeshData(mesh, dim); partitioner->setPartitionMapping(partition); partitioner->partitionate(nb_partitions); tit = mesh.firstType(dim, gt); for(; tit != tend; ++tit) { UInt nb_element = mesh.getNbElement(*tit, gt); const Array & type_partition_reference = partition(*tit, gt); const Array & type_partition = partitioner->getPartitions()(*tit, gt); for(UInt i(0); i < nb_element; ++i) { AKANTU_DEBUG_ASSERT(type_partition(i) == type_partition_reference(i), "Incorrect partitioning"); } } -#ifdef AKANTU_USE_IOHELPER + //#define DEBUG_TEST + +#ifdef DEBUG_TEST DumperParaview dumper("test-mesh-data-partition"); - dumper::Field * field = + dumper::Field * field1 = new dumper::ElementalField(partitioner->getPartitions(), dim); + dumper::Field * field2 = + new dumper::ElementalField(partition, dim); dumper.registerMesh(mesh, dim); - dumper.registerField("partitions", field); + dumper.registerField("partitions" , field1); + dumper.registerField("partitions_ref", field2); dumper.dump(); -#endif //AKANTU_USE_IOHELPER +#endif + delete partitioner; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_cohesive/CMakeLists.txt index e0d81456f..893a085b1 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/CMakeLists.txt @@ -1,40 +1,39 @@ #=============================================================================== # @file CMakeLists.txt # # @author Marco Vocialta # # @date creation: Tue May 08 2012 # @date last modification: Fri Jun 21 2013 # # @brief configuration for cohesive elements tests # # @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 . # # @section DESCRIPTION # #=============================================================================== -add_akantu_test(test_cohesive_buildfacets "test_cohesive_buildfacets") add_akantu_test(test_cohesive_intrinsic "test_cohesive_intrinsic") add_akantu_test(test_cohesive_extrinsic "test_cohesive_extrinsic") add_akantu_test(test_cohesive_buildfragments "test_cohesive_buildfragments") add_akantu_test(test_cohesive_intrinsic_impl "test_cohesive_intrinsic_impl") add_akantu_test(test_cohesive_1d_element "test_cohesive_1d_element") add_akantu_test(test_cohesive_extrinsic_implicit "test_cohesive_extrinsic_implicit") #=============================================================================== diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/CMakeLists.txt index 9fe5cbdb1..1e2c3ea33 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/CMakeLists.txt @@ -1,64 +1,62 @@ #=============================================================================== # @file CMakeLists.txt # # @author Marco Vocialta # # @date creation: Tue May 08 2012 # @date last modification: Wed Oct 09 2013 # # @brief configuration for extrinsic cohesive elements tests # # @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 . # # @section DESCRIPTION # #=============================================================================== add_mesh(test_cohesive_extrinsic_mesh triangle.geo 2 1) add_mesh(test_cohesive_extrinsic_quadrangle_mesh quadrangle.geo 2 2) add_mesh(test_cohesive_extrinsic_tetrahedron_mesh tetrahedron.geo 3 2) -add_mesh(test_cohesive_extrinsic_fatigue_mesh fatigue.geo 2 1) register_test(test_cohesive_extrinsic SOURCES test_cohesive_extrinsic.cc DEPENDENCIES test_cohesive_extrinsic_mesh FILES_TO_COPY material.dat DIRECTORIES_TO_CREATE paraview PACKAGE cohesive_element ) register_test(test_cohesive_extrinsic_quadrangle SOURCES test_cohesive_extrinsic_quadrangle.cc DEPENDENCIES test_cohesive_extrinsic_quadrangle_mesh PACKAGE cohesive_element ) register_test(test_cohesive_extrinsic_tetrahedron SOURCES test_cohesive_extrinsic_tetrahedron.cc DEPENDENCIES test_cohesive_extrinsic_tetrahedron_mesh PACKAGE cohesive_element ) register_test(test_cohesive_extrinsic_fatigue SOURCES test_cohesive_extrinsic_fatigue.cc - DEPENDENCIES test_cohesive_extrinsic_fatigue_mesh - FILES_TO_COPY material_fatigue.dat + FILES_TO_COPY material_fatigue.dat fatigue.msh DIRECTORIES_TO_CREATE paraview PACKAGE cohesive_element ) diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/fatigue.geo b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/fatigue.geo deleted file mode 100644 index 2b13ad957..000000000 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/fatigue.geo +++ /dev/null @@ -1,18 +0,0 @@ -Point(1) = {0, 0, 0, 1}; -Point(2) = {2, 0, 0, 1}; -Point(3) = {2, 1, 0, 1}; -Point(4) = {0, 1, 0, 1}; - -Line(1) = {1, 2}; -Line(2) = {2, 3}; -Line(3) = {3, 4}; -Line(4) = {4, 1}; - -Line Loop(5) = {4, 1, 2, 3}; -Plane Surface(6) = {5}; -Physical Surface(7) = {6}; - -Transfinite Line {1, 3} = 3; -Transfinite Line {2, 4} = 2; - -Recombine Surface "*"; diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/fatigue.msh b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/fatigue.msh new file mode 100644 index 000000000..ac0ee23d8 --- /dev/null +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/fatigue.msh @@ -0,0 +1,17 @@ +$MeshFormat +2.2 0 8 +$EndMeshFormat +$Nodes +6 +1 0 0 0 +2 2 0 0 +3 2 1 0 +4 0 1 0 +5 0.9999999999973842 0 0 +6 1.000000000004119 1 0 +$EndNodes +$Elements +2 +1 3 2 7 6 2 3 6 5 +2 3 2 7 6 1 5 6 4 +$EndElements diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_fatigue.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_fatigue.cc index b34b8195c..842fb0426 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_fatigue.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic/test_cohesive_extrinsic_fatigue.cc @@ -1,228 +1,230 @@ /** * @file test_cohesive_intrinsic_fatigue.cc * @author Marco Vocialta * @date Fri Feb 20 10:13:14 2015 * * @brief Test for the linear fatigue cohesive law * * @section LICENSE * * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" #include "material_cohesive_linear_fatigue.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; // the following class contains an implementation of the 1D linear // fatigue cohesive law class MaterialFatigue { public: MaterialFatigue(Real delta_f, Real sigma_c, Real delta_c) : delta_f(delta_f), sigma_c(sigma_c), delta_c(delta_c), tolerance(Math::getTolerance()) {}; Real computeTraction(Real delta) { if (delta - delta_c > -tolerance) traction = 0; else if (delta_max < tolerance && delta < tolerance) traction = sigma_c; else { Real delta_dot = delta - delta_prec; if (delta_dot > -tolerance) { stiff_plus *= 1 - delta_dot / delta_f; traction += stiff_plus * delta_dot; Real max_traction = sigma_c * (1 - delta / delta_c); if (traction - max_traction > -tolerance || delta_max < tolerance) { traction = max_traction; stiff_plus = traction / delta; } } else { Real stiff_minus = traction / delta_prec; stiff_plus += (stiff_plus - stiff_minus) * delta_dot / delta_f; traction += stiff_minus * delta_dot; } } delta_prec = delta; delta_max = std::max(delta, delta_max); return traction; } private: const Real delta_f; const Real sigma_c; const Real delta_c; Real delta_prec; Real traction; Real delta_max; Real stiff_plus; const Real tolerance; }; void imposeOpening(SolidMechanicsModelCohesive &, Real); void arange(Array &, Real, Real, Real); /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { initialize("material_fatigue.dat", argc, argv); + Math::setTolerance(1e-13); + const UInt spatial_dimension = 2; const ElementType type = _quadrangle_4; Mesh mesh(spatial_dimension); mesh.read("fatigue.msh"); // init stuff const ElementType type_facet = Mesh::getFacetType(type); const ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet); SolidMechanicsModelCohesive model(mesh); model.initFull(SolidMechanicsModelCohesiveOptions(_explicit_lumped_mass, true)); MaterialCohesiveLinearFatigue<2> & numerical_material = dynamic_cast &>(model.getMaterial("cohesive")); Real delta_f = numerical_material.getParam("delta_f"); Real delta_c = numerical_material.getParam("delta_c"); Real sigma_c = 1; const Array & traction_array = numerical_material.getTraction(type_cohesive); MaterialFatigue theoretical_material(delta_f, sigma_c, delta_c); // model.setBaseName("fatigue"); // model.addDumpFieldVector("displacement"); // model.addDumpField("stress"); // model.dump(); // stretch material Real strain = 1; Array & displacement = model.getDisplacement(); const Array & position = mesh.getNodes(); for (UInt n = 0; n < mesh.getNbNodes(); ++n) displacement(n, 0) = position(n, 0) * strain; model.updateResidual(); // model.dump(); // insert cohesive elements model.checkCohesiveStress(); // create the displacement sequence Real increment = 0.01; Array openings; arange(openings, 0, 0.5, increment); arange(openings, 0.5, 0.1, increment); arange(openings, 0.1, 0.7, increment); arange(openings, 0.7, 0.3, increment); arange(openings, 0.3, 0.6, increment); arange(openings, 0.6, 0.3, increment); arange(openings, 0.3, 0.7, increment); arange(openings, 0.7, 1.3, increment); const Array & switches = numerical_material.getSwitches(type_cohesive); // std::ofstream edis("fatigue_edis.txt"); // impose openings for (UInt i = 0; i < openings.getSize(); ++i) { // compute numerical traction imposeOpening(model, openings(i)); model.updateResidual(); // model.dump(); Real numerical_traction = traction_array(0, 0); // compute theoretical traction Real theoretical_traction = theoretical_material.computeTraction(openings(i)); // test traction if (std::abs(numerical_traction - theoretical_traction) > 1e-13) AKANTU_DEBUG_ERROR("The numerical traction " << numerical_traction << " and theoretical traction " << theoretical_traction << " are not coincident"); // edis << model.getEnergy("dissipated") << std::endl; } if (switches(0) != 7) AKANTU_DEBUG_ERROR("The number of switches is wrong"); std::cout << "OK: the test_cohesive_extrinsic_fatigue passed." << std::endl; return 0; } /* -------------------------------------------------------------------------- */ void imposeOpening(SolidMechanicsModelCohesive & model, Real opening) { UInt spatial_dimension = model.getSpatialDimension(); Mesh & mesh = model.getFEEngine().getMesh(); Array & position = mesh.getNodes(); Array & displacement = model.getDisplacement(); UInt nb_nodes = mesh.getNbNodes(); Array update(nb_nodes); update.clear(); Mesh::type_iterator it = mesh.firstType(spatial_dimension); Mesh::type_iterator end = mesh.lastType(spatial_dimension); for (; it != end; ++it) { ElementType type = *it; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); const Array & connectivity = mesh.getConnectivity(type); Vector barycenter(spatial_dimension); for (UInt el = 0; el < nb_element; ++el) { mesh.getBarycenter(el, type, barycenter.storage()); if (barycenter(0) > 1) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity(el, n); if (!update(node)) { displacement(node, 0) = opening + position(node, 0); update(node) = true; } } } } } } /* -------------------------------------------------------------------------- */ void arange(Array & openings, Real begin, Real end, Real increment) { if (begin < end) { for (Real opening = begin; opening < end - increment / 2.; opening += increment) openings.push_back(opening); } else { for (Real opening = begin; opening > end + increment / 2.; opening -= increment) openings.push_back(opening); } } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/CMakeLists.txt index fd6209326..0f11d4de5 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/CMakeLists.txt @@ -1,41 +1,37 @@ #=============================================================================== # @file CMakeLists.txt # # @author Mauro Corrado # # @date Fri May 01 11:56:18 2015 # # @brief checking correct assembling of stiffness matrix in case of cohe elems # # @section LICENSE # # Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # # @section DESCRIPTION # #=============================================================================== register_test(test_assembling_K_cohe_elements SOURCES test_assembling_K_cohe_elements.cc - FILES_TO_COPY quadrangle.msh material.dat + FILES_TO_COPY quadrangle.msh material.dat K_matrix_verified PACKAGE cohesive_element ) - -#add_mesh(test_cohesive_buildfacets_mesh mesh.geo 3 2) -#add_dependencies(test_cohesive_buildfacets test_cohesive_buildfacets_mesh) - diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/K_matrix_verified b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/K_matrix_verified new file mode 100644 index 000000000..9ae429d9d --- /dev/null +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/K_matrix_verified @@ -0,0 +1,120 @@ +%%MatrixMarket matrix coordinate real symmetric +20 20 118 +17 17 80000 +17 18 0 +17 13 -1.81898940354586e-12 +17 14 0 +17 7 -10000 +17 8 5000 +17 15 -20000 +17 16 0 +18 18 80000 +18 13 0 +18 14 -20000 +18 7 5000 +18 8 -10000 +18 15 0 +18 16 -1.81898940354586e-12 +13 13 40000 +13 14 0 +13 7 -10000 +13 8 -5000 +13 15 -10000 +13 16 -5000 +14 14 40000 +14 7 5000 +14 8 -9.09494701772928e-13 +14 15 -5000 +14 16 -10000 +7 7 20000 +7 8 -5000 +7 15 -9.09494701772928e-13 +7 16 -5000 +8 8 20000 +8 15 5000 +8 16 -10000 +15 15 40000 +15 16 0 +16 16 40000 +17 11 -10000 +17 12 -5000 +17 5 -10000 +17 6 -5000 +18 11 5000 +18 12 -9.09494701772928e-13 +18 5 -5000 +18 6 -10000 +11 11 21320.8409773605 +11 12 -4882.11803623535 +11 5 -9.09494701772928e-13 +11 6 -5000 +11 13 -10000 +11 14 5000 +12 12 19800.7540266124 +12 5 5000 +12 6 -10000 +12 13 5000 +12 14 -10000 +5 5 20000 +5 6 5000 +5 13 -10000 +5 14 -5000 +6 6 20000 +6 13 5000 +6 14 -9.09494701772928e-13 +17 9 -1.81898940354586e-12 +17 10 0 +17 3 -10000 +17 4 5000 +17 19 -10000 +17 20 5000 +18 9 0 +18 10 -20000 +18 3 5000 +18 4 -10000 +18 19 -5000 +18 20 -9.09494701772928e-13 +9 9 40000 +9 10 0 +9 3 -10000 +9 4 -5000 +9 19 -10000 +9 20 -5000 +10 10 40000 +10 3 5000 +10 4 -9.09494701772928e-13 +10 19 -5000 +10 20 -10000 +3 3 20000 +3 4 -5000 +3 19 -9.09494701772928e-13 +3 20 -5000 +4 4 20000 +4 19 5000 +4 20 -10000 +19 19 21320.8409773605 +19 20 5117.88196376465 +20 20 19800.7540266124 +17 1 -10000 +17 2 -5000 +18 1 -5000 +18 2 -10000 +15 1 -9.09494701772928e-13 +15 2 -5000 +15 9 -10000 +15 10 5000 +16 1 5000 +16 2 -10000 +16 9 5000 +16 10 -10000 +1 1 20000 +1 2 5000 +1 9 -10000 +1 10 -5000 +2 2 20000 +2 9 5000 +2 10 -9.09494701772928e-13 +11 19 -1320.84097736047 +11 20 -117.881963764652 +12 19 -117.881963764652 +12 20 199.245973387621 diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/quadrangle.msh b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/quadrangle.msh index 5f9c0fc91..22a9d7f77 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/quadrangle.msh +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/quadrangle.msh @@ -1,22 +1,22 @@ $MeshFormat 2.2 0 8 $EndMeshFormat $Nodes 9 1 1 1 0 2 -1 1 0 3 -1 -1 0 4 1 -1 0 -5 2.750244476601438e-12 1 0 -6 -1 2.750244476601438e-12 0 -7 -2.750244476601438e-12 -1 0 -8 1 -2.750244476601438e-12 0 +5 0 1 0 +6 -1 0 0 +7 0 -1 0 +8 1 0 0 9 0 0 0 $EndNodes $Elements 4 1 3 2 7 6 9 7 4 8 2 3 2 7 6 9 6 3 7 3 3 2 7 6 9 5 2 6 4 3 2 7 6 9 8 1 5 $EndElements diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.cc b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.cc index 24acdfee9..911aaba82 100644 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.cc +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.cc @@ -1,118 +1,92 @@ /** * @file matrix_assembling_cohesive_elements.cc * * @author Mauro Corrado * * @date creation: Thu April 30 2015 * * @brief Test to check the correct matrix assembling for cohesive elements * with degenerated nodes * * @section LICENSE * * Copyright (©) 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" #include "material_cohesive.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { initialize("material.dat", argc, argv); debug::setDebugLevel(dblWarning); const UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); mesh.read("quadrangle.msh"); SolidMechanicsModelCohesive model(mesh); /// model initialization model.initFull(SolidMechanicsModelCohesiveOptions(_static, true)); // CohesiveElementInserter inserter(mesh); model.limitInsertion(_y, -0.001, 0.001); model.updateAutomaticInsertion(); /// boundary conditions Array & boundary = model.getBlockedDOFs(); Array & position = mesh.getNodes(); Array & displacement = model.getDisplacement(); for (UInt n = 0; n < mesh.getNbNodes(); ++n) { if (position(n,1) < -0.99){ boundary(n,1) = true; boundary(n,0) = true; } if (position(n,1) > 0.99 && position(n,0) < -0.99) boundary(n,1) = true; } - model.setBaseName("test_K"); - model.addDumpFieldVector("displacement"); - model.addDumpField("residual" ); - model.addDumpField("stress" ); - model.addDumpField("blocked_dofs"); - model.dump(); - - // Dumping cohesive elements - model.setBaseNameToDumper("cohesive elements", "cohe_test_K"); - model.addDumpFieldVectorToDumper("cohesive elements", "displacement"); - model.addDumpFieldToDumper("cohesive elements", "damage"); - model.dump("cohesive elements"); - Real increment = 0.004; Real error; for (UInt n = 0; n < mesh.getNbNodes(); ++n) { if (position(n,1) > 0.99 && position(n,0) < -0.99) displacement(n,1) += increment; } - model.solveStepCohesive<_scm_newton_raphson_tangent, _scc_increment>(1e-13, error, 100); - - model.dump(); - model.dump("cohesive elements"); - - // Matrix matrix = getStiffnessMatrix(); + model.solveStepCohesive<_scm_newton_raphson_tangent, _scc_increment>(1e-13, error, 10); /// save the matrix - model.getStiffnessMatrix().saveMatrix("K_matrix.txt"); - - /// print the matrix to screen - std::ifstream K_matrix; - K_matrix.open("K_matrix.txt"); - std::string current_line; - while(getline(K_matrix, current_line)) - std::cout << current_line << std::endl; - K_matrix.close(); + model.getStiffnessMatrix().saveMatrix("K_matrix_test"); finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.sh b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.sh new file mode 100755 index 000000000..bca1ece5e --- /dev/null +++ b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +./test_assembling_K_cohe_elements && diff K_matrix_verified K_matrix_test >/dev/null 2>&1 diff --git a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.verified b/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.verified deleted file mode 100644 index cbb10b5ac..000000000 --- a/test/test_model/test_solid_mechanics_model/test_cohesive/test_cohesive_extrinsic_implicit/test_assembling_K_cohe_elements.verified +++ /dev/null @@ -1,120 +0,0 @@ -%%MatrixMarket matrix coordinate real symmetric -20 20 118 -17 17 80000 -17 18 0 -17 13 -3.7310154965553e-12 -17 14 -2.75040292763151e-08 -17 7 -9999.99999997708 -17 8 5000 -17 15 -20000 -17 16 2.75031197816133e-08 -18 18 80000 -18 13 -2.75031197816133e-08 -18 14 -20000 -18 7 5000 -18 8 -10000.0000000229 -18 15 2.75040292763151e-08 -18 16 -3.7310154965553e-12 -13 13 40000 -13 14 9.09494701772928e-13 -13 7 -9999.99999994042 -13 8 -4999.99999998625 -13 15 -10000.0000000046 -13 16 -5000 -14 14 40000 -14 7 5000.00000001375 -14 8 5.04179989979647e-08 -14 15 -5000 -14 16 -9999.99999999541 -7 7 19999.9999999679 -7 8 -5000 -7 15 -5.04204070717051e-08 -7 16 -5000.00000001375 -8 8 20000.0000000321 -8 15 4999.99999998625 -8 16 -10000.0000000596 -15 15 40000 -15 16 -9.09494701772928e-13 -16 16 40000 -17 11 -10000.0000000321 -17 12 -4999.99999998625 -17 5 -10000.0000000229 -17 6 -5000 -18 11 5000.00000001375 -18 12 -2.29205738833116e-08 -18 5 -5000 -18 6 -9999.99999997708 -11 11 21320.8409773377 -11 12 -4882.1180362384 -11 5 5.04179989979647e-08 -11 6 -5000.00000001375 -11 13 -9999.99999999541 -11 14 5000 -12 12 19800.7540265798 -12 5 4999.99999998625 -12 6 -9999.99999994042 -12 13 5000 -12 14 -10000.0000000046 -5 5 20000.0000000321 -5 6 5000 -5 13 -10000.0000000596 -5 14 -4999.99999998625 -6 6 19999.9999999679 -6 13 5000.00000001375 -6 14 -5.04204070717051e-08 -17 9 -3.7310154965553e-12 -17 10 -2.75040292763151e-08 -17 3 -9999.99999997708 -17 4 5000 -17 19 -9999.99999996791 -17 20 5000.00000001375 -18 9 -2.75031197816133e-08 -18 10 -20000 -18 3 5000 -18 4 -10000.0000000229 -18 19 -4999.99999998625 -18 20 2.29168222176668e-08 -9 9 40000 -9 10 9.09494701772928e-13 -9 3 -9999.99999994042 -9 4 -4999.99999998625 -9 19 -10000.0000000046 -9 20 -5000 -10 10 40000 -10 3 5000.00000001375 -10 4 5.04179989979647e-08 -10 19 -5000 -10 20 -9999.99999999541 -3 3 19999.9999999679 -3 4 -5000 -3 19 -5.04204070717051e-08 -3 20 -5000.00000001375 -4 4 20000.0000000321 -4 19 4999.99999998625 -4 20 -10000.0000000596 -19 19 21320.8409773835 -19 20 5117.8819637616 -20 20 19800.754026644 -17 1 -10000.0000000229 -17 2 -5000 -18 1 -5000 -18 2 -9999.99999997708 -15 1 5.04179989979647e-08 -15 2 -5000.00000001375 -15 9 -9999.99999999541 -15 10 5000 -16 1 4999.99999998625 -16 2 -9999.99999994042 -16 9 5000 -16 10 -10000.0000000046 -1 1 20000.0000000321 -1 2 5000 -1 9 -10000.0000000596 -1 10 -4999.99999998625 -2 2 19999.9999999679 -2 9 5000.00000001375 -2 10 -5.04204070717051e-08 -11 19 -1320.84097736057 -11 20 -117.881963761601 -12 19 -117.881963761601 -12 20 199.245973388092 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 # # @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 . # # @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 # # @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 . # # @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") diff --git a/test/test_surface_extraction/CMakeLists.txt b/test/test_surface_extraction/CMakeLists.txt deleted file mode 100644 index f8cd2f36c..000000000 --- a/test/test_surface_extraction/CMakeLists.txt +++ /dev/null @@ -1,47 +0,0 @@ -#=============================================================================== -# @file CMakeLists.txt -# -# @author Leonardo Snozzi -# -# @date creation: Tue Oct 26 2010 -# @date last modification: Tue Nov 06 2012 -# -# @brief configuration for surface extraction 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 . -# -# @section DESCRIPTION -# -#=============================================================================== - -#=============================================================================== -add_mesh(test_surface_extraction_2d_mesh squares.geo 2 1) -register_test(test_surface_extraction_triangle_3 - SOURCES test_surface_extraction_triangle_3.cc - DEPENDENCIES test_surface_extraction_2d_mesh - PACKAGE core - ) - -#=============================================================================== -add_mesh(test_surface_extraction_3d_mesh cubes.geo 3 1) -register_test(test_surface_extraction_tetrahedron_4 - SOURCES test_surface_extraction_tetrahedron_4.cc - DEPENDENCIES test_surface_extraction_3d_mesh - PACKAGE core - ) diff --git a/test/test_surface_extraction/cubes.geo b/test/test_surface_extraction/cubes.geo deleted file mode 100644 index cdd2e3788..000000000 --- a/test/test_surface_extraction/cubes.geo +++ /dev/null @@ -1,74 +0,0 @@ -h = 1; - -Point(1) = {0, 0, 0, h}; -Point(2) = {1, 0, 0, h}; -Point(3) = {1, 1, 0, h}; -Point(4) = {0, 1, 0, h}; -Point(5) = {0, 0, 1, h}; -Point(6) = {1, 0, 1, h}; -Point(7) = {1, 1, 1, h}; -Point(8) = {0, 1, 1, h}; - -Point(9) = {2+0, 0, 0, h}; -Point(10) = {2+1, 0, 0, h}; -Point(11) = {2+1, 1, 0, h}; -Point(12) = {2+0, 1, 0, h}; -Point(13) = {2+0, 0, 1, h}; -Point(14) = {2+1, 0, 1, h}; -Point(15) = {2+1, 1, 1, h}; -Point(16) = {2+0, 1, 1, h}; - -Line(1) = {5, 6}; -Line(2) = {6, 7}; -Line(3) = {7, 8}; -Line(4) = {8, 5}; -Line(5) = {1, 2}; -Line(6) = {2, 3}; -Line(7) = {3, 4}; -Line(8) = {4, 1}; -Line(9) = {5, 1}; -Line(10) = {6, 2}; -Line(11) = {7, 3}; -Line(12) = {8, 4}; -Line(13) = {13, 14}; -Line(14) = {14, 15}; -Line(15) = {15, 16}; -Line(16) = {16, 13}; -Line(17) = {9, 10}; -Line(18) = {10, 11}; -Line(19) = {11, 12}; -Line(20) = {12, 9}; -Line(21) = {13, 9}; -Line(22) = {14, 10}; -Line(23) = {15, 11}; -Line(24) = {16, 12}; - - -Line Loop(25) = {4, 1, 2, 3}; -Plane Surface(26) = {25}; -Line Loop(27) = {7, 8, 5, 6}; -Plane Surface(28) = {27}; -Line Loop(29) = {12, -7, -11, 3}; -Plane Surface(30) = {29}; -Line Loop(31) = {12, 8, -9, -4}; -Plane Surface(32) = {31}; -Line Loop(33) = {1, 10, -5, -9}; -Plane Surface(34) = {33}; -Line Loop(35) = {2, 11, -6, -10}; -Plane Surface(36) = {35}; -Line Loop(37) = {16, 13, 14, 15}; -Plane Surface(38) = {37}; -Line Loop(39) = {20, 17, 18, 19}; -Plane Surface(40) = {39}; -Line Loop(41) = {24, 20, -21, -16}; -Plane Surface(42) = {41}; -Line Loop(43) = {13, 22, -17, -21}; -Plane Surface(44) = {43}; -Line Loop(45) = {14, 23, -18, -22}; -Plane Surface(46) = {45}; -Line Loop(47) = {15, 24, -19, -23}; -Plane Surface(48) = {47}; -Surface Loop(49) = {32, 30, 28, 34, 26, 36}; -Volume(50) = {49}; -Surface Loop(51) = {42, 48, 38, 44, 46, 40}; -Volume(52) = {51}; diff --git a/test/test_surface_extraction/squares.geo b/test/test_surface_extraction/squares.geo deleted file mode 100644 index d2e389681..000000000 --- a/test/test_surface_extraction/squares.geo +++ /dev/null @@ -1,37 +0,0 @@ -// Element size -h = 0.5; - -// Dimension of square -L = 1; - -// ------------------------------------------ -// Geometry -// ------------------------------------------ - -// Points -Point(1) = {0, 0, 0, h}; -Point(2) = {L, 0, 0, h}; -Point(3) = {L, L, 0, h}; -Point(4) = {0, L, 0, h}; - -Point(5) = {1.5*L, 0, 0, h}; -Point(6) = {2.5*L, 0, 0, h}; -Point(7) = {2.5*L, L, 0, h}; -Point(8) = {1.5*L, L, 0, h}; - -// Lines -Line(1) = {4, 1}; -Line(2) = {1, 2}; -Line(3) = {2, 3}; -Line(4) = {3, 4}; - -Line(5) = {8, 5}; -Line(6) = {5, 6}; -Line(7) = {6, 7}; -Line(8) = {7, 8}; - -// Geometric and Physical Surface -Line Loop(1) = {1, 2, 3, 4}; -Line Loop(2) = {5, 6, 7, 8}; -Plane Surface(1) = {1}; -Plane Surface(2) = {2}; diff --git a/test/test_surface_extraction/test_surface_extraction_tetrahedron_4.cc b/test/test_surface_extraction/test_surface_extraction_tetrahedron_4.cc deleted file mode 100644 index d667b447d..000000000 --- a/test/test_surface_extraction/test_surface_extraction_tetrahedron_4.cc +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @file test_surface_extraction_tetrahedron_4.cc - * - * @author Leonardo Snozzi - * @author Marco Vocialta - * - * @date creation: Tue Oct 26 2010 - * @date last modification: Thu Mar 27 2014 - * - * @brief 3d surface extraction 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 . - * - */ - -/* -------------------------------------------------------------------------- */ - -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" -#include "solid_mechanics_model.hh" -#include "material.hh" -#include - -#ifdef AKANTU_USE_IOHELPER -# include "io_helper.hh" - -#endif //AKANTU_USE_IOHELPER - -using namespace akantu; - -int main(int argc, char *argv[]) -{ - int dim = 3; - - akantu::initialize(argc, argv); - - Mesh mesh(dim); - MeshIOMSH mesh_io; - mesh_io.read("cubes.msh", mesh); - - MeshUtils::buildFacets(mesh); - - mesh.createBoundaryGroupFromGeometry(); -// MeshUtils::buildSurfaceID(mesh); - - unsigned int nb_nodes = mesh.getNbNodes(); -#ifdef AKANTU_USE_IOHELPER - iohelper::DumperParaview dumper; - dumper.setMode(iohelper::TEXT); - - dumper.setPoints(mesh.getNodes().storage(), dim, nb_nodes, "test-surface-extraction"); - dumper.setConnectivity((int*)mesh.getConnectivity(_tetrahedron_4).storage(), - iohelper::TETRA1, mesh.getNbElement(_tetrahedron_4), iohelper::C_MODE); - dumper.setPrefix("paraview/"); - dumper.init(); - dumper.dump(); - - iohelper::DumperParaview dumper_surface; - dumper_surface.setMode(iohelper::TEXT); - - dumper_surface.setPoints(mesh.getNodes().storage(), dim, nb_nodes, "test-surface-extraction_boundary"); - - dumper_surface.setConnectivity((int *)mesh.getConnectivity(_triangle_3).storage(), - iohelper::TRIANGLE1, mesh.getNbElement(_triangle_3), iohelper::C_MODE); - - UInt * surf_id = new UInt[mesh.getNbElement(_triangle_3)]; - - for(Mesh::const_element_group_iterator it(mesh.element_group_begin()); - it != mesh.element_group_end(); ++it) { - const Array & element_ids = it->second->getElements(_triangle_3); - for(UInt i(0); i << element_ids.getSize(); ++i) { - UInt elem_idx = element_ids(i); - surf_id[elem_idx] = atoi((it->first.c_str())); - } - } - -// for (UInt i = 0; i < mesh.getSurfaceID(_triangle_3).getSize(); ++i) -// surf_id[i] = (double)mesh.getSurfaceID(_triangle_3).storage()[i]; - - dumper_surface.addElemDataField("surface_id", surf_id, 1, mesh.getNbElement(_triangle_3)); - dumper_surface.setPrefix("paraview/"); - dumper_surface.init(); - dumper_surface.dump(); - - delete [] surf_id; -#endif //AKANTU_USE_IOHELPER - - finalize(); - return EXIT_SUCCESS; -} diff --git a/test/test_surface_extraction/test_surface_extraction_triangle_3.cc b/test/test_surface_extraction/test_surface_extraction_triangle_3.cc deleted file mode 100644 index 2b7a57d8e..000000000 --- a/test/test_surface_extraction/test_surface_extraction_triangle_3.cc +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file test_surface_extraction_triangle_3.cc - * - * @author Leonardo Snozzi - * @author Marco Vocialta - * - * @date creation: Tue Oct 26 2010 - * @date last modification: Thu Mar 27 2014 - * - * @brief test for surface extractions - * - * @section LICENSE - * - * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) - * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) - * - * Akantu is free software: you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more - * details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Akantu. If not, see . - * - */ - -/* -------------------------------------------------------------------------- */ - -#include "aka_common.hh" -#include "mesh.hh" -#include "mesh_io.hh" -#include "mesh_io_msh.hh" -#include "mesh_utils.hh" -#include "solid_mechanics_model.hh" -#include "material.hh" -#include - -#ifdef AKANTU_USE_IOHELPER -# include "io_helper.hh" - -#endif //AKANTU_USE_IOHELPER - -using namespace akantu; - -int main(int argc, char *argv[]) -{ - int dim = 2; - - akantu::initialize(argc, argv); - - Mesh mesh(dim); - MeshIOMSH mesh_io; - mesh_io.read("squares.msh", mesh); - - MeshUtils::buildFacets(mesh); - mesh.createBoundaryGroupFromGeometry(); - - unsigned int nb_nodes = mesh.getNbNodes(); -#ifdef AKANTU_USE_IOHELPER - iohelper::DumperParaview dumper; - dumper.setMode(iohelper::TEXT); - - dumper.setPoints(mesh.getNodes().storage(), dim, nb_nodes, "test-surface-extraction"); - dumper.setConnectivity((int*)mesh.getConnectivity(_triangle_3).storage(), - iohelper::TRIANGLE1, mesh.getNbElement(_triangle_3), iohelper::C_MODE); - dumper.setPrefix("paraview/"); - dumper.init(); - dumper.dump(); - - iohelper::DumperParaview dumper_surface; - dumper_surface.setMode(iohelper::TEXT); - - dumper_surface.setPoints(mesh.getNodes().storage(), dim, nb_nodes, "test-surface-extraction_boundary"); - - dumper_surface.setConnectivity((int *)mesh.getConnectivity(_segment_2).storage(), - iohelper::LINE1, mesh.getNbElement(_segment_2), iohelper::C_MODE); - UInt * surf_id = new UInt [mesh.getNbElement(_segment_2)]; - - for(Mesh::const_element_group_iterator it(mesh.element_group_begin()); - it != mesh.element_group_end(); ++it) { - const Array & element_ids = it->second->getElements(_segment_2); - for(UInt i(0); i << element_ids.getSize(); ++i) { - UInt elem_idx = element_ids(i); - surf_id[elem_idx] = atoi((it->first.c_str())); - } - } - //for (UInt i = 0; i < mesh.getSurfaceID(_segment_2).getSize(); ++i) - // surf_id[i] = (double)mesh.getSurfaceID(_segment_2).storage()[i]; - - dumper_surface.addElemDataField("surface_id", surf_id, 1, mesh.getNbElement(_segment_2)); - dumper_surface.setPrefix("paraview/"); - dumper_surface.init(); - dumper_surface.dump(); - - delete [] surf_id; -#endif //AKANTU_USE_IOHELPER - - finalize(); - return EXIT_SUCCESS; -} diff --git a/third-party/cmake/iohelper.cmake b/third-party/cmake/iohelper.cmake index a28255874..d4c94cdbf 100644 --- a/third-party/cmake/iohelper.cmake +++ b/third-party/cmake/iohelper.cmake @@ -1,19 +1,20 @@ ExternalProject_Add(IOHelper PREFIX ${PROJECT_BINARY_DIR}/third-party GIT_REPOSITORY ${IOHELPER_GIT} CMAKE_ARGS / CMAKE_CACHE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_CXX_COMPILER:PATH=${CMAKE_CXX_COMPILER} + TIMEOUT 6 ) set_third_party_shared_libirary_name(IOHELPER_LIBRARIES iohelper) set(IOHELPER_INCLUDE_DIR "${PROJECT_BINARY_DIR}/third-party/include" CACHE PATH "IOHelper include directory") mark_as_advanced( IOHELPER_LIBRARIES IOHELPER_INCLUDE_DIR ) package_set_libraries(IOHelper ${IOHELPER_LIBRARIES}) package_set_include_dir(IOHelper ${PROJECT_BINARY_DIR}/third-party/include/iohelper) package_add_extra_dependency(IOHelper IOHelper)