diff --git a/cmake/AkantuTestAndExamples.cmake b/cmake/AkantuTestAndExamples.cmake index 8a6e50b0d..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}) + 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 333cc7f1b..e4b5aaca1 100644 --- a/cmake/Modules/CMakePackagesSystem.cmake +++ b/cmake/Modules/CMakePackagesSystem.cmake @@ -1,1637 +1,1646 @@ #=============================================================================== # @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) - _package_is_deactivated(${_pkg_name} _deactivated) - if(NOT _deactivated AND ${_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() - # deactivate the packages than can already be deactivated - _package_deactivate(${pkg_name}) - #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}) + + string(TOUPPER ${${pkg_name}} _u_package) + _package_set_libraries(${pkg_name} ${${_u_package}_LIBRARIES}) + _package_set_include_dir(${pkg_name} ${${_u_package}_INCLUDE_DIR}) 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_SOURCE_DIR}/tmp/) + 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_SOURCE_DIR}/tmp/${_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_SOURCE_DIR}/tmp/") + 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() - message(SEND_ERROR "Please register them in the good package or clean the sources") + endif() endfunction() diff --git a/extra_packages/extra-materials b/extra_packages/extra-materials index 848d42523..8ec6bad2d 160000 --- a/extra_packages/extra-materials +++ b/extra_packages/extra-materials @@ -1 +1 @@ -Subproject commit 848d42523de0623a3d0d5e6e6ab6f651dd4998ab +Subproject commit 8ec6bad2d21fc4bcfaa805fd33ef6790451dc4e0 diff --git a/packages/blackdynamite.cmake b/packages/blackdynamite.cmake index 91fae2930..5b973c202 100644 --- a/packages/blackdynamite.cmake +++ b/packages/blackdynamite.cmake @@ -1,58 +1,41 @@ #=============================================================================== # @file blackdynamite.cmake # # @author Nicolas Richart # # @date Tue Nov 29 15:16:35 2011 # # @brief package description for BlackDynamite support # # @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 . # #=============================================================================== package_declare(BlackDynamite EXTERNAL DESCRIPTION "Use BlackDynamite library" SYSTEM OFF) -package_use_system(BlackDynamite _use_system) -if(NOT ${_use_system}) - package_get_option_name(BlackDynamite _option_name) +set(_version 1) - if(${_option_name}) - set(BLACKDYNAMITE_URL "svn+ssh://lsmssrv1.epfl.ch/space/repositories/SimulPack/BlackDynamite") - - include(ExternalProject) - - ExternalProject_Add(blackdynamite - PREFIX ${PROJECT_BINARY_DIR}/third-party - SVN_REPOSITORY ${BLACKDYNAMITE_URL} - CMAKE_ARGS / - CMAKE_CACHE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCMAKE_CXX_COMPILER:PATH=${CMAKE_CXX_COMPILER} - BUILD_COMMAND make - INSTALL_COMMAND make install - ) - - set_third_party_shared_libirary_name(BLACKDYNAMITE_LIBRARIES blackdynamite) - package_set_libraries(BlackDynamite ${BLACKDYNAMITE_LIBRARIES}) - package_set_include_dir(BlackDynamite ${PROJECT_BINARY_DIR}/third-party/include/blackdynamite) - - package_add_extra_dependency(BlackDynamite blackdynamite) - endif() -endif() +package_add_third_party_script_variable(BlackDynamite + BLACKDYNAMITE_VERSION "${_version}") +package_add_third_party_script_variable(BlackDynamite + BLACKDYNAMITE_GIT "svn+ssh://lsmssrv1.epfl.ch/space/repositories/SimulPack/BlackDynamite") +package_add_third_party_script_variable(BlackDynamite + BLACKDYNAMITE_ARCHIVE "blackdynamite-${_version}.tar.gz") \ No newline at end of file diff --git a/packages/cgal.cmake b/packages/cgal.cmake index 1c9a17ea0..6053afb9c 100644 --- a/packages/cgal.cmake +++ b/packages/cgal.cmake @@ -1,52 +1,69 @@ #=============================================================================== # @file cgal.cmake # # @author Lucas Frérot # # @date creation: Thu Feb 19 2015 # @date last modification: Mon Mar 2 2015 # # @brief package description for CGAL # # @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 . # #=============================================================================== package_declare(CGAL EXTERNAL DESCRIPTION "Add CGAL support in akantu" COMPILE_FLAGS "-frounding-math" BOOST_COMPONENTS system ) package_declare_sources(CGAL + geometry/mesh_geom_common.hh + geometry/mesh_geom_abstract.hh geometry/mesh_geom_abstract.cc + geometry/mesh_geom_factory.hh geometry/mesh_geom_factory_tmpl.hh - geometry/mesh_geom_container.hh - geometry/mesh_geom_container.cc + + geometry/mesh_geom_intersector.hh + geometry/mesh_geom_intersector_tmpl.hh + + geometry/mesh_segment_intersector.hh + geometry/mesh_segment_intersector_tmpl.hh geometry/tree_type_helper.hh geometry/geom_helper_functions.hh geometry/aabb_primitives/triangle.hh + geometry/aabb_primitives/line_arc.hh geometry/aabb_primitives/tetrahedron.hh geometry/aabb_primitives/aabb_primitive.hh + geometry/aabb_primitives/aabb_primitive.cc + + geometry/mesh_geom_spherical_traits.hh + ) + +package_declare_documentation(CGAL + "This package allows the use of CGAL's geometry algorithms in Akantu. Note that it needs a version of CGAL $\\geq$ 4.5 and needs activation of boost's system component." + "" + "CGAL checks with an assertion that the compilation flag \\shellcode{-frounding-math} is activated, which forbids the use of Valgrind on any code compilated with the package." ) diff --git a/packages/embedded.cmake b/packages/embedded.cmake index aeb711a3c..df0eeb3ae 100644 --- a/packages/embedded.cmake +++ b/packages/embedded.cmake @@ -1,51 +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.hh - model/solid_mechanics/embedded_interface.cc + 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/packages/iohelper.cmake b/packages/iohelper.cmake index 7d57685cd..e38c2e638 100644 --- a/packages/iohelper.cmake +++ b/packages/iohelper.cmake @@ -1,68 +1,71 @@ #=============================================================================== # @file 90_iohelper.cmake # # @author Nicolas Richart # # @date creation: Tue Nov 29 2011 # @date last modification: Tue Sep 02 2014 # # @brief package description for iohelper # # @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(IOHelper EXTERNAL DESCRIPTION "Add IOHelper support in akantu" SYSTEM OFF third-party/cmake/iohelper.cmake DEFAULT ON) +set(_version "master") package_add_third_party_script_variable(IOHelper - IOHELPER_VERSION "1.1") + IOHELPER_VERSION ${_version}) package_add_third_party_script_variable(IOHelper IOHELPER_GIT "https://git.epfl.ch/repo/iohelper.git") +package_add_third_party_script_variable(Scotch + IOHELPER_ARCHIVE "iohelper_${_version}.tar.gz") package_declare_sources(IOHelper io/dumper/dumpable_iohelper.hh io/dumper/dumper_iohelper.hh io/dumper/dumper_iohelper.cc io/dumper/dumper_paraview.hh io/dumper/dumper_text.cc io/dumper/dumper_text.hh io/dumper/dumper_paraview.cc io/dumper/dumper_homogenizing_field.hh io/dumper/dumper_type_traits.hh io/dumper/dumper_compute.hh io/dumper/dumper_nodal_field.hh io/dumper/dumper_quadrature_points_field.hh io/dumper/dumper_variable.hh io/dumper/dumper_iterator_helper.hh io/dumper/dumper_connectivity_field.hh io/dumper/dumper_padding_helper.hh io/dumper/dumper_elemental_field.hh io/dumper/dumper_element_iterator.hh io/dumper/dumper_material_internal_field.hh io/dumper/dumper_generic_elemental_field.hh io/dumper/dumper_generic_elemental_field_tmpl.hh ) package_declare_documentation(IOHelper "This package activates the IOHelper facilities withing Akantu. This is mandatory if you want to be able to output Paraview files" "as well as any Dumper within Akantu." ) diff --git a/packages/scotch.cmake b/packages/scotch.cmake index ba0bf44ab..ded1582cd 100644 --- a/packages/scotch.cmake +++ b/packages/scotch.cmake @@ -1,74 +1,76 @@ #=============================================================================== # @file 90_scotch.cmake # # @author Nicolas Richart # # @date creation: Mon Nov 21 2011 # @date last modification: Thu Jul 10 2014 # # @brief package description for scotch # # @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(Scotch EXTERNAL DESCRIPTION "Add Scotch support in akantu" SYSTEM ON third-party/cmake/scotch.cmake) package_declare_sources(Scotch mesh_utils/mesh_partition/mesh_partition_scotch.cc ) package_add_third_party_script_variable(Scotch SCOTCH_VERSION "5.1.12b") package_add_third_party_script_variable(Scotch SCOTCH_ARCHIVE_HASH "MD5=e13b49be804755470b159d7052764dc0") +package_add_third_party_script_variable(Scotch + SCOTCH_ARCHIVE "scotch_${SCOTCH_VERSION}_esmumps.tar.gz") package_add_third_party_script_variable(Scotch SCOTCH_URL "https://gforge.inria.fr/frs/download.php/28978/scotch_${SCOTCH_VERSION}_esmumps.tar.gz") package_declare_documentation(Scotch "This package enables the use the \\href{http://www.labri.fr/perso/pelegrin/scotch/}{Scotch}" "library in order to perform a graph partitioning leading to the domain" "decomposition used within \\akantu" "" "Under Ubuntu (14.04 LTS) the installation can be performed using the commands:" "\\begin{command}" " > sudo apt-get install libscotch-dev" "\\end{command}" "" "If you activate the advanced option AKANTU\\_USE\\_THIRD\\_PARTY\\_SCOTCH" "the make system of akantu can automatically compile Scotch." "" "If the automated download fails due to a SSL access not supported by your" "version of CMake please download the file" "\\href{${SCOTCH_ARCHIVE}}{scotch\\_${SCOTCH_VERSION}\\_esmumps.tar.gz}" "and then place it in the directory \\shellcode{/third-party}" ) # if(SCOTCH_INCLUDE_DIR) # file(STRINGS ${SCOTCH_INCLUDE_DIR}/scotch.h SCOTCH_INCLUDE_CONTENT) # string(REGEX MATCH "_cplusplus" _match ${SCOTCH_INCLUDE_CONTENT}) # if(_match) # set(AKANTU_SCOTCH_NO_EXTERN ON) # list(APPEND AKANTU_DEFINITIONS AKANTU_SCOTCH_NO_EXTERN) # else() # set(AKANTU_SCOTCH_NO_EXTERN OFF) # endif() # endif() 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_array.hh b/src/common/aka_array.hh index 5d5fce77e..72237a15e 100644 --- a/src/common/aka_array.hh +++ b/src/common/aka_array.hh @@ -1,375 +1,371 @@ /** * @file aka_array.hh * * @author Till Junge * @author Nicolas Richart * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Jun 24 2014 * * @brief Array container for Akantu * This container differs from the std::vector from the fact it as 2 dimensions * a main dimension and the size stored per entries * * @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_VECTOR_HH__ #define __AKANTU_VECTOR_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #include -//#include - #include - /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /// class that afford to store vectors in static memory class ArrayBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ArrayBase(const ID & id = ""); virtual ~ArrayBase(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// get the amount of space allocated in bytes inline UInt getMemorySize() const; /// set the size to zero without freeing the allocated space inline void empty(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// Get the real size allocated in memory AKANTU_GET_MACRO(AllocatedSize, allocated_size, UInt); /// Get the Size of the Array AKANTU_GET_MACRO(Size, size, UInt); /// Get the number of components AKANTU_GET_MACRO(NbComponent, nb_component, UInt); /// Get the name of th array AKANTU_GET_MACRO(ID, id, const ID &); /// Set the name of th array AKANTU_SET_MACRO(ID, id, const ID &); // AKANTU_GET_MACRO(Tag, tag, const std::string &); // AKANTU_SET_MACRO(Tag, tag, const std::string &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the vector ID id; /// the size allocated UInt allocated_size; /// the size used UInt size; /// number of components UInt nb_component; /// size of the stored type UInt size_of_type; // /// User defined tag // std::string tag; }; /* -------------------------------------------------------------------------- */ -/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template class Array : public ArrayBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef T value_type; typedef value_type & reference; typedef value_type * pointer_type; typedef const value_type & const_reference; /// Allocation of a new vector inline Array(UInt size = 0, UInt nb_component = 1, const ID & id = ""); /// Allocation of a new vector with a default value Array(UInt size, UInt nb_component, const value_type def_values[], const ID & id = ""); /// Allocation of a new vector with a default value Array(UInt size, UInt nb_component, const_reference value, const ID & id = ""); /// Copy constructor (deep copy if deep=true) Array(const Array& vect, bool deep = true, const ID & id = ""); #ifndef SWIG /// Copy constructor (deep copy) Array(const std::vector & vect); #endif virtual inline ~Array(); Array & operator=(const Array & a) { /// this is to let STL allocate and copy arrays in the case of std::vector::resize AKANTU_DEBUG_ASSERT(this->size == 0,"Cannot copy akantu::Array"); return const_cast(a); } /* ------------------------------------------------------------------------ */ /* Iterator */ /* ------------------------------------------------------------------------ */ /// \todo protected: does not compile with intel check why public: template ::value > class iterator_internal; public: /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ template class const_iterator; template class iterator; /* ------------------------------------------------------------------------ */ /// iterator for Array of nb_component = 1 typedef iterator< T > scalar_iterator; /// const_iterator for Array of nb_component = 1 typedef const_iterator< T > const_scalar_iterator; /// iterator rerturning Vectors of size n on entries of Array with nb_component = n typedef iterator< Vector > vector_iterator; /// const_iterator rerturning Vectors of n size on entries of Array with nb_component = n typedef const_iterator< Vector > const_vector_iterator; /// iterator rerturning Matrices of size (m, n) on entries of Array with nb_component = m*n typedef iterator< Matrix > matrix_iterator; /// const iterator rerturning Matrices of size (m, n) on entries of Array with nb_component = m*n typedef const_iterator< Matrix > const_matrix_iterator; /* ------------------------------------------------------------------------ */ /// Get an iterator that behaves like a pointer T * to the first entry inline iterator begin(); /// Get an iterator that behaves like a pointer T * to the end of the Array inline iterator end(); /// Get a const_iterator to the beginging of an Array of scalar inline const_iterator begin() const; /// Get a const_iterator to the end of an Array of scalar inline const_iterator end() const; /* ------------------------------------------------------------------------ */ /// Get a vector_iterator on the begining of the Array inline vector_iterator begin(UInt n); /// Get a vector_iterator on the end of the Array inline vector_iterator end(UInt n); /// Get a vector_iterator on the begining of the Array inline const_vector_iterator begin(UInt n) const; /// Get a vector_iterator on the end of the Array inline const_vector_iterator end(UInt n) const; /// Get a vector_iterator on the begining of the Array considered of shape (new_size, n) inline vector_iterator begin_reinterpret(UInt n, UInt new_size); /// Get a vector_iterator on the end of the Array considered of shape (new_size, n) inline vector_iterator end_reinterpret(UInt n, UInt new_size); /// Get a const_vector_iterator on the begining of the Array considered of shape (new_size, n) inline const_vector_iterator begin_reinterpret(UInt n, UInt new_size) const; /// Get a const_vector_iterator on the end of the Array considered of shape (new_size, n) inline const_vector_iterator end_reinterpret(UInt n, UInt new_size) const; /* ------------------------------------------------------------------------ */ /// Get a matrix_iterator on the begining of the Array (Matrices of size (m, n)) inline matrix_iterator begin(UInt m, UInt n); /// Get a matrix_iterator on the end of the Array (Matrices of size (m, n)) inline matrix_iterator end(UInt m, UInt n); /// Get a const_matrix_iterator on the begining of the Array (Matrices of size (m, n)) inline const_matrix_iterator begin(UInt m, UInt n) const; /// Get a const_matrix_iterator on the end of the Array (Matrices of size (m, n)) inline const_matrix_iterator end(UInt m, UInt n) const; /// Get a matrix_iterator on the begining of the Array considered of shape (new_size, m*n) inline matrix_iterator begin_reinterpret(UInt m, UInt n, UInt size); /// Get a matrix_iterator on the end of the Array considered of shape (new_size, m*n) inline matrix_iterator end_reinterpret(UInt m, UInt n, UInt size); /// Get a const_matrix_iterator on the begining of the Array considered of shape (new_size, m*n) inline const_matrix_iterator begin_reinterpret(UInt m, UInt n, UInt size) const; /// Get a const_matrix_iterator on the end of the Array considered of shape (new_size, m*n) inline const_matrix_iterator end_reinterpret(UInt m, UInt n, UInt size) const; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// append a tuple of size nb_component containing value inline void push_back(const_reference value); /// append a vector inline void push_back(const value_type new_elem[]); /// append a Vector or a Matrix template class C> inline void push_back(const C & new_elem); /// append the value of the iterator template inline void push_back(const iterator & it); /// erase the value at position i inline void erase(UInt i); /// ask Nico, clarify template inline iterator erase(const iterator & it); /// change the size of the Array void resize(UInt size); /// change the number of components by interlacing data void extendComponentsInterlaced(UInt multiplicator, UInt stride); /// search elem in the vector, return the position of the first occurrence or -1 if not found Int find(const_reference elem) const;\ /// @see Array::find(const_reference elem) const Int find(T elem[]) const; /// set all entries of the array to 0 inline void clear() { std::fill_n(values, size*nb_component, T()); } /// set all entries of the array to the value t /// @param t value to fill the array with inline void set(T t) { std::fill_n(values, size*nb_component, t); } /// set all tuples of the array to a given vector or matrix /// @param vm Matrix or Vector to fill the array with template class C> inline void set(const C & vm); /// copy another Array in the current Array, the no_sanity_check allows you to /// force the copy in cases where you know what you do with two non matching /// Arrays in terms of n void copy(const Array & other, bool no_sanity_check = false); /// give the address of the memory allocated for this vector T * storage() const { return values; }; /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; protected: /// perform the allocation for the constructors void allocate(UInt size, UInt nb_component = 1); /// resize without initializing the memory void resizeUnitialized(UInt new_size); /* ------------------------------------------------------------------------ */ /* Operators */ /* ------------------------------------------------------------------------ */ public: /// substraction entry-wise Array & operator-=(const Array & other); /// addition entry-wise Array & operator+=(const Array & other); /// multiply evry entry by alpha Array & operator*=(const T & alpha); /// check if the array are identical entry-wise bool operator==(const Array & other) const; /// @see Array::operator==(const Array & other) const bool operator!=(const Array & other) const; /// return a reference to the j-th entry of the i-th tuple inline reference operator()(UInt i, UInt j = 0); /// return a const reference to the j-th entry of the i-th tuple inline const_reference operator()(UInt i, UInt j = 0) const; /// return a reference to the ith component of the 1D array inline reference operator[](UInt i); /// return a const reference to the ith component of the 1D array inline const_reference operator[](UInt i) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the number of tuples contained in the array UInt getSize() const{ return this->size; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// array of values T * values; // /!\ very dangerous }; __END_AKANTU__ #include "aka_types.hh" __BEGIN_AKANTU__ #include "aka_array_tmpl.hh" /* -------------------------------------------------------------------------- */ /* Inline Functions Array */ /* -------------------------------------------------------------------------- */ template inline std::ostream & operator<<(std::ostream & stream, const Array & _this) { _this.printself(stream); return stream; } /* -------------------------------------------------------------------------- */ /* Inline Functions ArrayBase */ /* -------------------------------------------------------------------------- */ inline std::ostream & operator<<(std::ostream & stream, const ArrayBase & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_VECTOR_HH__ */ diff --git a/src/common/aka_common.hh b/src/common/aka_common.hh index 3bfae0690..b9bc5168e 100644 --- a/src/common/aka_common.hh +++ b/src/common/aka_common.hh @@ -1,443 +1,503 @@ /** * @file aka_common.hh * * @author Nicolas Richart * * @date creation: Mon Jun 14 2010 * @date last modification: Mon Sep 15 2014 * * @brief common type descriptions for akantu * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * * @section DESCRIPTION * * All common things to be included in the projects files * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COMMON_HH__ #define __AKANTU_COMMON_HH__ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #define __BEGIN_AKANTU__ namespace akantu { #define __END_AKANTU__ }; /* -------------------------------------------------------------------------- */ #define __BEGIN_AKANTU_DUMPER__ namespace dumper { #define __END_AKANTU_DUMPER__ } /* -------------------------------------------------------------------------- */ #if defined(WIN32) # define __attribute__(x) #endif /* -------------------------------------------------------------------------- */ #include "aka_config.hh" #include "aka_error.hh" #include "aka_safe_enum.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Common types */ /* -------------------------------------------------------------------------- */ typedef double Real; typedef unsigned int UInt; typedef unsigned long long UInt64; typedef signed int Int; typedef std::string ID; static const Real UINT_INIT_VALUE = 0; #ifdef AKANTU_NDEBUG static const Real REAL_INIT_VALUE = 0; #else static const Real REAL_INIT_VALUE = std::numeric_limits::quiet_NaN(); #endif /* -------------------------------------------------------------------------- */ /* Memory types */ /* -------------------------------------------------------------------------- */ typedef UInt MemoryID; typedef std::string Surface; typedef std::pair SurfacePair; typedef std::list< SurfacePair > SurfacePairList; /* -------------------------------------------------------------------------- */ extern const UInt _all_dimensions; + /* -------------------------------------------------------------------------- */ /* Mesh/FEM/Model types */ /* -------------------------------------------------------------------------- */ __END_AKANTU__ +#define AKANTU_ALL_ELEMENT_TYPE \ + AKANTU_ek_regular_ELEMENT_TYPE \ + AKANTU_ek_cohesive_ELEMENT_TYPE \ + AKANTU_ek_structural_ELEMENT_TYPE \ + AKANTU_ek_igfem_ELEMENT_TYPE + +#define AKANTU_NOT_STRUCTURAL_ELEMENT_TYPE \ + AKANTU_ek_regular_ELEMENT_TYPE \ + AKANTU_ek_cohesive_ELEMENT_TYPE \ + AKANTU_ek_igfem_ELEMENT_TYPE + +/// @enum ElementType type of elements +enum ElementType { + _not_defined, + _point_1, + _segment_2, ///< first order segment + _segment_3, ///< second order segment + _triangle_3, ///< first order triangle + _triangle_6, ///< second order triangle + _tetrahedron_4, ///< first order tetrahedron + _tetrahedron_10, ///< second order tetrahedron + _quadrangle_4, ///< first order quadrangle + _quadrangle_8, ///< second order quadrangle + _hexahedron_8, ///< first order hexahedron + _hexahedron_20, ///< second order hexahedron + _pentahedron_6, ///< first order pentahedron + _pentahedron_15, ///< second order pentahedron + +#if defined (AKANTU_STRUCTURAL_MECHANICS) + _bernoulli_beam_2, ///< Bernoulli beam 2D + _bernoulli_beam_3, ///< Bernoulli beam 3D + _kirchhoff_shell, ///< Kirchhoff shell +#endif + +#if defined(AKANTU_COHESIVE_ELEMENT) + _cohesive_2d_4, ///< first order 2D cohesive + _cohesive_2d_6, ///< second order 2D cohesive + _cohesive_1d_2, ///< first order 1D cohesive + _cohesive_3d_6, ///< first order 3D cohesive + _cohesive_3d_12, ///< second order 3D cohesive +#endif +#if defined(AKANTU_IGFEM) + _igfem_triangle_3, ///< first order triangle for IGFEM +#endif + _max_element_type +}; + + + +//! standard output stream operator for ElementType +inline std::ostream & operator <<(std::ostream & stream, ElementType type); + +//! standard input stream operator for ElementType +inline std::istream & operator >>(std::istream & stream, ElementType & type); + + + +>>>>>>> aa23fede75a27f42e38d9c4ed84e1c67fa93931b + #include "aka_element_classes_info.hh" __BEGIN_AKANTU__ /// small help to use names for directions enum SpacialDirection { _x = 0, _y = 1, _z = 2 }; /// enum MeshIOType type of mesh reader/writer enum MeshIOType { _miot_auto, ///< Auto guess of the reader to use based on the extension _miot_gmsh, ///< Gmsh files _miot_gmsh_struct, ///< Gsmh reader with reintpretation of elements has structures elements _miot_diana, ///< TNO Diana mesh format _miot_abaqus ///< Abaqus mesh format }; /// enum AnalysisMethod type of solving method used to solve the equation of motion enum AnalysisMethod { _static, _implicit_dynamic, _explicit_lumped_mass, _explicit_lumped_capacity, _explicit_consistent_mass }; //! enum ContactResolutionMethod types of solving for the contact enum ContactResolutionMethod { _penalty, _lagrangian, _augmented_lagrangian, _nitsche, _mortar }; //! enum ContactImplementationMethod types for different contact implementations enum ContactImplementationMethod { _none, _uzawa, _generalized_newton }; /// enum SolveConvergenceMethod different resolution algorithms enum SolveConvergenceMethod { _scm_newton_raphson_tangent, ///< Newton-Raphson with tangent matrix _scm_newton_raphson_tangent_modified, ///< Newton-Raphson with constant tangent matrix _scm_newton_raphson_tangent_not_computed ///< Newton-Raphson with constant tangent matrix (user has to assemble it) }; /// enum SolveConvergenceCriteria different convergence criteria enum SolveConvergenceCriteria { _scc_residual, ///< Use residual to test the convergence _scc_increment, ///< Use increment to test the convergence _scc_residual_mass_wgh ///< Use residual weighted by inv. nodal mass to testb }; /// enum CohesiveMethod type of insertion of cohesive elements enum CohesiveMethod { _intrinsic, _extrinsic }; /// myfunction(double * position, double * stress/force, double * normal, unsigned int material_id) typedef void (*BoundaryFunction)(double *,double *, double*, unsigned int); /// @enum BoundaryFunctionType type of function passed for boundary conditions enum BoundaryFunctionType { _bft_stress, _bft_traction, _bft_traction_local }; /// @enum SparseMatrixType type of sparse matrix used enum SparseMatrixType { _unsymmetric, _symmetric }; /* -------------------------------------------------------------------------- */ /* Contact */ /* -------------------------------------------------------------------------- */ typedef ID ContactID; typedef ID ContactSearchID; typedef ID ContactNeighborStructureID; enum ContactType { _ct_not_defined = 0, _ct_2d_expli = 1, _ct_3d_expli = 2, _ct_rigid = 3 }; enum ContactSearchType { _cst_not_defined = 0, _cst_2d_expli = 1, _cst_expli = 2 }; enum ContactNeighborStructureType { _cnst_not_defined = 0, _cnst_regular_grid = 1, _cnst_2d_grid = 2 }; /* -------------------------------------------------------------------------- */ /* Friction */ /* -------------------------------------------------------------------------- */ typedef ID FrictionID; /* -------------------------------------------------------------------------- */ /* Ghosts handling */ /* -------------------------------------------------------------------------- */ typedef ID SynchronizerID; /// @enum CommunicatorType type of communication method to use enum CommunicatorType { _communicator_mpi, _communicator_dummy }; /// @enum SynchronizationTag type of synchronizations enum SynchronizationTag { //--- SolidMechanicsModel tags --- _gst_smm_mass, //< synchronization of the SolidMechanicsModel.mass _gst_smm_for_gradu, //< synchronization of the SolidMechanicsModel.displacement _gst_smm_boundary, //< synchronization of the boundary, forces, velocities and displacement _gst_smm_uv, //< synchronization of the nodal velocities and displacement _gst_smm_res, //< synchronization of the nodal residual _gst_smm_init_mat, //< synchronization of the data to initialize materials _gst_smm_stress, //< synchronization of the stresses to compute the internal forces _gst_smmc_facets, //< synchronization of facet data to setup facet synch _gst_smmc_facets_conn, //< synchronization of facet global connectivity _gst_smmc_facets_stress, //< synchronization of facets' stress to setup facet synch _gst_smmc_damage, //< synchronization of damage //--- CohesiveElementInserter tags --- _gst_ce_inserter, //< synchronization of global nodes id of newly inserted cohesive elements //--- GroupManager tags --- _gst_gm_clusters, //< synchronization of clusters //--- HeatTransfer tags --- _gst_htm_capacity, //< synchronization of the nodal heat capacity _gst_htm_temperature, //< synchronization of the nodal temperature _gst_htm_gradient_temperature, //< synchronization of the element gradient temperature //--- LevelSet tags --- /// synchronization of the nodal level set value phi _gst_htm_phi, /// synchronization of the element gradient phi _gst_htm_gradient_phi, //--- Material non local --- _gst_mnl_for_average, //< synchronization of data to average in non local material _gst_mnl_weight, //< synchronization of data for the weight computations //--- General tags --- _gst_test, //< Test tag _gst_user_1, //< tag for user simulations _gst_user_2, //< tag for user simulations _gst_material_id, //< synchronization of the material ids _gst_for_dump, //< everything that needs to be synch before dump //--- Contact & Friction --- _gst_cf_nodal, //< synchronization of disp, velo, and current position _gst_cf_incr, //< synchronization of increment ///--- Solver tags --- _gst_solver_solution //< synchronization of the solution obained with the PETSc solver }; /// standard output stream operator for SynchronizationTag inline std::ostream & operator <<(std::ostream & stream, SynchronizationTag type); /// @enum GhostType type of ghost enum GhostType { _not_ghost, _ghost, _casper // not used but a real cute ghost }; /* -------------------------------------------------------------------------- */ struct GhostType_def { typedef GhostType type; static const type _begin_ = _not_ghost; static const type _end_ = _casper; }; typedef safe_enum ghost_type_t; /// standard output stream operator for GhostType inline std::ostream & operator <<(std::ostream & stream, GhostType type); /// @enum SynchronizerOperation reduce operation that the synchronizer can perform enum SynchronizerOperation { _so_sum, _so_min, _so_max, _so_null }; /* -------------------------------------------------------------------------- */ /* Global defines */ /* -------------------------------------------------------------------------- */ #define AKANTU_MIN_ALLOCATION 2000 #define AKANTU_INDENT " " #define AKANTU_INCLUDE_INLINE_IMPL /* -------------------------------------------------------------------------- */ // int 2 type construct template struct Int2Type { enum { result = d }; }; // type 2 type construct template class Type2Type { typedef T OriginalType; }; /* -------------------------------------------------------------------------- */ template struct is_scalar { enum{ value = false }; }; #define AKANTU_SPECIFY_IS_SCALAR(type) \ template<> \ struct is_scalar { \ enum { value = true }; \ } AKANTU_SPECIFY_IS_SCALAR(Real); AKANTU_SPECIFY_IS_SCALAR(UInt); AKANTU_SPECIFY_IS_SCALAR(Int); AKANTU_SPECIFY_IS_SCALAR(bool); template < typename T1, typename T2 > struct is_same { enum { value = false }; // is_same represents a bool. }; template < typename T > struct is_same { enum { value = true }; }; /* -------------------------------------------------------------------------- */ #define AKANTU_SET_MACRO(name, variable, type) \ inline void set##name (type variable) { \ this->variable = variable; \ } #define AKANTU_GET_MACRO(name, variable, type) \ inline type get##name () const { \ return variable; \ } #define AKANTU_GET_MACRO_NOT_CONST(name, variable, type) \ inline type get##name () { \ return variable; \ } #define AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, \ support, con) \ inline con Array & \ get##name (const support & el_type, \ const GhostType & ghost_type = _not_ghost) con { \ return variable(el_type, ghost_type); \ } #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType,) #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType, const) #define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType,) #define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE_CONST(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType, const) /* -------------------------------------------------------------------------- */ /// initialize the static part of akantu void initialize(int & argc, char ** & argv); /// initialize the static part of akantu and read the global input_file void initialize(const std::string & input_file, int & argc, char ** & argv); /* -------------------------------------------------------------------------- */ /// finilize correctly akantu and clean the memory void finalize (); /* -------------------------------------------------------------------------- */ /* * For intel compiler annoying remark */ #if defined(__INTEL_COMPILER) /// remark #981: operands are evaluated in unspecified order #pragma warning ( disable : 981 ) /// remark #383: value copied to temporary, reference to temporary used #pragma warning ( disable : 383 ) #endif //defined(__INTEL_COMPILER) /* -------------------------------------------------------------------------- */ /* string manipulation */ /* -------------------------------------------------------------------------- */ inline std::string to_lower(const std::string & str); /* -------------------------------------------------------------------------- */ inline std::string trim(const std::string & to_trim); /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /// give a string representation of the a human readable size in bit template std::string printMemorySize(UInt size); /* -------------------------------------------------------------------------- */ __END_AKANTU__ #include "aka_fwd.hh" __BEGIN_AKANTU__ /// get access to the internal argument parser cppargparse::ArgumentParser & getStaticArgumentParser(); /// get access to the internal input file parser Parser & getStaticParser(); /// get access to the user part of the internal input file parser const ParserSection & getUserParser(); __END_AKANTU__ #include "aka_common_inline_impl.cc" #endif /* __AKANTU_COMMON_HH__ */ diff --git a/src/common/aka_common_inline_impl.cc b/src/common/aka_common_inline_impl.cc index 95b29f74f..41f096007 100644 --- a/src/common/aka_common_inline_impl.cc +++ b/src/common/aka_common_inline_impl.cc @@ -1,178 +1,177 @@ /** * @file aka_common_inline_impl.cc * * @author Guillaume Anciaux * @author Nicolas Richart * * @date creation: Thu Dec 01 2011 * @date last modification: Wed Jul 23 2014 * * @brief inline implementations of common akantu type descriptions * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * * @section DESCRIPTION * * All common things to be included in the projects files * */ #include #include - +#include #include __BEGIN_AKANTU__ - /* -------------------------------------------------------------------------- */ /// standard output stream operator for GhostType inline std::ostream & operator <<(std::ostream & stream, GhostType type) { switch(type) { case _not_ghost : stream << "not_ghost"; break; case _ghost : stream << "ghost" ; break; case _casper : stream << "Casper the friendly ghost"; break; } return stream; } /* -------------------------------------------------------------------------- */ /// standard output stream operator for SynchronizationTag inline std::ostream & operator <<(std::ostream & stream, SynchronizationTag type) { switch(type) { case _gst_smm_mass : stream << "_gst_smm_mass" ; break; case _gst_smm_for_gradu : stream << "_gst_smm_for_gradu" ; break; case _gst_smm_boundary : stream << "_gst_smm_boundary" ; break; case _gst_smm_uv : stream << "_gst_smm_uv" ; break; case _gst_smm_res : stream << "_gst_smm_res" ; break; case _gst_smm_init_mat : stream << "_gst_smm_init_mat" ; break; case _gst_smm_stress : stream << "_gst_smm_stress" ; break; case _gst_smmc_facets : stream << "_gst_smmc_facets" ; break; case _gst_smmc_facets_conn : stream << "_gst_smmc_facets_conn" ; break; case _gst_smmc_facets_stress : stream << "_gst_smmc_facets_stress" ; break; case _gst_smmc_damage : stream << "_gst_smmc_damage" ; break; case _gst_ce_inserter : stream << "_gst_ce_inserter" ; break; case _gst_gm_clusters : stream << "_gst_gm_clusters" ; break; case _gst_htm_capacity : stream << "_gst_htm_capacity" ; break; case _gst_htm_temperature : stream << "_gst_htm_temperature" ; break; case _gst_htm_gradient_temperature : stream << "_gst_htm_gradient_temperature"; break; case _gst_htm_phi : stream << "_gst_htm_phi" ; break; case _gst_htm_gradient_phi : stream << "_gst_htm_gradient_phi" ; break; case _gst_mnl_for_average : stream << "_gst_mnl_for_average" ; break; case _gst_mnl_weight : stream << "_gst_mnl_weight" ; break; case _gst_test : stream << "_gst_test" ; break; case _gst_user_1 : stream << "_gst_user_1" ; break; case _gst_user_2 : stream << "_gst_user_2" ; break; case _gst_material_id : stream << "_gst_material_id" ; break; case _gst_for_dump : stream << "_gst_for_dump" ; break; case _gst_cf_nodal : stream << "_gst_cf_nodal" ; break; case _gst_cf_incr : stream << "_gst_cf_incr" ; break; case _gst_solver_solution : stream << "_gst_solver_solution" ; break; } return stream; } /* -------------------------------------------------------------------------- */ /// standard output stream operator for SolveConvergenceCriteria inline std::ostream & operator <<(std::ostream & stream, SolveConvergenceCriteria criteria) { switch(criteria) { case _scc_residual : stream << "_scc_residual" ; break; case _scc_increment: stream << "_scc_increment"; break; case _scc_residual_mass_wgh: stream << "_scc_residual_mass_wgh"; break; } return stream; } /* -------------------------------------------------------------------------- */ inline std::string to_lower(const std::string & str) { std::string lstr = str; std::transform(lstr.begin(), lstr.end(), lstr.begin(), (int(*)(int))tolower); return lstr; } /* -------------------------------------------------------------------------- */ inline std::string trim(const std::string & to_trim) { std::string trimed = to_trim; //left trim trimed.erase(trimed.begin(), std::find_if(trimed.begin(), trimed.end(), std::not1(std::ptr_fun(isspace)))); // right trim trimed.erase(std::find_if(trimed.rbegin(), trimed.rend(), std::not1(std::ptr_fun(isspace))).base(), trimed.end()); return trimed; } __END_AKANTU__ #include __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template std::string printMemorySize(UInt size) { Real real_size = size * sizeof(T); UInt mult = (std::log(real_size) / std::log(2)) / 10; std::stringstream sstr; real_size /= Real(1 << (10 * mult)); sstr << std::setprecision(2) << std::fixed << real_size; std::string size_prefix; switch(mult) { case 0: sstr << ""; break; case 1: sstr << "Ki"; break; case 2: sstr << "Mi"; break; case 3: sstr << "Gi"; break; // I started on this type of machines // (32bit computers) (Nicolas) case 4: sstr << "Ti"; break; case 5: sstr << "Pi"; break; case 6: sstr << "Ei"; break; // theoritical limit of RAM of the current // computers in 2014 (64bit computers) (Nicolas) case 7: sstr << "Zi"; break; case 8: sstr << "Yi"; break; default: AKANTU_DEBUG_ERROR("The programmer in 2014 didn't thought so far (even wikipedia does not go further)." << " You have at least 1024 times more than a yobibit of RAM!!!" << " Just add the prefix corresponding in this switch case."); } sstr << "Byte"; return sstr.str(); } __END_AKANTU__ 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_math_tmpl.hh b/src/common/aka_math_tmpl.hh index 034dc0565..46d77ee92 100644 --- a/src/common/aka_math_tmpl.hh +++ b/src/common/aka_math_tmpl.hh @@ -1,774 +1,774 @@ /** * @file aka_math_tmpl.hh * * @author Leonardo Snozzi * @author Ramin Aghababaei * @author Peter Spijker * @author Alejandro M. Aragón * @author Nicolas Richart * @author Daniel Pino Muñoz * @author Guillaume Anciaux * @author Mathilde Radiguet * @author Marco Vocialta * @author David Simon Kammer * * @date creation: Wed Aug 04 2010 * @date last modification: Tue Sep 16 2014 * * @brief Implementation of the inline functions of the math toolkit * * @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 . * */ __END_AKANTU__ #include #include #include #include "aka_blas_lapack.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ inline void Math::matrix_vector(UInt im, UInt in, Real * A, Real * x, Real * y, Real alpha) { #ifdef AKANTU_USE_BLAS /// y = alpha*op(A)*x + beta*y char tran_A = 'N'; int incx = 1; int incy = 1; double beta = 0.; int m = im; int n = in; aka_gemv(&tran_A, &m, &n, &alpha, A, &m, x, &incx, &beta, y, &incy); #else memset(y, 0, im*sizeof(Real)); for (UInt i = 0; i < im; ++i) { for (UInt j = 0; j < in; ++j) { y[i] += A[i + j*im] * x[j]; } y[i] *= alpha; } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_vector(UInt im, UInt in, Real * A, Real * x, Real * y, Real alpha) { #ifdef AKANTU_USE_BLAS /// y = alpha*op(A)*x + beta*y char tran_A = 'T'; int incx = 1; int incy = 1; double beta = 0.; int m = im; int n = in; aka_gemv(&tran_A, &m, &n, &alpha, A, &m, x, &incx, &beta, y, &incy); #else memset(y, 0, in*sizeof(Real)); for (UInt i = 0; i < im; ++i) { for (UInt j = 0; j < in; ++j) { y[j] += A[j * im + i] * x[i]; } y[i] *= alpha; } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrix_matrix(UInt im, UInt in, UInt ik, Real * A, Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C char trans_a = 'N'; char trans_b = 'N'; double beta = 0.; int m = im, n = in, k = ik; aka_gemm(&trans_a, &trans_b, &m, &n, &k, &alpha, A, &m, B, &k, &beta, C, &m); #else memset(C, 0, im*in*sizeof(Real)); for (UInt j = 0; j < in; ++j) { UInt _jb = j * ik; UInt _jc = j * im; for (UInt i = 0; i < im; ++i) { for (UInt l = 0; l < ik; ++l) { UInt _la = l * im; C[i + _jc] += A[i + _la] * B[l + _jb]; } C[i + _jc] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_matrix(UInt im, UInt in, UInt ik, Real * A, Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C char trans_a = 'T'; char trans_b = 'N'; double beta = 0.; int m = im, n = in, k = ik; aka_gemm(&trans_a, &trans_b, &m, &n, &k, &alpha, A, &k, B, &k, &beta, C, &m); #else memset(C, 0, im*in*sizeof(Real)); for (UInt j = 0; j < in; ++j) { UInt _jc = j*im; UInt _jb = j*ik; for (UInt i = 0; i < im; ++i) { UInt _ia = i*ik; for (UInt l = 0; l < ik; ++l) { C[i + _jc] += A[l + _ia] * B[l + _jb]; } C[i + _jc] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrix_matrixt(UInt im, UInt in, UInt ik, Real * A, Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C char trans_a = 'N'; char trans_b = 'T'; double beta = 0.; int m = im, n = in, k = ik; aka_gemm(&trans_a, &trans_b, &m, &n, &k, &alpha, A, &m, B, &n, &beta, C, &m); #else memset(C, 0, im*in*sizeof(Real)); for (UInt j = 0; j < in; ++j) { UInt _jc = j * im; for (UInt i = 0; i < im; ++i) { for (UInt l = 0; l < ik; ++l) { UInt _la = l * im; UInt _lb = l * in; C[i + _jc] += A[i + _la] * B[j + _lb]; } C[i + _jc] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_matrixt(UInt im, UInt in, UInt ik, Real * A, Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C char trans_a = 'T'; char trans_b = 'T'; double beta = 0.; int m = im, n = in, k = ik; aka_gemm(&trans_a, &trans_b, &m, &n, &k, &alpha, A, &k, B, &n, &beta, C, &m); #else memset(C, 0, im * in * sizeof(Real)); for (UInt j = 0; j < in; ++j) { UInt _jc = j*im; for (UInt i = 0; i < im; ++i) { UInt _ia = i*ik; for (UInt l = 0; l < ik; ++l) { UInt _lb = l * in; C[i + _jc] += A[l + _ia] * B[j + _lb]; } C[i + _jc] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline Real Math::vectorDot(Real * v1, Real * v2, UInt in) { #ifdef AKANTU_USE_BLAS /// d := v1 . v2 int incx = 1, incy = 1, n = in; Real d = aka_dot(&n, v1, &incx, v2, &incy); #else Real d = 0; for (UInt i = 0; i < in; ++i) { d += v1[i] * v2[i]; } #endif return d; } /* -------------------------------------------------------------------------- */ template inline void Math::matMul(UInt m, UInt n, UInt k, Real alpha, Real * A, Real * B, __attribute__ ((unused)) Real beta, Real * C) { if(tr_A) { if(tr_B) matrixt_matrixt(m, n, k, A, B, C, alpha); else matrixt_matrix(m, n, k, A, B, C, alpha); } else { if(tr_B) matrix_matrixt(m, n, k, A, B, C, alpha); else matrix_matrix(m, n, k, A, B, C, alpha); } } /* -------------------------------------------------------------------------- */ template inline void Math::matVectMul(UInt m, UInt n, Real alpha, Real * A, Real * x, __attribute__ ((unused)) Real beta, Real * y) { if(tr_A) { matrixt_vector(m, n, A, x, y, alpha); } else { matrix_vector(m, n, A, x, y, alpha); } } /* -------------------------------------------------------------------------- */ template inline void Math::matrixEig(UInt n, T * A, T * d, T * V) { // Matrix A is row major, so the lapack function in fortran will process // A^t. Asking for the left eigenvectors of A^t will give the transposed right // eigenvectors of A so in the C++ code the right eigenvectors. char jobvl; if(V != NULL) jobvl = 'V'; // compute left eigenvectors else jobvl = 'N'; // compute left eigenvectors char jobvr('N'); // compute right eigenvectors T * di = new T[n]; // imaginary part of the eigenvalues int info; int N = n; T wkopt; int lwork = -1; // query and allocate the optimal workspace aka_geev(&jobvl, &jobvr, &N, A, &N, d, di, V, &N, NULL, &N, &wkopt, &lwork, &info); lwork = int(wkopt); T * work = new T[lwork]; // solve the eigenproblem aka_geev(&jobvl, &jobvr, &N, A, &N, d, di, V, &N, NULL, &N, work, &lwork, &info); AKANTU_DEBUG_ASSERT(info == 0, "Problem computing eigenvalues/vectors. DGEEV exited with the value " << info); delete [] work; delete [] di; // I hope for you that there was no complex eigenvalues !!! } /* -------------------------------------------------------------------------- */ inline void Math::matrix22_eigenvalues(Real * A, Real *Adiag) { ///d = determinant of Matrix A Real d = det2(A); ///b = trace of Matrix A Real b = A[0]+A[3]; Real c = sqrt(b*b - 4 *d); Adiag[0]= .5*(b + c); Adiag[1]= .5*(b - c); } /* -------------------------------------------------------------------------- */ inline void Math::matrix33_eigenvalues(Real * A, Real *Adiag) { matrixEig(3, A, Adiag); } /* -------------------------------------------------------------------------- */ template inline void Math::eigenvalues(Real * A, Real * d) { if(dim == 1) { d[0] = A[0]; } else if(dim == 2) { matrix22_eigenvalues(A, d); } // else if(dim == 3) { matrix33_eigenvalues(A, d); } else matrixEig(dim, A, d); } /* -------------------------------------------------------------------------- */ inline Real Math::det2(const Real * mat) { return mat[0]*mat[3] - mat[1]*mat[2]; } /* -------------------------------------------------------------------------- */ inline Real Math::det3(const Real * mat) { return mat[0]*(mat[4]*mat[8]-mat[7]*mat[5]) - mat[3]*(mat[1]*mat[8]-mat[7]*mat[2]) + mat[6]*(mat[1]*mat[5]-mat[4]*mat[2]); } /* -------------------------------------------------------------------------- */ template inline Real Math::det(const Real * mat) { if(n == 1) return *mat; else if(n == 2) return det2(mat); else if(n == 3) return det3(mat); else return det(n, mat); } /* -------------------------------------------------------------------------- */ template inline T Math::det(UInt n, const T * A) { int N = n; int info; int * ipiv = new int[N+1]; T * LU = new T[N*N]; std::copy(A, A + N*N, LU); // LU factorization of A aka_getrf(&N, &N, LU, &N, ipiv, &info); if(info > 0) { AKANTU_DEBUG_ERROR("Singular matrix - cannot factorize it (info: " << info <<" )"); } // det(A) = det(L) * det(U) = 1 * det(U) = product_i U_{ii} T det = 1.; for (int i = 0; i < N; ++i) det *= (2*(ipiv[i] == i) - 1) * LU[i*n+i]; delete [] ipiv; delete [] LU; return det; } /* -------------------------------------------------------------------------- */ inline void Math::normal2(const Real * vec,Real * normal) { normal[0] = vec[1]; normal[1] = -vec[0]; Math::normalize2(normal); } /* -------------------------------------------------------------------------- */ inline void Math::normal3(const Real * vec1,const Real * vec2,Real * normal) { Math::vectorProduct3(vec1,vec2,normal); Math::normalize3(normal); } /* -------------------------------------------------------------------------- */ inline void Math::normalize2(Real * vec) { Real norm = Math::norm2(vec); vec[0] /= norm; vec[1] /= norm; } /* -------------------------------------------------------------------------- */ inline void Math::normalize3(Real * vec) { Real norm = Math::norm3(vec); vec[0] /= norm; vec[1] /= norm; vec[2] /= norm; } /* -------------------------------------------------------------------------- */ inline Real Math::norm2(const Real * vec) { return sqrt(vec[0]*vec[0] + vec[1]*vec[1]); } /* -------------------------------------------------------------------------- */ inline Real Math::norm3(const Real * vec) { return sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); } /* -------------------------------------------------------------------------- */ inline Real Math::norm(UInt n, const Real * vec) { Real norm = 0.; for (UInt i = 0; i < n; ++i) { norm += vec[i]*vec[i]; } return sqrt(norm); } /* -------------------------------------------------------------------------- */ inline void Math::inv2(const Real * mat,Real * inv) { Real det_mat = det2(mat); inv[0] = mat[3] / det_mat; inv[1] = -mat[1] / det_mat; inv[2] = -mat[2] / det_mat; inv[3] = mat[0] / det_mat; } /* -------------------------------------------------------------------------- */ inline void Math::inv3(const Real * mat,Real * inv) { Real det_mat = det3(mat); inv[0] = (mat[4]*mat[8] - mat[7]*mat[5])/det_mat; inv[1] = (mat[2]*mat[7] - mat[8]*mat[1])/det_mat; inv[2] = (mat[1]*mat[5] - mat[4]*mat[2])/det_mat; inv[3] = (mat[5]*mat[6] - mat[8]*mat[3])/det_mat; inv[4] = (mat[0]*mat[8] - mat[6]*mat[2])/det_mat; inv[5] = (mat[2]*mat[3] - mat[5]*mat[0])/det_mat; inv[6] = (mat[3]*mat[7] - mat[6]*mat[4])/det_mat; inv[7] = (mat[1]*mat[6] - mat[7]*mat[0])/det_mat; inv[8] = (mat[0]*mat[4] - mat[3]*mat[1])/det_mat; } /* -------------------------------------------------------------------------- */ template inline void Math::inv(const Real * A, Real * Ainv) { if(n == 1) *Ainv = 1./ *A; else if(n == 2) inv2(A, Ainv); else if(n == 3) inv3(A, Ainv); else inv(n, A, Ainv); } /* -------------------------------------------------------------------------- */ template inline void Math::inv(UInt n, const T * A, T * invA) { int N = n; int info; int * ipiv = new int[N+1]; int lwork = N*N; T * work = new T[lwork]; std::copy(A, A + n*n, invA); aka_getrf(&N, &N, invA, &N, ipiv, &info); if(info > 0) { AKANTU_DEBUG_ERROR("Singular matrix - cannot factorize it (info: " << info <<" )"); } aka_getri(&N, invA, &N, ipiv, work, &lwork, &info); if(info != 0) { AKANTU_DEBUG_ERROR("Cannot invert the matrix (info: "<< info <<" )"); } delete [] ipiv; delete [] work; } /* -------------------------------------------------------------------------- */ template inline void Math::solve(UInt n, const T * A, T * x, const T * b) { int N = n; int info; int * ipiv = new int[N]; T * lu_A = new T[N*N]; std::copy(A, A + N*N, lu_A); aka_getrf(&N, &N, lu_A, &N, ipiv, &info); if(info > 0) { AKANTU_DEBUG_ERROR("Singular matrix - cannot factorize it (info: "<< info <<" )"); exit (EXIT_FAILURE); } char trans = 'N'; int nrhs = 1; std::copy(b, b + N, x); aka_getrs(&trans, &N, &nrhs, lu_A, &N, ipiv, x, &N, &info); if(info != 0) { AKANTU_DEBUG_ERROR("Cannot solve the system (info: "<< info <<" )"); exit (EXIT_FAILURE); } delete [] ipiv; delete [] lu_A; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ inline Real Math::matrixDoubleDot22(Real * A, Real * B) { Real d; d = A[0] * B[0] + A[1] * B[1] + A[2] * B[2] + A[3] * B[3]; return d; } /* -------------------------------------------------------------------------- */ inline Real Math::matrixDoubleDot33(Real * A, Real * B) { Real d; d = A[0] * B[0] + A[1] * B[1] + A[2] * B[2] + A[3] * B[3] + A[4] * B[4] + A[5] * B[5] + A[6] * B[6] + A[7] * B[7] + A[8] * B[8]; return d; } /* -------------------------------------------------------------------------- */ inline Real Math::matrixDoubleDot(UInt n, Real * A, Real * B) { Real d = 0.; for (UInt i = 0; i < n; ++i) { for (UInt j = 0; j < n; ++j) { d += A[i*n+j] * B[i*n+j]; } } return d; } /* -------------------------------------------------------------------------- */ inline void Math::vectorProduct3(const Real * v1, const Real * v2, Real * res) { res[0] = v1[1]*v2[2] - v1[2]*v2[1]; res[1] = v1[2]*v2[0] - v1[0]*v2[2]; res[2] = v1[0]*v2[1] - v1[1]*v2[0]; } /* -------------------------------------------------------------------------- */ inline Real Math::vectorDot2(const Real * v1, const Real * v2) { return (v1[0]*v2[0] + v1[1]*v2[1]); } /* -------------------------------------------------------------------------- */ inline Real Math::vectorDot3(const Real * v1, const Real * v2) { return (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]); } /* -------------------------------------------------------------------------- */ inline Real Math::distance_2d(const Real * x, const Real * y) { return sqrt((y[0] - x[0])*(y[0] - x[0]) + (y[1] - x[1])*(y[1] - x[1])); } /* -------------------------------------------------------------------------- */ inline Real Math::triangle_inradius(const Real * coord1, const Real * coord2, const Real * coord3) { /** * @f{eqnarray*}{ * r &=& A / s \\ * A &=& 1/4 * \sqrt{(a + b + c) * (a - b + c) * (a + b - c) (-a + b + c)} \\ * s &=& \frac{a + b + c}{2} * @f} */ Real a, b, c; a = distance_2d(coord1, coord2); b = distance_2d(coord2, coord3); c = distance_2d(coord1, coord3); Real s; s = (a + b + c) * 0.5; return sqrt((s - a) * (s - b) * (s - c) / s); } /* -------------------------------------------------------------------------- */ inline Real Math::distance_3d(const Real * x, const Real * y) { return sqrt((y[0] - x[0])*(y[0] - x[0]) + (y[1] - x[1])*(y[1] - x[1]) + (y[2] - x[2])*(y[2] - x[2]) ); } /* -------------------------------------------------------------------------- */ inline Real Math::tetrahedron_volume(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4) { Real xx[9], vol; xx[0] = coord2[0]; xx[1] = coord2[1]; xx[2] = coord2[2]; xx[3] = coord3[0]; xx[4] = coord3[1]; xx[5] = coord3[2]; xx[6] = coord4[0]; xx[7] = coord4[1]; xx[8] = coord4[2]; vol = det3(xx); xx[0] = coord1[0]; xx[1] = coord1[1]; xx[2] = coord1[2]; xx[3] = coord3[0]; xx[4] = coord3[1]; xx[5] = coord3[2]; xx[6] = coord4[0]; xx[7] = coord4[1]; xx[8] = coord4[2]; vol -= det3(xx); xx[0] = coord1[0]; xx[1] = coord1[1]; xx[2] = coord1[2]; xx[3] = coord2[0]; xx[4] = coord2[1]; xx[5] = coord2[2]; xx[6] = coord4[0]; xx[7] = coord4[1]; xx[8] = coord4[2]; vol += det3(xx); xx[0] = coord1[0]; xx[1] = coord1[1]; xx[2] = coord1[2]; xx[3] = coord2[0]; xx[4] = coord2[1]; xx[5] = coord2[2]; xx[6] = coord3[0]; xx[7] = coord3[1]; xx[8] = coord3[2]; vol -= det3(xx); vol /= 6; return vol; } /* -------------------------------------------------------------------------- */ inline Real Math::tetrahedron_inradius(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4) { Real l12, l13, l14, l23, l24, l34; l12 = distance_3d(coord1, coord2); l13 = distance_3d(coord1, coord3); l14 = distance_3d(coord1, coord4); l23 = distance_3d(coord2, coord3); l24 = distance_3d(coord2, coord4); l34 = distance_3d(coord3, coord4); Real s1, s2, s3, s4; s1 = (l12 + l23 + l13) * 0.5; s1 = sqrt(s1*(s1-l12)*(s1-l23)*(s1-l13)); s2 = (l12 + l24 + l14) * 0.5; s2 = sqrt(s2*(s2-l12)*(s2-l24)*(s2-l14)); s3 = (l23 + l34 + l24) * 0.5; s3 = sqrt(s3*(s3-l23)*(s3-l34)*(s3-l24)); s4 = (l13 + l34 + l14) * 0.5; s4 = sqrt(s4*(s4-l13)*(s4-l34)*(s4-l14)); Real volume = Math::tetrahedron_volume(coord1,coord2,coord3,coord4); return 3*volume/(s1+s2+s3+s4); } /* -------------------------------------------------------------------------- */ inline void Math::barycenter(const Real * coord, UInt nb_points, UInt spatial_dimension, Real * barycenter) { memset(barycenter, 0, spatial_dimension * sizeof(Real)); for (UInt n = 0; n < nb_points; ++n) { UInt offset = n * spatial_dimension; for (UInt i = 0; i < spatial_dimension; ++i) { barycenter[i] += coord[offset + i] / (Real) nb_points; } } } /* -------------------------------------------------------------------------- */ inline void Math::vector_2d(const Real * x, const Real * y, Real * res) { res[0] = y[0]-x[0]; res[1] = y[1]-x[1]; } /* -------------------------------------------------------------------------- */ inline void Math::vector_3d(const Real * x, const Real * y, Real * res) { res[0] = y[0]-x[0]; res[1] = y[1]-x[1]; res[2] = y[2]-x[2]; } /* -------------------------------------------------------------------------- */ inline bool Math::are_float_equal(const Real x, const Real y){ Real abs_max = std::max(std::abs(x), std::abs(y)); - if (abs_max < tolerance) return true; - else return ( std::abs(x - y) / abs_max < tolerance); + if (abs_max <= tolerance) return true; + else return std::abs(x - y) <= (tolerance * abs_max); } /* -------------------------------------------------------------------------- */ inline bool Math::isnan(Real x) { #if defined(__INTEL_COMPILER) #pragma warning ( push ) #pragma warning ( disable : 1572 ) #endif //defined(__INTEL_COMPILER) // x = x return false means x = quiet_NaN return !(x == x); #if defined(__INTEL_COMPILER) #pragma warning ( pop ) #endif //defined(__INTEL_COMPILER) } /* -------------------------------------------------------------------------- */ inline bool Math::are_vector_equal(UInt n, Real * x, Real * y){ bool test = true; for (UInt i = 0; i < n; ++i) { test &= are_float_equal(x[i],y[i]); } return test; } /* -------------------------------------------------------------------------- */ inline bool Math::intersects(Real x_min, Real x_max, Real y_min, Real y_max) { return ! ((x_max <= y_min) || (x_min >= y_max)); } /* -------------------------------------------------------------------------- */ inline bool Math::is_in_range(Real a, Real x_min, Real x_max) { return ((a >= x_min) && (a <= x_max)); } /* -------------------------------------------------------------------------- */ template inline T Math::pow(T x) { return (pow(x)*x); } template<> inline UInt Math::pow<0, UInt>(__attribute__((unused)) UInt x) { return (1); } template<> inline Real Math::pow<0, Real>(__attribute__((unused)) Real x) { return (1.); } /* -------------------------------------------------------------------------- */ template Real Math::NewtonRaphson::solve(const Functor & funct, Real x_0) { Real x = x_0; Real f_x= funct.f(x); UInt iter = 0; while(std::abs(f_x) > this->tolerance && iter < this->max_iteration) { x -= f_x/funct.f_prime(x); f_x = funct.f(x); iter++; } AKANTU_DEBUG_ASSERT(iter < this->max_iteration, "Newton Raphson (" << funct.name << ") solve did not converge in " << this->max_iteration << " iterations (tolerance: " << this->tolerance << ")"); return x; } 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/element_classes/element_class_pentahedron_15_inline_impl.cc b/src/fe_engine/element_classes/element_class_pentahedron_15_inline_impl.cc index 8b5d1fa51..8f7dc8c42 100644 --- a/src/fe_engine/element_classes/element_class_pentahedron_15_inline_impl.cc +++ b/src/fe_engine/element_classes/element_class_pentahedron_15_inline_impl.cc @@ -1,164 +1,164 @@ /** * @file element_class_pentahedron_15_inline_impl.cc * * @author Sacha Laffely * @author Damien Scantamburlo * * @date creation: Wed Mar 19 2015 * * @brief Specialization of the element_class class for the type _pentahedron_15 * * @section LICENSE * * Copyright (©) 2010-2012, 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 * * @verbatim /z | | | 1 | /|\ |/ | \ 10 7 6 / | \ / | \ 4 2--8--0 | \ / / | \11 / 13 12 9----------/y | / \ / |/ \ / 5--14--3 / / / \x x y z * N0 -1 1 0 * N1 -1 0 1 * N2 -1 0 0 * N3 1 1 0 * N4 1 0 1 * N5 1 0 0 * N6 -1 0.5 0.5 * N7 -1 0 0.5 * N8 -1 0.5 0 * N9 0 1 0 * N10 0 0 1 * N11 0 0 0 * N12 1 0.5 0.5 * N13 1 0 0.5 * N14 1 0.5 0 */ /* -------------------------------------------------------------------------- */ AKANTU_DEFINE_ELEMENT_CLASS_PROPERTY(_pentahedron_15, _gt_pentahedron_15, _itp_lagrange_pentahedron_15, _ek_regular, 3, _git_pentahedron, 2); AKANTU_DEFINE_SHAPE(_gt_pentahedron_15, _gst_prism); /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_pentahedron_15>::computeShapes(const vector_type & c, vector_type & N) { // Shape Functions, Natural coordinates N( 0) = 0.5 * c(1) * (1 - c(0)) * (2 * c(1) - 2 - c(0)); N( 1) = 0.5 * c(2) * (1 - c(0)) * (2 * c(2) - 2 - c(0)); N( 2) = 0.5 * (c(0) - 1) * (1 - c(1) - c(2)) * (c(0) + 2 * c(1) + 2 * c(2)); N( 3) = 0.5 * c(1) * (1 + c(0)) * (2 * c(1) - 2 + c(0)); N( 4) = 0.5 * c(2) * (1 + c(0)) * (2 * c(2) - 2 + c(0)); N( 5) = 0.5 * (-c(0) - 1) * (1 - c(1) - c(2)) * (-c(0) + 2 * c(1) + 2 * c(2)); N( 6) = 2.0 * c(1) * c(2) * (1 - c(0)); N( 7) = 2.0 * c(2) * (1 - c(1) - c(2)) * (1 - c(0)); N( 8) = 2.0 * c(1) * (1 - c(0)) * (1 - c(1) - c(2)); - N( 9) = c(1) * (1 - c(0)*c(0)); - N(10) = c(2) * (1 - c(0)*c(0)); - N(11) = (1 - c(1) - c(2)) * (1 - c(0)*c(0)); + N( 9) = c(1) * (1 - c(0) * c(0)); + N(10) = c(2) * (1 - c(0) * c(0)); + N(11) = (1 - c(1) - c(2)) * (1 - c(0) * c(0)); N(12) = 2.0 * c(1) * c(2) * (1 + c(0)); N(13) = 2.0 * c(2) * (1 - c(1) - c(2)) * (1 + c(0)); N(14) = 2.0 * c(1) * (1 - c(1) - c(2)) * (1 + c(0)); } /* -------------------------------------------------------------------------- */ template <> template inline void InterpolationElement<_itp_lagrange_pentahedron_15>::computeDNDS(const vector_type & c, matrix_type & dnds) { //ddx dnds(0, 0) = 0.5 * c(1) * (2 * c(0) - 2 * c(1) + 1); dnds(0, 1) = 0.5 * c(2) * (2 * c(0) - 2 * c(2) + 1); dnds(0, 2) = -0.5 * (2 * c(0) + 2 * c(1) + 2 * c(2) - 1) * (c(1) + c(2) -1); dnds(0, 3) = 0.5 * c(1) * (2 * c(0) + 2 * c(1) - 1); dnds(0, 4) = 0.5 * c(2) * (2 * c(0) + 2 * c(2) - 1); dnds(0, 5) = -0.5 * (c(1) + c(2) - 1) * (2 * c(0) - 2 * c(1) - 2 * c(2) + 1); dnds(0, 6) = -2.0 * c(1) * c(2); dnds(0, 7) = 2.0 * c(2) * (c(1) + c(2) - 1); dnds(0, 8) = 2.0 * c(1) * (c(1) + c(2) - 1); dnds(0, 9) = -2.0 * c(0) * c(1); dnds(0,10) = -2.0 * c(0) * c(2); dnds(0,11) = 2.0 * c(0) * (c(1) + c(2) - 1); dnds(0,12) = 2.0 * c(1) * c(2); dnds(0,13) = -2.0 * c(2) * (c(1) + c(2) - 1); dnds(0,14) = -2.0 * c(1) * (c(1) + c(2) - 1); //ddy dnds(1, 0) = -0.5 * (c(0) - 1) * (4 * c(1) - c(0) - 2); dnds(1, 1) = 0.0; dnds(1, 2) = -0.5 * (c(0) - 1) * (4 * c(1) + c(0) + 2 * (2 * c(2) - 1)); dnds(1, 3) = 0.5 * (c(0) + 1) * (4 * c(1) + c(0) - 2); dnds(1, 4) = 0.0; dnds(1, 5) = 0.5 * (c(0) + 1) * (4 * c(1) - c(0) + 2 * (2 * c(2) - 1)); dnds(1, 6) = -2.0 * (c(0) - 1) * c(2); dnds(1, 7) = 2.0 * c(2) * (c(0) - 1); dnds(1, 8) = 2.0 * (2 * c(1) + c(2) - 1) * (c(0) - 1); - dnds(1, 9) = -(c(0)*c(0) - 1); + dnds(1, 9) = -(c(0) * c(0) - 1); dnds(1,10) = 0.0; dnds(1,11) = (c(0)*c(0) - 1); dnds(1,12) = 2.0 * c(2) * (c(0) + 1); dnds(1,13) = -2.0 * c(2) * (c(0) + 1); dnds(1,14) = -2.0 * (2 * c(1) + c(2) - 1) * (c(0) + 1); //ddz dnds(2, 0) = 0.0; dnds(2, 1) = -0.5 * (c(0) - 1) * (4 * c(2) - c(0) - 2); dnds(2, 2) = -0.5 * (c(0) - 1) * (4 * c(2) + c(0) + 2 * (2 * c(1) - 1)); dnds(2, 3) = 0.0; dnds(2, 4) = 0.5 * (c(0) + 1) * (4 * c(2) + c(0) - 2); dnds(2, 5) = 0.5 * (c(0) + 1) * (4 * c(2) - c(0) + 2 * (2 * c(1) - 1)); dnds(2, 6) = -2.0 * (c(0) - 1) * c(1); dnds(2, 7) = 2.0 * (c(0) - 1) * (2 * c(2) + c(1) - 1); dnds(2, 8) = 2.0 * c(1) * (c(0) - 1); dnds(2, 9) = 0.0; - dnds(2,10) = -(c(0)*c(0) - 1); - dnds(2,11) = (c(0)*c(0) - 1); + dnds(2,10) = -(c(0) * c(0) - 1); + dnds(2,11) = (c(0) * c(0) - 1); dnds(2,12) = 2.0 * (c(0) + 1) * c(1); dnds(2,13) = -2.0 * (c(0) + 1) * (2 * c(2) + c(1) - 1); dnds(2,14) = -2.0 * (c(0) + 1) * c(1); } diff --git a/src/fe_engine/fe_engine.cc b/src/fe_engine/fe_engine.cc index a75e16f9a..425d2c873 100644 --- a/src/fe_engine/fe_engine.cc +++ b/src/fe_engine/fe_engine.cc @@ -1,271 +1,273 @@ /** * @file fe_engine.cc * * @author Guillaume Anciaux * @author Nicolas Richart * * @date creation: Tue Jul 20 2010 * @date last modification: Fri Jun 13 2014 * * @brief Implementation of the FEEngine 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 "fe_engine.hh" #include "mesh.hh" #include "element_class.hh" #include "static_communicator.hh" #include "aka_math.hh" #include "dof_synchronizer.hh" - - /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ FEEngine::FEEngine(Mesh & mesh, UInt element_dimension, ID id, MemoryID memory_id) : Memory(id, memory_id), mesh(mesh), normals_on_quad_points("normals_on_quad_points", id) { AKANTU_DEBUG_IN(); this->element_dimension = (element_dimension != _all_dimensions) ? element_dimension : mesh.getSpatialDimension(); init(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEEngine::init() { } /* -------------------------------------------------------------------------- */ FEEngine::~FEEngine() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEEngine::assembleArray(const Array & elementary_vect, Array & nodal_values, const Array & equation_number, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type, const Array & filter_elements, Real scale_factor) const { AKANTU_DEBUG_IN(); UInt nb_element; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); Array::const_iterator< Vector > conn_it; Array * filtered_connectivity = NULL; if(filter_elements != empty_filter) { nb_element = filter_elements.getSize(); filtered_connectivity = new Array(0, nb_nodes_per_element); FEEngine::filterElementalData(mesh, mesh.getConnectivity(type, ghost_type), *filtered_connectivity, type, ghost_type, filter_elements); const Array & cfiltered = *filtered_connectivity; // \todo temporary patch conn_it = cfiltered.begin(nb_nodes_per_element); } else { nb_element = mesh.getNbElement(type, ghost_type); conn_it = mesh.getConnectivity(type, ghost_type).begin(nb_nodes_per_element); } AKANTU_DEBUG_ASSERT(elementary_vect.getSize() == nb_element, "The vector elementary_vect(" << elementary_vect.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(elementary_vect.getNbComponent() == nb_degree_of_freedom*nb_nodes_per_element, "The vector elementary_vect(" << elementary_vect.getID() << ") has not the good number of component." << "(" << elementary_vect.getNbComponent() << " != " << nb_degree_of_freedom*nb_nodes_per_element << ")"); AKANTU_DEBUG_ASSERT(nodal_values.getNbComponent() == nb_degree_of_freedom, "The vector nodal_values(" << nodal_values.getID() << ") has not the good number of component." << "(" << nodal_values.getNbComponent() << " != " << nb_degree_of_freedom << ")"); nodal_values.resize(mesh.getNbNodes()); Real * nodal_it = nodal_values.storage(); Array::const_matrix_iterator elem_it = elementary_vect.begin(nb_degree_of_freedom, nb_nodes_per_element); for (UInt el = 0; el < nb_element; ++el, ++elem_it, ++conn_it) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = (*conn_it)(n); UInt offset_node = node * nb_degree_of_freedom; const Vector & elem_data = (*elem_it)(n); for (UInt d = 0; d < nb_degree_of_freedom; ++d) { nodal_it[equation_number(offset_node + d)] += scale_factor * elem_data(d); } } } delete filtered_connectivity; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEEngine::assembleMatrix(const Array & elementary_mat, SparseMatrix & matrix, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type, const Array & filter_elements) const { AKANTU_DEBUG_IN(); UInt nb_element; if(ghost_type == _not_ghost) { nb_element = mesh.getNbElement(type); } else { AKANTU_DEBUG_TO_IMPLEMENT(); } UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); if(filter_elements != empty_filter) { nb_element = filter_elements.getSize(); } AKANTU_DEBUG_ASSERT(elementary_mat.getSize() == nb_element, "The vector elementary_mat(" << elementary_mat.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(elementary_mat.getNbComponent() == nb_degree_of_freedom * nb_nodes_per_element * nb_degree_of_freedom * nb_nodes_per_element, "The vector elementary_mat(" << elementary_mat.getID() << ") has not the good number of component."); Real * elementary_mat_val = elementary_mat.storage(); UInt offset_elementary_mat = elementary_mat.getNbComponent(); UInt * connectivity_val = mesh.getConnectivity(type, ghost_type).storage(); UInt size_mat = nb_nodes_per_element * nb_degree_of_freedom; UInt size = mesh.getNbGlobalNodes() * nb_degree_of_freedom; Int * eq_nb_val = matrix.getDOFSynchronizer().getGlobalDOFEquationNumbers().storage(); Int * local_eq_nb_val = new Int[size_mat]; for (UInt e = 0; e < nb_element; ++e) { UInt el = e; if(filter_elements != empty_filter) el = filter_elements(e); Int * tmp_local_eq_nb_val = local_eq_nb_val; UInt * conn_val = connectivity_val + el * nb_nodes_per_element; for (UInt i = 0; i < nb_nodes_per_element; ++i) { UInt n = conn_val[i]; for (UInt d = 0; d < nb_degree_of_freedom; ++d) { *tmp_local_eq_nb_val++ = eq_nb_val[n * nb_degree_of_freedom + d]; } // memcpy(tmp_local_eq_nb_val, eq_nb_val + n * nb_degree_of_freedom, nb_degree_of_freedom * sizeof(Int)); // tmp_local_eq_nb_val += nb_degree_of_freedom; } /// The matrix assembling for cohesive elements with degenerated nodes /// (i.e. elements in correspondence of the crack tips) has to be done /// without considering symmetry + +#if defined(AKANTU_COHESIVE_ELEMENT) if (mesh.getKind(type) == _ek_cohesive){ /// matrix assembling procedure for cohesive elements for (UInt i = 0; i < size_mat; ++i) { UInt c_irn = local_eq_nb_val[i]; if(c_irn < size) { for (UInt j = 0; j < size_mat; ++j) { UInt c_jcn = local_eq_nb_val[j]; if(c_jcn < size) { if (matrix.getSparseMatrixType() == _symmetric){ if (c_jcn >= c_irn){ matrix(c_irn, c_jcn) += elementary_mat_val[j * size_mat + i]; } }else{ matrix(c_irn, c_jcn) += elementary_mat_val[j * size_mat + i]; } } } } } elementary_mat_val += offset_elementary_mat; }else{ - +#endif /// matrix assembling procedure for all the elements except cohesive ones for (UInt i = 0; i < size_mat; ++i) { UInt c_irn = local_eq_nb_val[i]; if(c_irn < size) { UInt j_start = (matrix.getSparseMatrixType() == _symmetric) ? i : 0; for (UInt j = j_start; j < size_mat; ++j) { UInt c_jcn = local_eq_nb_val[j]; if(c_jcn < size) { matrix(c_irn, c_jcn) += elementary_mat_val[j * size_mat + i]; } } } } elementary_mat_val += offset_elementary_mat; } +#if defined(AKANTU_COHESIVE_ELEMENT) } +#endif delete [] local_eq_nb_val; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEEngine::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "FEEngine [" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + element dimension : " << element_dimension << std::endl; stream << space << " + mesh [" << std::endl; mesh.printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/src/fe_engine/fe_engine.hh b/src/fe_engine/fe_engine.hh index 8783e5c72..76d5aa429 100644 --- a/src/fe_engine/fe_engine.hh +++ b/src/fe_engine/fe_engine.hh @@ -1,412 +1,349 @@ /** * @file fe_engine.hh * * @author Guillaume Anciaux * @author Nicolas Richart * * @date creation: Tue Jul 20 2010 * @date last modification: Mon Jul 07 2014 * * @brief FEM class * * @section LICENSE * * Copyright (©) 2010-2012, 2014 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_FE_ENGINE_HH__ #define __AKANTU_FE_ENGINE_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "mesh.hh" #include "element_class.hh" #include "sparse_matrix.hh" - +#include "quadrature_point.hh" /* -------------------------------------------------------------------------- */ -namespace akantu { - class Integrator; - class ShapeFunctions; -} - __BEGIN_AKANTU__ - -class QuadraturePoint : public Element { -public: - typedef Vector position_type; -public: - QuadraturePoint(const Element & element, UInt num_point = 0, UInt nb_quad_per_element = 0) : - Element(element), num_point(num_point), - global_num(element.element*nb_quad_per_element + num_point), - position((Real *)NULL, 0) { }; - - QuadraturePoint(ElementType type = _not_defined, UInt element = 0, - UInt num_point = 0, GhostType ghost_type = _not_ghost) : - Element(type, element, ghost_type), num_point(num_point), global_num(0), - position((Real *)NULL, 0) { }; - - QuadraturePoint(UInt element, UInt num_point, - UInt global_num, - const position_type & position, - ElementType type, - GhostType ghost_type = _not_ghost) : - Element(type, element, ghost_type), num_point(num_point), global_num(global_num), - position((Real *)NULL, 0) { this->position.shallowCopy(position); }; - - QuadraturePoint(const QuadraturePoint & quad) : - Element(quad), num_point(quad.num_point), global_num(quad.global_num), position((Real *) NULL, 0) { - position.shallowCopy(quad.position); - }; - - inline QuadraturePoint & operator=(const QuadraturePoint & q) { - if(this != &q) { - element = q.element; - type = q.type; - ghost_type = q.ghost_type; - num_point = q.num_point; - global_num = q.global_num; - position.shallowCopy(q.position); - } - - return *this; - } - - AKANTU_GET_MACRO(Position, position, const position_type &); - - void setPosition(const position_type & position) { - this->position.shallowCopy(position); - } - - /// function to print the containt of the class - virtual void printself(std::ostream & stream, int indent = 0) const { - std::string space; - for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); - stream << space << "QuadraturePoint ["; - Element::printself(stream, 0); - stream << ", " << num_point << "(" << global_num << ")" << "]"; - } - -public: - UInt num_point; - UInt global_num; -private: - position_type position; -}; +/* -------------------------------------------------------------------------- */ +class Integrator; +class ShapeFunctions; +/* -------------------------------------------------------------------------- */ /** * The generic FEEngine class derived in a FEEngineTemplate class containing the * shape functions and the integration method */ class FEEngine : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FEEngine(Mesh & mesh, UInt spatial_dimension = _all_dimensions, ID id = "fem", MemoryID memory_id = 0); virtual ~FEEngine(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// pre-compute all the shape functions, their derivatives and the jacobians virtual void initShapeFunctions(const GhostType & ghost_type = _not_ghost) = 0; /// extract the nodal values and store them per element template static void extractNodalToElementField(const Mesh & mesh, const Array & nodal_f, Array & elemental_f, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter); /// filter a field template static void filterElementalData(const Mesh & mesh, const Array & quad_f, Array & filtered_f, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter); /* ------------------------------------------------------------------------ */ /* Integration method bridges */ /* ------------------------------------------------------------------------ */ /// integrate f for all elements of type "type" virtual void integrate(const Array & f, Array &intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter) const = 0; /// integrate a scalar value on all elements of type "type" virtual Real integrate(const Array & f, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter) const = 0; /// integrate f for all quadrature points of type "type" but don't sum over all quadrature points virtual void integrateOnQuadraturePoints(const Array & f, Array &intf, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter) const = 0; /// integrate one element scalar value on all elements of type "type" virtual Real integrate(const Vector & f, const ElementType & type, UInt index, const GhostType & ghost_type = _not_ghost) const = 0; /* ------------------------------------------------------------------------ */ /* compatibility with old FEEngine fashion */ /* ------------------------------------------------------------------------ */ #ifndef SWIG /// get the number of quadrature points virtual UInt getNbQuadraturePoints(const ElementType & type, const GhostType & ghost_type = _not_ghost) const = 0; /// get the precomputed shapes const virtual Array & getShapes(const ElementType & type, const GhostType & ghost_type = _not_ghost, UInt id = 0) const = 0; /// get the derivatives of shapes const virtual Array & getShapesDerivatives(const ElementType & type, const GhostType & ghost_type = _not_ghost, UInt id = 0) const = 0; /// get quadrature points const virtual Matrix & getQuadraturePoints(const ElementType & type, const GhostType & ghost_type = _not_ghost) const = 0; #endif /* ------------------------------------------------------------------------ */ /* Shape method bridges */ /* ------------------------------------------------------------------------ */ virtual void gradientOnQuadraturePoints(const Array &u, Array &nablauq, const UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter) const = 0; virtual void interpolateOnQuadraturePoints(const Array &u, Array &uq, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter) const = 0; virtual void interpolateOnQuadraturePoints(const Array & u, ElementTypeMapArray & uq, const ElementTypeMapArray * filter_elements = NULL) const = 0; virtual void computeShapes(const Vector & real_coords, UInt elem, const ElementType & type, Vector & shapes, const GhostType & ghost_type = _not_ghost) const = 0; virtual void computeShapeDerivatives(const Vector & real__coords, UInt element, const ElementType & type, Matrix & shape_derivatives, const GhostType & ghost_type = _not_ghost) const = 0; /* ------------------------------------------------------------------------ */ /* Other methods */ /* ------------------------------------------------------------------------ */ /// pre-compute normals on control points virtual void computeNormalsOnControlPoints(const GhostType & ghost_type = _not_ghost) = 0; /// pre-compute normals on control points virtual void computeNormalsOnControlPoints(__attribute__((unused)) const Array & field, __attribute__((unused)) const GhostType & ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// pre-compute normals on control points virtual void computeNormalsOnControlPoints(__attribute__((unused)) const Array & field, __attribute__((unused)) Array & normal, __attribute__((unused)) const ElementType & type, __attribute__((unused)) const GhostType & ghost_type = _not_ghost) const { AKANTU_DEBUG_TO_IMPLEMENT(); } /// assemble vectors void assembleArray(const Array & elementary_vect, Array & nodal_values, const Array & equation_number, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter, Real scale_factor = 1) const; /// assemble matrix in the complete sparse matrix void assembleMatrix(const Array & elementary_mat, SparseMatrix & matrix, UInt nb_degree_of_freedom, const ElementType & type, const GhostType & ghost_type = _not_ghost, const Array & filter_elements = empty_filter) const; /// assemble a field as a lumped matrix (ex. rho in lumped mass) virtual void assembleFieldLumped(__attribute__ ((unused)) const Array & field_1, __attribute__ ((unused)) UInt nb_degree_of_freedom, __attribute__ ((unused)) Array & lumped, __attribute__ ((unused)) const Array & equation_number, __attribute__ ((unused)) ElementType type, __attribute__ ((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); }; /// assemble a field as a matrix (ex. rho to mass matrix) virtual void assembleFieldMatrix(__attribute__ ((unused)) const Array & field_1, __attribute__ ((unused)) UInt nb_degree_of_freedom, __attribute__ ((unused)) SparseMatrix & matrix, __attribute__ ((unused)) ElementType type, __attribute__ ((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); } #ifdef AKANTU_STRUCTURAL_MECHANICS virtual void assembleFieldMatrix(__attribute__ ((unused)) const Array & field_1, __attribute__ ((unused)) UInt nb_degree_of_freedom, __attribute__ ((unused)) SparseMatrix & M, __attribute__ ((unused)) Array * n, __attribute__ ((unused)) ElementTypeMapArray & rotation_mat, __attribute__ ((unused)) ElementType type, __attribute__ ((unused)) const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); } virtual void computeShapesMatrix(__attribute__ ((unused))const ElementType & type, __attribute__ ((unused))UInt nb_degree_of_freedom, __attribute__ ((unused))UInt nb_nodes_per_element, __attribute__ ((unused))Array * n, __attribute__ ((unused))UInt id, __attribute__ ((unused))UInt degree_to_interpolate, __attribute__ ((unused))UInt degree_interpolated, __attribute__ ((unused))const bool sign, __attribute__ ((unused))const GhostType & ghost_type) const { AKANTU_DEBUG_TO_IMPLEMENT(); } #endif /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; private: /// initialise the class void init(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the dimension of the element handeled by this fe_engine object AKANTU_GET_MACRO(ElementDimension, element_dimension, UInt); /// get the mesh contained in the fem object AKANTU_GET_MACRO(Mesh, mesh, const Mesh &); /// get the mesh contained in the fem object AKANTU_GET_MACRO_NOT_CONST(Mesh, mesh, Mesh &); /// get the in-radius of an element static inline Real getElementInradius(const Matrix & coord, const ElementType & type); /// get the normals on quadrature points AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NormalsOnQuadPoints, normals_on_quad_points, Real); /// get cohesive element type for a given facet type static inline ElementType getCohesiveElementType(const ElementType & type_facet); /// get the interpolation element associated to an element type static inline InterpolationType getInterpolationType(const ElementType & el_type); virtual const ShapeFunctions & getShapeFunctionsInterface() const = 0; virtual const Integrator & getIntegratorInterface() const = 0; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// spatial dimension of the problem UInt element_dimension; /// the mesh on which all computation are made Mesh & mesh; /// normals at quadrature points ElementTypeMapArray normals_on_quad_points; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const FEEngine & _this) { _this.printself(stream); return stream; } /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const QuadraturePoint & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #include "fe_engine_inline_impl.cc" #include "fe_engine_template.hh" #endif /* __AKANTU_FE_ENGINE_HH__ */ diff --git a/src/fe_engine/fe_engine_template_tmpl.hh b/src/fe_engine/fe_engine_template_tmpl.hh index 8a7c1aebf..661200711 100644 --- a/src/fe_engine/fe_engine_template_tmpl.hh +++ b/src/fe_engine/fe_engine_template_tmpl.hh @@ -1,1526 +1,1559 @@ /** * @file fe_engine_template_tmpl.hh * * @author Aurelia Isabel Cuba Ramos * @author Marco Vocialta * @author Nicolas Richart * * @date creation: Mon Nov 05 2012 * @date last modification: Mon Jul 07 2014 * * @brief Template implementation of FEEngineTemplate * * @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" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template