diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 000000000..2efd5a35f --- /dev/null +++ b/AUTHORS @@ -0,0 +1,24 @@ +Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + +Akantu is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Akantu is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with Akantu. If not, see <http://www.gnu.org/licenses/>. + + +Authors : + + - David Kammer <david.kammer@epfl.ch> + - Guillaume ANCIAUX <guillaume.anciaux@epfl.ch> + - Leonardo Snozzi <leonardo.snozzi@epfl.ch> + - Nicolas Richart <nicolas.richart@epfl.ch> + - Peter Spijker <peter.spijker@epfl.ch> diff --git a/CMakeLists.txt b/CMakeLists.txt index 912329789..516fd0054 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,327 +1,341 @@ #=============================================================================== # @file CMakeLists.txt # @author Nicolas Richart <nicolas.richart@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== # _ ,-, _ # ,--, /: :\/': :`\/: :\ # |`; ' `,' `.; `: | _ _ # | | | ' | |. | | | | # | : | F E | A S | T++ || __ _| | ____ _ _ __ | |_ _ _ # | :. | : | : | : | \ / _` | |/ / _` | '_ \| __| | | | # \__/: :.. : :.. | :.. | ) | (_| | < (_| | | | | |_| |_| | # `---',\___/,\___/ /' \__,_|_|\_\__,_|_| |_|\__|\__,_| # `==._ .. . /' # `-::-' #=============================================================================== #=============================================================================== # CMake Project #=============================================================================== cmake_minimum_required(VERSION 2.6) project(AKANTU) enable_language(CXX) #=============================================================================== # Misc. #=============================================================================== set(AKANTU_CMAKE_DIR "${AKANTU_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries.") #=============================================================================== # Version Number #=============================================================================== # AKANTU version number. An even minor number corresponds to releases. set(AKANTU_MAJOR_VERSION 0) set(AKANTU_MINOR_VERSION 1) set(AKANTU_BUILD_VERSION 0) set(AKANTU_VERSION "${AKANTU_MAJOR_VERSION}.${AKANTU_MINOR_VERSION}.${AKANTU_BUILD_VERSION}" ) # Append the library version information to the library target properties if(NOT AKANTU_NO_LIBRARY_VERSION) set(AKANTU_LIBRARY_PROPERTIES ${AKANTU_LIBRARY_PROPERTIES} VERSION "${AKANTU_VERSION}" SOVERSION "${AKANTU_MAJOR_VERSION}.${AKANTU_MINOR_VERSION}" ) endif(NOT AKANTU_NO_LIBRARY_VERSION) #=============================================================================== # Options #=============================================================================== option(AKANTU_DEBUG "Compiles akantu with the debug messages" ON) option(AKANTU_DOCUMENTATION "Build source documentation using Doxygen." OFF) # compilation switch option(AKANTU_BUILD_CONTACT "Build the contact algorithm" OFF) # features option(AKANTU_USE_IOHELPER "Add IOHelper support in akantu" OFF) option(AKANTU_USE_MPI "Add MPI support in akantu" OFF) option(AKANTU_USE_SCOTCH "Add Scotch support in akantu" OFF) option(AKANTU_USE_MUMPS "Add Mumps support in akantu" OFF) option(AKANTU_USE_BLAS "Use BLAS for arithmetic operations" OFF) option(AKANTU_USE_EPSN "Use EPSN streering environment" OFF) #=============================================================================== # Options handling #=============================================================================== # Debug if(NOT AKANTU_DEBUG) add_definitions(-DAKANTU_NDEBUG) endif(NOT AKANTU_DEBUG) # IOHelper if(AKANTU_USE_IOHELPER) find_package(IOHelper REQUIRED) if(IOHELPER_FOUND) add_definitions(-DAKANTU_USE_IOHELPER) set(AKANTU_EXTERNAL_LIB_INCLUDE_PATH ${AKANTU_EXTERNAL_LIB_INCLUDE_PATH} ${IOHELPER_INCLUDE_PATH} ) set(AKANTU_EXTERNAL_LIBRARIES ${AKANTU_EXTERNAL_LIBRARIES} ${IOHELPER_LIBRARIES} ) endif(IOHELPER_FOUND) endif(AKANTU_USE_IOHELPER) # MPI set(AKANTU_MPI_ON FALSE) if(AKANTU_USE_MPI) find_package(MPI REQUIRED) if(MPI_FOUND) add_definitions(-DAKANTU_USE_MPI) set(AKANTU_EXTERNAL_LIB_INCLUDE_PATH ${AKANTU_EXTERNAL_LIB_INCLUDE_PATH} ${MPI_INCLUDE_PATH} ) set(AKANTU_EXTERNAL_LIBRARIES ${AKANTU_EXTERNAL_LIBRARIES} ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARY} ) set(AKANTU_MPI_ON TRUE) endif(MPI_FOUND) endif(AKANTU_USE_MPI) # Scotch set(AKANTU_SCOTCH_ON FALSE) if(AKANTU_USE_SCOTCH) find_package(Scotch REQUIRED) if(SCOTCH_FOUND) add_definitions(-DAKANTU_USE_SCOTCH) set(AKANTU_EXTERNAL_LIB_INCLUDE_PATH ${AKANTU_EXTERNAL_LIB_INCLUDE_PATH} ${SCOTCH_INCLUDE_PATH} ) set(AKANTU_EXTERNAL_LIBRARIES ${AKANTU_EXTERNAL_LIBRARIES} ${SCOTCH_LIBRARIES} ) set(AKANTU_SCOTCH_ON TRUE) endif(SCOTCH_FOUND) endif(AKANTU_USE_SCOTCH) # MUMPS set(AKANTU_MUMPS_ON FALSE) if(AKANTU_USE_MUMPS) find_package(Mumps REQUIRED) if(MUMPS_FOUND) add_definitions(-DAKANTU_USE_MUMPS) set(AKANTU_EXTERNAL_LIB_INCLUDE_PATH ${AKANTU_EXTERNAL_LIB_INCLUDE_PATH} ${MUMPS_INCLUDE_PATH} ) set(AKANTU_EXTERNAL_LIBRARIES ${AKANTU_EXTERNAL_LIBRARIES} ${MUMPS_LIBRARIES} ) set(AKANTU_MUMPS_ON TRUE) endif(MUMPS_FOUND) endif(AKANTU_USE_MUMPS) # BLAS set(AKANTU_BLAS_ON FALSE) if(AKANTU_USE_BLAS) enable_language(Fortran) find_package(BLAS) if(BLAS_FOUND) add_definitions(-DAKANTU_USE_CBLAS) set(AKANTU_EXTERNAL_LIBRARIES ${AKANTU_EXTERNAL_LIBRARIES} ${BLAS_LIBRARIES} ) set(AKANTU_BLAS_ON TRUE) endif(BLAS_FOUND) endif(AKANTU_USE_BLAS) # EPSN set(AKANTU_EPSN_ON FALSE) if(AKANTU_USE_EPSN) find_package(EPSN) if(EPSN_FOUND) add_definitions(-DAKANTU_USE_EPSN) set(AKANTU_EXTERNAL_LIB_INCLUDE_PATH ${AKANTU_EXTERNAL_LIB_INCLUDE_PATH} ${EPSN_INCLUDE_DIR} ) set(AKANTU_EXTERNAL_LIBRARIES ${AKANTU_EXTERNAL_LIBRARIES} ${EPSN_LIBRARIES} ) set(AKANTU_EPSN_ON TRUE) endif(EPSN_FOUND) endif(AKANTU_USE_EPSN) #=============================================================================== # Library #=============================================================================== set(AKANTU_COMMON_SRC common/aka_common.cc common/aka_error.cc common/aka_extern.cc common/aka_static_memory.cc common/aka_memory.cc common/aka_vector.cc common/aka_math.cc fem/mesh.cc fem/fem.cc fem/element_class.cc # model/integration_scheme/central_difference.cc model/solid_mechanics/solid_mechanics_model.cc model/solid_mechanics/solid_mechanics_model_mass.cc model/solid_mechanics/solid_mechanics_model_boundary.cc model/solid_mechanics/solid_mechanics_model_material.cc model/solid_mechanics/material.cc model/solid_mechanics/materials/material_elastic.cc mesh_utils/mesh_io.cc mesh_utils/mesh_io/mesh_io_msh.cc mesh_utils/mesh_partition.cc mesh_utils/mesh_utils.cc solver/sparse_matrix.cc solver/solver.cc synchronizer/ghost_synchronizer.cc synchronizer/synchronizer.cc synchronizer/communicator.cc synchronizer/static_communicator.cc ) set(AKANTU_CONTACT_SRC model/solid_mechanics/contact.cc model/solid_mechanics/contact_search.cc model/solid_mechanics/contact_neighbor_structure.cc model/solid_mechanics/contact/contact_2d_explicit.cc model/solid_mechanics/contact/contact_search_2d_explicit.cc model/solid_mechanics/contact/regular_grid_neighbor_structure.cc model/solid_mechanics/contact/contact_search_3d_explicit.cc model/solid_mechanics/contact/contact_3d_explicit.cc model/solid_mechanics/contact/grid_2d_neighbor_structure.cc model/solid_mechanics/contact/contact_rigid_no_friction.cc ) if(AKANTU_BUILD_CONTACT) set(AKANTU_COMMON_SRC ${AKANTU_COMMON_SRC} ${AKANTU_CONTACT_SRC}) endif(AKANTU_BUILD_CONTACT) if(AKANTU_USE_MPI AND MPI_FOUND) set(AKANTU_COMMON_SRC ${AKANTU_COMMON_SRC} synchronizer/static_communicator_mpi.cc ) endif(AKANTU_USE_MPI AND MPI_FOUND) if(AKANTU_SCOTCH_ON) set(AKANTU_COMMON_SRC ${AKANTU_COMMON_SRC} mesh_utils/mesh_partition/mesh_partition_scotch.cc ) endif(AKANTU_SCOTCH_ON) if(AKANTU_MUMPS_ON) set(AKANTU_COMMON_SRC ${AKANTU_COMMON_SRC} solver/solver_mumps.cc ) endif(AKANTU_MUMPS_ON) set(AKANTU_INCLUDE_DIRS common fem/ mesh_utils/ mesh_utils/mesh_io/ mesh_utils/mesh_partition/ model/ model/integration_scheme model/solid_mechanics model/solid_mechanics/materials model/solid_mechanics/contact synchronizer/ solver/ ) include_directories( ${AKANTU_INCLUDE_DIRS} ${AKANTU_EXTERNAL_LIB_INCLUDE_PATH} ) add_library(akantu ${AKANTU_COMMON_SRC}) set_target_properties(akantu PROPERTIES ${AKANTU_LIBRARY_PROPERTIES}) #=========================================================================== # Documentation #=========================================================================== if(AKANTU_DOCUMENTATION) find_package(Doxygen REQUIRED) if(DOXYGEN_FOUND) set(DOXYGEN_WARNINGS NO) set(DOXYGEN_QUIET YES) if(CMAKE_VERBOSE_MAKEFILE) set(DOXYGEN_WARNINGS YES) set(DOXYGEN_QUIET NO) endif(CMAKE_VERBOSE_MAKEFILE) add_subdirectory(doc/doxygen) endif(DOXYGEN_FOUND) endif(AKANTU_DOCUMENTATION) #=============================================================================== # Tests #=============================================================================== ENABLE_TESTING() INCLUDE(CTest) option(AKANTU_TESTS "Activate tests" OFF) if(AKANTU_TESTS) find_package(GMSH REQUIRED) add_subdirectory(test) endif(AKANTU_TESTS) #=============================================================================== # Examples #=============================================================================== option(AKANTU_EXAMPLES "Activate examples" OFF) if(AKANTU_EXAMPLES) find_package(GMSH REQUIRED) add_subdirectory(examples) endif(AKANTU_EXAMPLES) diff --git a/COPYING b/COPYING new file mode 100644 index 000000000..65c5ca88a --- /dev/null +++ b/COPYING @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/cmake/AkantuTestAndExamples.cmake b/cmake/AkantuTestAndExamples.cmake index d1892af95..a020de5bc 100644 --- a/cmake/AkantuTestAndExamples.cmake +++ b/cmake/AkantuTestAndExamples.cmake @@ -1,88 +1,102 @@ #=============================================================================== # @file AkantuTestAndExamples.cmake # @author Nicolas Richart <nicolas.richart@epfl.ch> # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @date Mon Oct 25 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== macro(manage_test_and_example et_name desc build_all label) string(TOUPPER ${et_name} upper_name) option(AKANTU_BUILD${label}${upper_name} "${desc}") mark_as_advanced(AKANTU_BUILD_${upper_name}) if(${build_all}) set(AKANTU_BUILD${label}${upper_name}_OLD ${AKANTU_BUILD${label}${upper_name}} CACHE INTERNAL "${desc}" FORCE) set(AKANTU_BUILD${label}${upper_name} ON CACHE INTERNAL "${desc}" FORCE) else(${build_all}) 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(${build_all}) if(AKANTU_BUILD${label}${upper_name}) add_subdirectory(${et_name}) endif(AKANTU_BUILD${label}${upper_name}) endmacro() #=============================================================================== # Tests #=============================================================================== if(AKANTU_TESTS) option(AKANTU_BUILD_ALL_TESTS "Build all tests") mark_as_advanced(AKANTU_BUILD_ALL_TESTS) endif(AKANTU_TESTS) #=============================================================================== macro(register_test test_name) add_executable(${test_name} ${ARGN}) target_link_libraries(${test_name} akantu ${AKANTU_EXTERNAL_LIBRARIES}) if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${test_name}.sh) add_test(${test_name} ${CMAKE_CURRENT_BINARY_DIR}/${test_name}.sh) else(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${test_name}.sh) add_test(${test_name} ${CMAKE_CURRENT_BINARY_DIR}/${test_name}) endif(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${test_name}.sh) endmacro() #=============================================================================== macro(add_akantu_test test_name desc) manage_test_and_example(${test_name} ${desc} AKANTU_BUILD_ALL_TESTS _) endmacro() #=============================================================================== # 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 source_list) add_executable(${example_name} ${source_list}) 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_) endmacro() diff --git a/cmake/FindEPSN.cmake b/cmake/FindEPSN.cmake index e54de40aa..a06979f90 100644 --- a/cmake/FindEPSN.cmake +++ b/cmake/FindEPSN.cmake @@ -1,39 +1,53 @@ #=============================================================================== # @file FindEPSN.cmake # @author Nicolas Richart <nicolas.richart@epfl.ch> # @date Tue Aug 25 16:53:57 2010 # # @brief The find_package file for EPSN # # @section LICENSE # -# <insert license here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # #=============================================================================== #=============================================================================== find_path(EPSN_DIR EPSNConfig.cmake PATHS $ENV{EPSN_TOP} ) if(EPSN_DIR) include(${EPSN_DIR}/EPSNConfig.cmake) set(EPSN_LIB_PATH ${EPSN_DIR}/lib ${EPSN_LIBRARIES_DIR} ) find_library(EPSN_COMMON_LIBRARY epsn_common PATHS ${EPSN_LIB_PATH} ) find_library(EPSN_SIMULATION_LIBRARY epsn_simulation PATHS ${EPSN_LIB_PATH} ) include(${EPSN_DIR}/EPSNLibraryDepends.cmake) set(EPSN_LIBRARIES ${EPSN_SIMULATION_LIBRARY} ${EPSN_COMMON_LIBRARY}) endif(EPSN_DIR) #=============================================================================== include(FindPackageHandleStandardArgs) find_package_handle_standard_args(EPSN DEFAULT_MSG EPSN_LIBRARIES EPSN_INCLUDE_DIR) diff --git a/cmake/FindGMSH.cmake b/cmake/FindGMSH.cmake index 38b07d4cc..64fb3df6f 100644 --- a/cmake/FindGMSH.cmake +++ b/cmake/FindGMSH.cmake @@ -1,87 +1,101 @@ #=============================================================================== # @file FindGMSH.cmake # @author Nicolas Richart <nicolas.richart@epfl.ch> # @date Thu Oct 14 13:15:47 2010 # # @brief Find gmsh and delacre the add_mesh macro # # @section LICENSE # -# <insert license here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # #=============================================================================== find_program(GMSH gmsh DOC "The mesh generetor gmsh") find_package(PackageHandleStandardArgs) find_package_handle_standard_args(GMSH DEFAULT_MSG GMSH) #=============================================================================== macro(PARSE_ARGUMENTS prefix arg_names option_names) set(DEFAULT_ARGS) foreach(arg_name ${arg_names}) set(${prefix}_${arg_name}) endforeach(arg_name) foreach(option ${option_names}) set(${prefix}_${option} FALSE) endforeach(option) set(current_arg_name DEFAULT_ARGS) set(current_arg_list) foreach(arg ${ARGN}) set(larg_names ${arg_names}) list(FIND larg_names "${arg}" is_arg_name) if (is_arg_name GREATER -1) set(${prefix}_${current_arg_name} ${current_arg_list}) set(current_arg_name ${arg}) set(current_arg_list) else (is_arg_name GREATER -1) set(loption_names ${option_names}) list(FIND loption_names "${arg}" is_option) if (is_option GREATER -1) set(${prefix}_${arg} TRUE) else (is_option GREATER -1) set(current_arg_list ${current_arg_list} ${arg}) endif (is_option GREATER -1) endif (is_arg_name GREATER -1) endforeach(arg) set(${prefix}_${current_arg_name} ${current_arg_list}) endmacro(PARSE_ARGUMENTS) #=============================================================================== macro(ADD_MESH MESH_TARGET GEO_FILE DIM ORDER) if(GMSH_FOUND) set(arguments ${MESH_TARGET} ${GEO_FILE} ${DIM} ${ORDER} ${ARGN} ) parse_arguments(ADD_MESH "OUTPUT" ${arguments} ) set(_geo_file ${CMAKE_CURRENT_SOURCE_DIR}/${GEO_FILE}) if(ADD_MESH_OUTPUT) set(_msh_file ${CMAKE_CURRENT_BINARY_DIR}/${ADD_MESH_OUTPUT}) else(ADD_MESH_OUTPUT) get_filename_component(_msh_file "${GEO_FILE}" NAME_WE) set(_msh_file ${CMAKE_CURRENT_BINARY_DIR}/${_msh_file}.msh) endif(ADD_MESH_OUTPUT) if(EXISTS ${_geo_file}) add_custom_command( OUTPUT ${_msh_file} DEPENDS ${_geo_file} COMMAND ${GMSH} ARGS -${DIM} -order ${ORDER} -optimize -o ${_msh_file} ${_geo_file} 2>&1 > /dev/null ) add_custom_target(${MESH_TARGET} DEPENDS ${_msh_file}) else(EXISTS ${_geo_file}) message(FATAL_ERROR "File ${_geo_file} not found") endif(EXISTS ${_geo_file}) endif(GMSH_FOUND) endmacro(ADD_MESH) diff --git a/cmake/FindIOHelper.cmake b/cmake/FindIOHelper.cmake index 51a6a5141..e1f02f0f5 100644 --- a/cmake/FindIOHelper.cmake +++ b/cmake/FindIOHelper.cmake @@ -1,44 +1,58 @@ #=============================================================================== # @file FindIOHelper.cmake # @author Nicolas Richart <nicolas.richart@epfl.ch> # @date Tue Aug 3 16:29:57 2010 # # @brief The find_package file for IOHelper # # @section LICENSE # -# <insert license here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # #=============================================================================== #=============================================================================== set(IOHELPER_LIBRARY "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) find_library(IOHELPER_LIBRARY IOHelper PATHS ${IOHELPER_DIR} PATH_SUFFIXES src ) find_path(IOHELPER_INCLUDE_PATH io_helper.h PATHS ${IOHELPER_DIR} PATH_SUFFIXES src ) #=============================================================================== mark_as_advanced(IOHELPER_LIBRARY) mark_as_advanced(IOHELPER_INCLUDE_PATH) #=============================================================================== find_package(ZLIB REQUIRED) set(IOHELPER_LIBRARIES_ALL ${IOHELPER_LIBRARY} ${ZLIB_LIBRARIES}) set(IOHELPER_LIBRARIES ${IOHELPER_LIBRARIES_ALL} CACHE INTERNAL "Libraries for IOHelper" FORCE) #=============================================================================== include(FindPackageHandleStandardArgs) find_package_handle_standard_args(IOHELPER DEFAULT_MSG IOHELPER_LIBRARY IOHELPER_INCLUDE_PATH) #=============================================================================== if(NOT IOHELPER_FOUND) set(IOHELPER_DIR "" CACHE PATH "Location of IOHelper source directory.") endif(NOT IOHELPER_FOUND) diff --git a/cmake/FindMumps.cmake b/cmake/FindMumps.cmake index be378c556..ac6465f64 100644 --- a/cmake/FindMumps.cmake +++ b/cmake/FindMumps.cmake @@ -1,60 +1,74 @@ #=============================================================================== # @file FindMumps.cmake # @author Nicolas Richart <nicolas.richart@epfl.ch> # @date Sun Dec 12 18:35:02 2010 # # @brief The find_package file for the Mumps solver # # @section LICENSE # -# <insert license here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # #=============================================================================== #=============================================================================== find_library(MUMPS_LIBRARY_DMUMPS NAME dmumps_scotch PATHS ${MUMPS_DIR} /usr PATH_SUFFIXES lib ) find_library(MUMPS_LIBRARY_COMMON NAME mumps_common_scotch PATHS ${MUMPS_DIR} PATH_SUFFIXES lib ) find_library(MUMPS_LIBRARY_PORD NAME pord_scotch PATHS ${MUMPS_DIR} PATH_SUFFIXES lib ) find_path(MUMPS_INCLUDE_PATH dmumps_c.h PATHS ${MUMPS_DIR} PATH_SUFFIXES include ) set(MUMPS_LIBRARIES ${MUMPS_LIB_COMMON} ${MUMPS_LIB_DMUMPS} ${MUMPS_LIB_PORD} CACHE INTERNAL "Libraries for mumps" FORCE ) #=============================================================================== mark_as_advanced(MUMPS_LIBRARY_COMMON) mark_as_advanced(MUMPS_LIBRARY_DMUMPS) mark_as_advanced(MUMPS_LIBRARY_PROD) mark_as_advanced(MUMPS_INCLUDE_PATH) set(MUMPS_LIBRARIES_ALL ${MUMPS_LIBRARY_DMUMPS} ${MUMPS_LIBRARY_COMMON} ${MUMPS_LIBRARY_PROD}) set(MUMPS_LIBRARIES ${MUMPS_LIBRARIES_ALL} CACHE INTERNAL "Libraries for mumps" FORCE) #=============================================================================== include(FindPackageHandleStandardArgs) find_package_handle_standard_args(MUMPS DEFAULT_MSG MUMPS_LIBRARIES MUMPS_INCLUDE_PATH) #=============================================================================== if(NOT MUMPS_FOUND) set(MUMPS_DIR "" CACHE PATH "Prefix of mumps library.") endif(NOT MUMPS_FOUND) diff --git a/cmake/FindScotch.cmake b/cmake/FindScotch.cmake index 66fd4507b..1e63994e4 100644 --- a/cmake/FindScotch.cmake +++ b/cmake/FindScotch.cmake @@ -1,59 +1,73 @@ #=============================================================================== # @file FindScotch.cmake # @author Nicolas Richart <nicolas.richart@epfl.ch> # @date Tue Aug 25 16:53:57 2010 # # @brief The find_package file for Scotch # # @section LICENSE # -# <insert license here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # #=============================================================================== #=============================================================================== #if(SCOTCH_DIR) # set(SCOTCH_LIBRARY "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) #endif(SCOTCH_DIR) find_library(SCOTCH_LIBRARY scotch PATHS ${SCOTCH_DIR} PATH_SUFFIXES src/libscotch lib ) find_library(SCOTCH_LIBRARY_ERR scotcherr PATHS ${SCOTCH_DIR} PATH_SUFFIXES src/libscotch lib ) find_path(SCOTCH_INCLUDE_PATH scotch.h PATHS ${SCOTCH_DIR} PATH_SUFFIXES include scotch src/libscotch include/scotch ) #=============================================================================== mark_as_advanced(SCOTCH_LIBRARY) mark_as_advanced(SCOTCH_LIBRARY_ERR) mark_as_advanced(SCOTCH_INCLUDE_PATH) set(SCOTCH_LIBRARIES_ALL ${SCOTCH_LIBRARY} ${SCOTCH_LIBRARY_ERR}) set(SCOTCH_LIBRARIES ${SCOTCH_LIBRARIES_ALL} CACHE INTERNAL "Libraries for scotch" FORCE) #=============================================================================== include(FindPackageHandleStandardArgs) find_package_handle_standard_args(SCOTCH DEFAULT_MSG SCOTCH_LIBRARY SCOTCH_LIBRARY_ERR SCOTCH_INCLUDE_PATH) if(SCOTCH_INCLUDE_PATH) file(STRINGS ${SCOTCH_INCLUDE_PATH}/scotch.h SCOTCH_INCLUDE_CONTENT) string(REGEX MATCH "_cplusplus" _match ${SCOTCH_INCLUDE_CONTENT}) if(_match) add_definitions(-DAKANTU_SCOTCH_NO_EXTERN) endif() endif() #=============================================================================== if(NOT SCOTCH_FOUND) set(SCOTCH_DIR "" CACHE PATH "Location of Scotch library.") endif(NOT SCOTCH_FOUND) diff --git a/common/aka_common.cc b/common/aka_common.cc index 972125381..ed0971065 100644 --- a/common/aka_common.cc +++ b/common/aka_common.cc @@ -1,49 +1,63 @@ /** * @file aka_common.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Jun 11 16:56:43 2010 * * @brief Initialization of global variables * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_static_memory.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void initialize(int * argc, char *** argv) { AKANTU_DEBUG_IN(); StaticMemory::getStaticMemory(); StaticCommunicator * comm = StaticCommunicator::getStaticCommunicator(argc, argv); debug::setParallelContext(comm->whoAmI(), comm->getNbProc()); debug::initSignalHandler(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void finalize() { AKANTU_DEBUG_IN(); if(StaticMemory::isInstantiated()) delete StaticMemory::getStaticMemory(); if(StaticCommunicator::isInstantiated()) { StaticCommunicator *comm = StaticCommunicator::getStaticCommunicator(); comm->barrier(); delete comm; } AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/common/aka_common.hh b/common/aka_common.hh index 812f9743e..66fa64368 100644 --- a/common/aka_common.hh +++ b/common/aka_common.hh @@ -1,279 +1,293 @@ /** * @file aka_common.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Jun 11 09:48:06 2010 * * @namespace akantu * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * * @section DESCRIPTION * * All common things to be included in the projects files * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COMMON_HH__ #define __AKANTU_COMMON_HH__ /* -------------------------------------------------------------------------- */ #include <cmath> #include <cstdlib> #include <cstring> /* -------------------------------------------------------------------------- */ #include <iostream> #include <iomanip> #include <string> #include <exception> #include <vector> #include <map> #include <set> #include <list> #include <limits> #include <algorithm> /* -------------------------------------------------------------------------- */ #define __BEGIN_AKANTU__ namespace akantu { #define __END_AKANTU__ } /* -------------------------------------------------------------------------- */ #include "aka_error.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Common types */ /* -------------------------------------------------------------------------- */ typedef double Real; typedef unsigned int UInt; typedef int Int; typedef std::string ID; #ifdef AKANTU_NDEBUG static const Real REAL_INIT_VALUE = 0; #else static const Real REAL_INIT_VALUE = std::numeric_limits<Real>::quiet_NaN(); #endif /* -------------------------------------------------------------------------- */ /* Memory types */ /* -------------------------------------------------------------------------- */ typedef UInt MemoryID; typedef ID VectorID; /* -------------------------------------------------------------------------- */ /* Mesh/FEM/Model types */ /* -------------------------------------------------------------------------- */ typedef ID MeshID; typedef ID FEMID; typedef ID ModelID; typedef ID MaterialID; typedef ID SparseMatrixID; typedef ID SolverID; typedef UInt Surface; /// @enum ElementType type of element potentially contained in a Mesh enum ElementType { _not_defined = 0, _segment_2 = 1, /// first order segment _segment_3 = 2, /// second order segment _triangle_3 = 3, /// first order triangle _triangle_6 = 4, /// second order triangle _tetrahedron_4 = 5, /// first order tetrahedron _tetrahedron_10 = 6, /// second order tetrahedron @remark not implemented yet _quadrangle_4, /// first order quadrangle _max_element_type, _point /// point only for some algorithm to be generic like mesh partitioning }; /// @enum MaterialType different materials implemented enum MaterialType { _elastic = 0, _max_material_type }; /// @enum BoundaryFunctionType type of function passed for boundary conditions enum BoundaryFunctionType { _bft_stress, _bft_forces }; /// @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_no_fric = 3 }; enum ContactSearchType { _cst_not_defined = 0, _cst_2d_expli = 1, _cst_3d_expli = 2 }; enum ContactNeighborStructureType { _cnst_not_defined = 0, _cnst_regular_grid = 1, _cnst_2d_grid = 2 }; /* -------------------------------------------------------------------------- */ /* Ghosts handling */ /* -------------------------------------------------------------------------- */ typedef ID SynchronizerID; /// @enum CommunicatorType type of communication method to use enum CommunicatorType { _communicator_mpi, _communicator_dummy }; /// @enum GhostSynchronizationTag type of synchronizations enum GhostSynchronizationTag { /// SolidMechanicsModel tags _gst_smm_mass, /// synchronization of the SolidMechanicsModel.mass _gst_smm_residual, /// synchronization of the SolidMechanicsModel.current_position _gst_smm_boundary, /// synchronization of the boundary, forces, velocities and displacement /// Test tag _gst_test }; /// @enum GhostType type of ghost enum GhostType { _not_ghost, _ghost, _casper // not used but a real cute ghost }; /// @enum SynchronizerOperation reduce operation that the synchronizer can perform enum SynchronizerOperation { _so_sum, _so_min, _so_max, _so_null }; /* -------------------------------------------------------------------------- */ /* Global defines */ /* -------------------------------------------------------------------------- */ #define AKANTU_MIN_ALLOCATION 2000 #define AKANTU_INDENT " " /* -------------------------------------------------------------------------- */ #define AKANTU_SET_MACRO(name, variable, type) \ inline void set##name (type variable) { \ this->variable = variable; \ } #define AKANTU_GET_MACRO(name, variable, type) \ inline type get##name () const { \ return variable; \ } #define AKANTU_GET_MACRO_NOT_CONST(name, variable, type) \ inline type get##name () { \ return variable; \ } #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE(name, variable, type) \ inline type get##name (const ::akantu::ElementType & el_type) const { \ AKANTU_DEBUG_IN(); \ AKANTU_DEBUG_ASSERT(variable[el_type] != NULL, \ "No " << #variable << " of type " \ << el_type << " in " << id); \ AKANTU_DEBUG_OUT(); \ return *variable[el_type]; \ } /* -------------------------------------------------------------------------- */ //! standard output stream operator for ElementType inline std::ostream & operator <<(std::ostream & stream, ElementType type) { switch(type) { case _segment_2 : stream << "segment_2" ; break; case _segment_3 : stream << "segment_3" ; break; case _triangle_3 : stream << "triangle_3" ; break; case _triangle_6 : stream << "triangle_6" ; break; case _tetrahedron_4 : stream << "tetrahedron_4" ; break; case _tetrahedron_10 : stream << "tetrahedron_10"; break; case _quadrangle_4 : stream << "quadrangle_4" ; break; case _not_defined : stream << "undefined" ; break; case _max_element_type : stream << "ElementType(" << (int) type << ")"; break; case _point : stream << "point"; break; } return stream; } /* -------------------------------------------------------------------------- */ void initialize(int * argc, char *** argv); /* -------------------------------------------------------------------------- */ void finalize (); /* -------------------------------------------------------------------------- */ /* * For intel compiler annoying remark */ #if defined(__INTEL_COMPILER) /// remark #981: operands are evaluated in unspecified order #pragma warning ( disable : 981 ) /// remark #383: value copied to temporary, reference to temporary used #pragma warning ( disable : 383 ) #endif //defined(__INTEL_COMPILER) /* -------------------------------------------------------------------------- */ /* string manipulation */ /* -------------------------------------------------------------------------- */ inline void to_lower(std::string & str) { std::transform(str.begin(), str.end(), str.begin(), (int(*)(int))std::tolower); } /* -------------------------------------------------------------------------- */ inline void trim(std::string & to_trim) { size_t first = to_trim.find_first_not_of(" \t"); if (first != std::string::npos) { size_t last = to_trim.find_last_not_of(" \t"); to_trim = to_trim.substr(first, last - first + 1); } else to_trim = ""; } __END_AKANTU__ #endif /* __AKANTU_COMMON_HH__ */ diff --git a/common/aka_error.cc b/common/aka_error.cc index 933872364..0729b8207 100644 --- a/common/aka_error.cc +++ b/common/aka_error.cc @@ -1,112 +1,126 @@ /** * @file aka_error.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Sun Sep 5 21:03:37 2010 * * @brief * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <csignal> #include <cerrno> #include <execinfo.h> #include <cxxabi.h> /* -------------------------------------------------------------------------- */ #include "aka_error.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ namespace debug { /* ------------------------------------------------------------------------ */ void setDebugLevel(const DebugLevel & level) { _debug_level = level; } /* ------------------------------------------------------------------------ */ const DebugLevel & getDebugLevel() { return _debug_level; } /* ------------------------------------------------------------------------ */ void setParallelContext(int rank, int size) { std::stringstream sstr; sstr << "[" << std::setfill(' ') << std::right << std::setw(3) << (rank + 1) << "/" << size << "] "; _parallel_context = sstr.str(); } /* ------------------------------------------------------------------------ */ void initSignalHandler() { struct sigaction action; action.sa_handler = &printBacktrace; sigemptyset(&(action.sa_mask)); action.sa_flags = SA_RESETHAND; sigaction(SIGSEGV, &action, NULL); } /* ------------------------------------------------------------------------ */ static std::string demangle(const char* symbol) { std::string trace(symbol); std::string::size_type begin = trace.find_first_of('(') + 1; std::string::size_type end = trace.find_last_of('+'); if (begin != std::string::npos && end != std::string::npos) { std::string sub_trace = trace.substr(begin, end - begin); int status; size_t size; std::string result; char * demangled_name; if ((demangled_name = abi::__cxa_demangle(sub_trace.c_str(), NULL, &size, &status)) != NULL) { result = demangled_name; free(demangled_name); } std::stringstream result_sstr; result_sstr << trace.substr(0, begin) << result << trace.substr(end); return result_sstr.str(); } return trace; } /* ------------------------------------------------------------------------ */ void printBacktrace(int sig) { AKANTU_DEBUG_INFO("Caught signal " << sig << "!"); void *array[10]; size_t size; char **strings; size_t i; size = backtrace (array, 10); strings = backtrace_symbols (array, size); std::cerr << "BACKTRACE : " << size - 1 << " stack frames." <<std::endl; /// -1 to remove the call to the printBacktrace function for (i = 1; i < size; i++) std::cerr << " " << demangle(strings[i]) << std::endl;; free (strings); std::cerr << "END BACKTRACE" << std::endl; // int * segfault = NULL; // *segfault = 0; } } __END_AKANTU__ diff --git a/common/aka_error.hh b/common/aka_error.hh index d4a92a355..e8624b975 100644 --- a/common/aka_error.hh +++ b/common/aka_error.hh @@ -1,220 +1,234 @@ /** * @file aka_error.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jun 14 11:43:22 2010 * * @brief error management and internal exceptions * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ERROR_HH__ #define __AKANTU_ERROR_HH__ /* -------------------------------------------------------------------------- */ #include <ostream> #include <sstream> #ifdef AKANTU_USE_MPI #include <mpi.h> #endif /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ enum DebugLevel { dbl0 = 0, dblError = 0, dblAssert = 0, dbl1 = 1, dblException = 1, dblCritical = 1, dbl2 = 2, dblMajor = 2, dbl3 = 3, dblCall = 3, dblSecondary = 3, dblHead = 3, dbl4 = 4, dblWarning = 4, dbl5 = 5, dblInfo = 5, dbl6 = 6, dblIn = 6, dblOut = 6, dbl7 = 7, dbl8 = 8, dblTrace = 8, dbl9 = 9, dblAccessory = 9, dbl10 = 10, dbl100 = 100, dblDump = 100 }; /* -------------------------------------------------------------------------- */ namespace debug { extern std::ostream & _akantu_cout; extern std::ostream & _akantu_debug_cout; extern DebugLevel _debug_level; extern std::string _parallel_context; void setDebugLevel(const DebugLevel & level); const DebugLevel & getDebugLevel(); void setParallelContext(int rank, int size); void initSignalHandler(); void printBacktrace(int sig); /* -------------------------------------------------------------------------- */ /// exception class that can be thrown by akantu class Exception : public std::exception { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: //! full constructor Exception(std::string info, std::string file, unsigned int line) : _info(info), _file(file), _line(line) { } //! destructor virtual ~Exception() throw() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual const char* what() const throw() { std::stringstream stream; stream << "akantu::Exception" << " : " << _info << " [" << _file << ":" << _line << "]"; return stream.str().c_str(); } virtual const char* info() const throw() { return _info.c_str(); } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// exception description and additionals std::string _info; /// file it is thrown from std::string _file; /// ligne it is thrown from unsigned int _line; }; } /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #define AKANTU_LOCATION "(" <<__FILE__ << ":" << __func__ << "():" << __LINE__ << ")" #ifndef AKANTU_USE_MPI #define AKANTU_EXIT(status) \ do { \ if (status != EXIT_SUCCESS) \ akantu::debug::printBacktrace(15); \ exit(status); \ } while(0) #else #define AKANTU_EXIT(status) \ do { \ if (status != EXIT_SUCCESS) \ akantu::debug::printBacktrace(15); \ MPI_Abort(MPI_COMM_WORLD, MPI_ERR_UNKNOWN); \ } while(0) #endif /* -------------------------------------------------------------------------- */ #define AKANTU_EXCEPTION(info) \ do { \ AKANTU_DEBUG(akantu::dblError, "!!! " << info); \ std::stringstream s_info; \ s_info << info ; \ ::akantu::debug::Exception ex(s_info.str(), __FILE__, __LINE__ ); \ throw ex; \ } while(0) /* -------------------------------------------------------------------------- */ #ifdef AKANTU_NDEBUG #define AKANTU_DEBUG_TEST(level) (0) #define AKANTU_DEBUG(level,info) #define AKANTU_DEBUG_IN() #define AKANTU_DEBUG_OUT() #define AKANTU_DEBUG_INFO(info) #define AKANTU_DEBUG_WARNING(info) #define AKANTU_DEBUG_TRACE(info) #define AKANTU_DEBUG_ASSERT(test,info) #define AKANTU_DEBUG_ERROR(info) AKANTU_EXCEPTION(info) /* -------------------------------------------------------------------------- */ #else #define AKANTU_DEBUG(level,info) \ ((::akantu::debug::_debug_level >= level) && \ (::akantu::debug::_akantu_debug_cout \ << ::akantu::debug::_parallel_context \ << info << " " \ << AKANTU_LOCATION \ << std::endl)) #define AKANTU_DEBUG_TEST(level) \ (::akantu::debug::_debug_level >= (level)) #define AKANTU_DEBUG_IN() \ AKANTU_DEBUG(::akantu::dblIn , "==> " << __func__ << "()") #define AKANTU_DEBUG_OUT() \ AKANTU_DEBUG(::akantu::dblOut , "<== " << __func__ << "()") #define AKANTU_DEBUG_INFO(info) \ AKANTU_DEBUG(::akantu::dblInfo , "--- " << info) #define AKANTU_DEBUG_WARNING(info) \ AKANTU_DEBUG(::akantu::dblWarning, "??? " << info) #define AKANTU_DEBUG_TRACE(info) \ AKANTU_DEBUG(::akantu::dblTrace , ">>> " << info) #define AKANTU_DEBUG_ASSERT(test,info) \ do { \ if (!(test)) { \ AKANTU_DEBUG(::akantu::dblAssert, "assert [" << #test << "] " \ << "!!! " << info); \ AKANTU_EXIT(EXIT_FAILURE); \ } \ } while(0) #define AKANTU_DEBUG_ERROR(info) \ do { \ AKANTU_DEBUG(::akantu::dblError, "!!! " << info); \ AKANTU_EXIT(EXIT_FAILURE); \ } while(0) #endif // AKANTU_NDEBUG /* -------------------------------------------------------------------------- */ __END_AKANTU__ #endif /* __AKANTU_ERROR_HH__ */ // LocalWords: acessory diff --git a/common/aka_extern.cc b/common/aka_extern.cc index 52c941ecd..52088e592 100644 --- a/common/aka_extern.cc +++ b/common/aka_extern.cc @@ -1,48 +1,62 @@ /** * @file aka_extern.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jun 14 14:34:14 2010 * * @brief initialisation of all global variables * to insure the order of creation * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <ostream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /** \todo write function to get this * values from the environment or a config file */ /* -------------------------------------------------------------------------- */ /* error.hpp variables */ /* -------------------------------------------------------------------------- */ namespace debug { /// standard output for debug messages std::ostream & _akantu_debug_cout = std::cerr; /// standard output for normal messages std::ostream & _akantu_cout = std::cout; /// debug level DebugLevel _debug_level = (DebugLevel) 5; /// parallel context used in debug messages std::string _parallel_context = ""; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/common/aka_math.cc b/common/aka_math.cc index 0bb95bda7..448b23377 100644 --- a/common/aka_math.cc +++ b/common/aka_math.cc @@ -1,113 +1,127 @@ /** * @file aka_math.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Jul 28 12:13:46 2010 * * @brief Implementation of the math toolbox * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_math.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void Math::matrix_vector(UInt m, UInt n, const Vector<Real> & A, const Vector<Real> & x, Vector<Real> & y) { 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.values; Real * x_val = x.values; Real * y_val = y.values; for (UInt el = 0; el < nb_element; ++el) { matrix_vector(m, n, A_val, x_val, y_val); 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 Vector<Real> & A, const Vector<Real> & B, Vector<Real> & C) { 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.values; Real * B_val = B.values; Real * C_val = C.values; for (UInt el = 0; el < nb_element; ++el) { matrix_matrix(m, n, k, A_val, B_val, C_val); A_val += offset_A; B_val += offset_B; C_val += offset_C; } AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/common/aka_math.hh b/common/aka_math.hh index 17a8ace94..9a97000bd 100644 --- a/common/aka_math.hh +++ b/common/aka_math.hh @@ -1,163 +1,177 @@ /** * @file aka_math.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Jul 28 11:51:56 2010 * * @brief mathematical operations * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_AKA_MATH_H__ #define __AKANTU_AKA_MATH_H__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_vector.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class Math { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Matrix algebra */ /* ------------------------------------------------------------------------ */ /// @f$ y = A*x @f$ static void matrix_vector(UInt m, UInt n, const Vector<Real> & A, const Vector<Real> & x, Vector<Real> & y); /// @f$ y = A*x @f$ static inline void matrix_vector(UInt m, UInt n, const Real * A, const Real * x, Real * y); /// @f$ C = A*B @f$ static void matrix_matrix(UInt m, UInt n, UInt k, const Vector<Real> & A, const Vector<Real> & B, Vector<Real> & C); /// @f$ C = A*B @f$ static inline void matrix_matrix(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C); /// @f$ C = A^t*B @f$ static inline void matrixt_matrix(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C); /// @f$ C = A*B^t @f$ static inline void matrix_matrixt(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C); /// @f$ C = A^t*B^t @f$ static inline void matrixt_matrixt(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C); /// determinent of a 3x3 matrix static inline Real det3(const Real * mat); /// determinent of a 2x2 matrix static inline Real det2(const Real * mat); /// inverse a 3x3 matrix static inline void inv3(const Real * mat, Real * inv); /// inverse a 2x2 matrix static inline void inv2(const Real * mat, Real * inv); /// vector 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 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); /* ------------------------------------------------------------------------ */ /* Geometry */ /* ------------------------------------------------------------------------ */ /// distance in 2D between x and y static inline Real distance_2d(const Real * x, const Real * y); /// distance in 3D between x and y static inline Real distance_3d(const Real * x, const Real * y); /// radius of the in-circle of a triangle static inline Real triangle_inradius(const Real * coord1, const Real * coord2, const Real * coord3); /// radius of the in-circle of a tetrahedron static inline Real tetrahedron_inradius(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4); /// volume of a tetrahedron static inline Real tetrahedron_volume(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4); /// compute the barycenter of n points static inline void barycenter(const Real * coord, UInt nb_points, UInt spatial_dimension, Real * barycenter); /// vector between x and y static inline void vector_2d(const Real * x, const Real * y, Real * vec); /// vector pointing from x to y in 3 spatial dimension static inline void vector_3d(const Real * x, const Real * y, Real * vec); }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "aka_math_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_AKA_MATH_H__ */ diff --git a/common/aka_math_inline_impl.cc b/common/aka_math_inline_impl.cc index 2b21051c9..8c7bbb121 100644 --- a/common/aka_math_inline_impl.cc +++ b/common/aka_math_inline_impl.cc @@ -1,373 +1,387 @@ /** * @file aka_math_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Jul 28 13:20:35 2010 * * @brief Implementation of the inline functions of the math toolkit * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ #ifdef AKANTU_USE_CBLAS # ifndef AKANTU_USE_CBLAS_MKL # include <cblas.h> # else // AKANTU_USE_CBLAS_MKL # include <mkl_cblas.h> # endif //AKANTU_USE_CBLAS_MKL #endif //AKANTU_USE_CBLAS /* -------------------------------------------------------------------------- */ inline void Math::matrix_vector(UInt m, UInt n, const Real * A, const Real * x, Real * y) { #ifdef AKANTU_USE_CBLAS /// y = alpha*op(A)*x + beta*y cblas_dgemv(CblasRowMajor, CblasNoTrans, m, n, 1, A, n, x, 1, 0, y, 1); #else memset(y, 0, m*sizeof(Real)); for (UInt i = 0; i < m; ++i) { UInt A_i = i * n; for (UInt j = 0; j < n; ++j) { y[i] += A[A_i + j] * x[j]; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrix_matrix(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C) { #ifdef AKANTU_USE_CBLAS /// C := alpha*op(A)*op(B) + beta*C cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, n, k, 1, A, k, B, n, 0, C, n); #else memset(C, 0, m*n*sizeof(Real)); for (UInt i = 0; i < m; ++i) { UInt A_i = i * k; UInt C_i = i * n; for (UInt j = 0; j < n; ++j) { for (UInt l = 0; l < k; ++l) { C[C_i + j] += A[A_i + l] * B[l * n + j]; } } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_matrix(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C) { #ifdef AKANTU_USE_CBLAS /// C := alpha*op(A)*op(B) + beta*C cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans, m, n, k, 1, A, m, B, n, 0, C, n); #else memset(C, 0, m*n*sizeof(Real)); for (UInt i = 0; i < m; ++i) { // UInt A_i = i * k; UInt C_i = i * n; for (UInt j = 0; j < n; ++j) { for (UInt l = 0; l < k; ++l) { C[C_i + j] += A[l * m + i] * B[l * n + j]; } } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrix_matrixt(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C) { #ifdef AKANTU_USE_CBLAS /// C := alpha*op(A)*op(B) + beta*C cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, m, n, k, 1, A, k, B, k, 0, C, n); #else memset(C, 0, m*n*sizeof(Real)); for (UInt i = 0; i < m; ++i) { UInt A_i = i * k; UInt C_i = i * n; for (UInt j = 0; j < n; ++j) { UInt B_j = j * k; for (UInt l = 0; l < k; ++l) { C[C_i + j] += A[A_i + l] * B[B_j + l]; } } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_matrixt(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C) { #ifdef AKANTU_USE_CBLAS /// C := alpha*op(A)*op(B) + beta*C cblas_dgemm(CblasRowMajor, CblasTrans, CblasTrans, m, n, k, 1, A, m, B, k, 0, C, n); #else memset(C, 0, m * n * sizeof(Real)); for (UInt i = 0; i < m; ++i) { UInt C_i = i * n; for (UInt j = 0; j < n; ++j) { UInt B_j = j * k; for (UInt l = 0; l < k; ++l) { C[C_i + j] += A[l * m + i] * B[B_j + l]; } } } #endif } /* -------------------------------------------------------------------------- */ inline Real Math::det2(const Real * mat) { return mat[0]*mat[3] - mat[1]*mat[2]; } /* -------------------------------------------------------------------------- */ inline Real Math::det3(const Real * mat) { return mat[0]*(mat[4]*mat[8]-mat[7]*mat[5]) - mat[3]*(mat[1]*mat[8]-mat[7]*mat[2]) + mat[6]*(mat[1]*mat[5]-mat[4]*mat[2]); } /* -------------------------------------------------------------------------- */ inline void Math::normal2(const Real * vec,Real * normal) { normal[0] = vec[1]; normal[1] = -vec[0]; Math::normalize2(normal); } /* -------------------------------------------------------------------------- */ inline void Math::normal3(const Real * vec1,const Real * vec2,Real * normal) { Math::vectorProduct3(vec1,vec2,normal); Math::normalize3(normal); } /* -------------------------------------------------------------------------- */ inline void Math::normalize2(Real * vec) { Real norm = Math::norm2(vec); vec[0] /= norm; vec[1] /= norm; } /* -------------------------------------------------------------------------- */ inline void Math::normalize3(Real * vec) { Real norm = Math::norm3(vec); vec[0] /= norm; vec[1] /= norm; vec[2] /= norm; } /* -------------------------------------------------------------------------- */ inline Real Math::norm2(const Real * vec) { return sqrt(vec[0]*vec[0] + vec[1]*vec[1]); } /* -------------------------------------------------------------------------- */ inline Real Math::norm3(const Real * vec) { return sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); } /* -------------------------------------------------------------------------- */ inline void Math::inv2(const Real * mat,Real * inv) { Real det_mat = det2(mat); inv[0] = mat[3] / det_mat; inv[1] = -mat[1] / det_mat; inv[2] = -mat[2] / det_mat; inv[3] = mat[0] / det_mat; } /* -------------------------------------------------------------------------- */ inline void Math::inv3(const Real * mat,Real * inv) { Real det_mat = det3(mat); inv[0] = (mat[4]*mat[8] - mat[7]*mat[5])/det_mat; inv[1] = (mat[2]*mat[7] - mat[8]*mat[1])/det_mat; inv[2] = (mat[1]*mat[5] - mat[4]*mat[2])/det_mat; inv[3] = (mat[5]*mat[6] - mat[8]*mat[3])/det_mat; inv[4] = (mat[0]*mat[8] - mat[6]*mat[2])/det_mat; inv[5] = (mat[2]*mat[3] - mat[5]*mat[0])/det_mat; inv[6] = (mat[3]*mat[7] - mat[6]*mat[4])/det_mat; inv[7] = (mat[1]*mat[6] - mat[7]*mat[0])/det_mat; inv[8] = (mat[0]*mat[4] - mat[3]*mat[1])/det_mat; } /* -------------------------------------------------------------------------- */ inline void Math::vectorProduct3(const Real * v1, const Real * v2, Real * res) { res[0] = v1[1]*v2[2] - v1[2]*v2[1]; res[1] = v1[2]*v2[0] - v1[0]*v2[2]; res[2] = v1[0]*v2[1] - v1[1]*v2[0]; } /* -------------------------------------------------------------------------- */ inline Real Math::vectorDot2(const Real * v1, const Real * v2) { return (v1[0]*v2[0] + v1[1]*v2[1]); } /* -------------------------------------------------------------------------- */ inline Real Math::vectorDot3(const Real * v1, const Real * v2) { return (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]); } /* -------------------------------------------------------------------------- */ inline Real Math::distance_2d(const Real * x, const Real * y) { return sqrt((y[0] - x[0])*(y[0] - x[0]) + (y[1] - x[1])*(y[1] - x[1])); } /* -------------------------------------------------------------------------- */ inline Real Math::triangle_inradius(const Real * coord1, const Real * coord2, const Real * coord3) { /** * @f{eqnarray*}{ * r &=& A / s \\ * A &=& 1/4 * \sqrt{(a + b + c) * (a - b + c) * (a + b - c) (-a + b + c)} \\ * s &=& \frac{a + b + c}{2} * @f} */ Real a, b, c; a = distance_2d(coord1, coord2); b = distance_2d(coord2, coord3); c = distance_2d(coord1, coord3); Real s; s = (a + b + c) * 0.5; return sqrt((s - a) * (s - b) * (s - c) / s); } /* -------------------------------------------------------------------------- */ inline Real Math::distance_3d(const Real * x, const Real * y) { return sqrt((y[0] - x[0])*(y[0] - x[0]) + (y[1] - x[1])*(y[1] - x[1]) + (y[2] - x[2])*(y[2] - x[2]) ); } /* -------------------------------------------------------------------------- */ inline Real Math::tetrahedron_volume(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4) { Real xx[9], vol; xx[0] = coord2[0]; xx[1] = coord2[1]; xx[2] = coord2[2]; xx[3] = coord3[0]; xx[4] = coord3[1]; xx[5] = coord3[2]; xx[6] = coord4[0]; xx[7] = coord4[1]; xx[8] = coord4[2]; vol = det3(xx); xx[0] = coord1[0]; xx[1] = coord1[1]; xx[2] = coord1[2]; xx[3] = coord3[0]; xx[4] = coord3[1]; xx[5] = coord3[2]; xx[6] = coord4[0]; xx[7] = coord4[1]; xx[8] = coord4[2]; vol -= det3(xx); xx[0] = coord1[0]; xx[1] = coord1[1]; xx[2] = coord1[2]; xx[3] = coord2[0]; xx[4] = coord2[1]; xx[5] = coord2[2]; xx[6] = coord4[0]; xx[7] = coord4[1]; xx[8] = coord4[2]; vol += det3(xx); xx[0] = coord1[0]; xx[1] = coord1[1]; xx[2] = coord1[2]; xx[3] = coord2[0]; xx[4] = coord2[1]; xx[5] = coord2[2]; xx[6] = coord3[0]; xx[7] = coord3[1]; xx[8] = coord3[2]; vol -= det3(xx); vol /= 6; return vol; } /* -------------------------------------------------------------------------- */ inline Real Math::tetrahedron_inradius(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4) { Real l12, l13, l14, l23, l24, l34; l12 = distance_3d(coord1, coord2); l13 = distance_3d(coord1, coord3); l14 = distance_3d(coord1, coord4); l23 = distance_3d(coord2, coord3); l24 = distance_3d(coord2, coord4); l34 = distance_3d(coord3, coord4); Real s1, s2, s3, s4; s1 = (l12 + l23 + l13) * 0.5; s1 = sqrt(s1*(s1-l12)*(s1-l23)*(s1-l13)); s2 = (l12 + l24 + l14) * 0.5; s2 = sqrt(s2*(s2-l12)*(s2-l24)*(s2-l14)); s3 = (l23 + l34 + l24) * 0.5; s3 = sqrt(s3*(s3-l23)*(s3-l34)*(s3-l24)); s4 = (l13 + l34 + l24) * 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]; } diff --git a/common/aka_memory.cc b/common/aka_memory.cc index ad54adc2c..7c3c22434 100644 --- a/common/aka_memory.cc +++ b/common/aka_memory.cc @@ -1,46 +1,60 @@ /** * @file aka_memory.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jun 15 11:15:53 2010 * * @brief static memory wrapper * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Memory::Memory(MemoryID memory_id) { static_memory = StaticMemory::getStaticMemory(); this->memory_id = memory_id; } /* -------------------------------------------------------------------------- */ Memory::~Memory() { if(StaticMemory::isInstantiated()) { std::list<VectorID>::iterator it; for (it = handeld_vectors_id.begin(); it != handeld_vectors_id.end(); ++it) { AKANTU_DEBUG(dblAccessory, "Deleting the vector " << *it); static_memory->sfree(memory_id, *it); } } handeld_vectors_id.clear(); static_memory->destroy(); static_memory = NULL; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/common/aka_memory.hh b/common/aka_memory.hh index b086f01a3..c7f75c606 100644 --- a/common/aka_memory.hh +++ b/common/aka_memory.hh @@ -1,96 +1,110 @@ /** * @file aka_memory.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jun 15 09:30:23 2010 * * @brief wrapper for the static_memory, all object which wants * to access the ststic_memory as to inherit from the class memory * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MEMORY_HH__ #define __AKANTU_MEMORY_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_static_memory.hh" #include "aka_vector.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Memory(MemoryID memory_id = 0); virtual ~Memory(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// malloc template<class T> inline Vector<T> & alloc(const VectorID & name, UInt size, UInt nb_component); /// malloc template<class T> inline Vector<T> & alloc(const VectorID & name, UInt size, UInt nb_component, const T & init_value); /* ------------------------------------------------------------------------ */ /// free an array inline void dealloc(const VectorID & name); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(MemoryID, memory_id, const MemoryID &); template<class T> inline Vector<T> & getVector(const VectorID & name); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// the static memory instance StaticMemory * static_memory; protected: /// the id registred in the static memory MemoryID memory_id; /// list of allocated vectors id std::list<VectorID> handeld_vectors_id; }; /* -------------------------------------------------------------------------- */ /* Inline functions */ /* -------------------------------------------------------------------------- */ #include "aka_memory_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_MEMORY_HH__ */ diff --git a/common/aka_memory_inline_impl.cc b/common/aka_memory_inline_impl.cc index 945975353..65f0a3a74 100644 --- a/common/aka_memory_inline_impl.cc +++ b/common/aka_memory_inline_impl.cc @@ -1,43 +1,57 @@ /** * @file aka_memory_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jul 15 00:22:48 2010 * * @brief Implementation of the inline functions of the class Memory * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ template<class T> inline Vector<T> & Memory::alloc(const VectorID & name, UInt size, UInt nb_component) { handeld_vectors_id.push_back(name); return static_memory->smalloc<T>(memory_id, name, size, nb_component); } /* -------------------------------------------------------------------------- */ template<class T> inline Vector<T> & Memory::alloc(const VectorID & name, UInt size, UInt nb_component, const T & init_value) { handeld_vectors_id.push_back(name); return static_memory->smalloc<T>(memory_id, name, size, nb_component, init_value); } /* -------------------------------------------------------------------------- */ inline void Memory::dealloc(const VectorID & name) { AKANTU_DEBUG(dblAccessory, "Deleting the vector " << name); static_memory->sfree(memory_id, name); handeld_vectors_id.remove(name); } /* -------------------------------------------------------------------------- */ template<class T> inline Vector<T> & Memory::getVector(const VectorID & name) { return static_cast< Vector<T> & >(const_cast<VectorBase &>(static_memory->getVector(memory_id, name))); } diff --git a/common/aka_static_memory.cc b/common/aka_static_memory.cc index 9353d839b..0e3be343f 100644 --- a/common/aka_static_memory.cc +++ b/common/aka_static_memory.cc @@ -1,138 +1,152 @@ /** * @file aka_static_memory.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jun 10 14:42:37 2010 * * @brief Memory management * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <stdexcept> #include <sstream> /* -------------------------------------------------------------------------- */ #include "aka_static_memory.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ bool StaticMemory::is_instantiated = false; StaticMemory * StaticMemory::single_static_memory = NULL; UInt StaticMemory::nb_reference = 0; /* -------------------------------------------------------------------------- */ StaticMemory * StaticMemory::getStaticMemory() { if(!single_static_memory) { single_static_memory = new StaticMemory(); is_instantiated = true; } nb_reference++; return single_static_memory; } /* -------------------------------------------------------------------------- */ void StaticMemory::destroy() { nb_reference--; if(nb_reference == 0) { delete single_static_memory; } } /* -------------------------------------------------------------------------- */ StaticMemory::~StaticMemory() { AKANTU_DEBUG_IN(); MemoryMap::iterator memory_it; for(memory_it = memories.begin(); memory_it != memories.end(); ++memory_it) { VectorMap::iterator vector_it; for(vector_it = (memory_it->second).begin(); vector_it != (memory_it->second).end(); ++vector_it) { delete vector_it->second; } (memory_it->second).clear(); } memories.clear(); is_instantiated = false; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StaticMemory::sfree(const MemoryID & memory_id, const VectorID & name) { AKANTU_DEBUG_IN(); try { VectorMap & vectors = const_cast<VectorMap &>(getMemory(memory_id)); VectorMap::iterator vector_it; vector_it = vectors.find(name); if(vector_it != vectors.end()) { delete vector_it->second; vectors.erase(vector_it); AKANTU_DEBUG_INFO("Vector " << name << " removed from the static memory number " << memory_id); AKANTU_DEBUG_OUT(); return; } } catch (debug::Exception e) { AKANTU_DEBUG_INFO("The memory " << memory_id << " does not exist (perhaps already freed) [" << e.what() << "]"); AKANTU_DEBUG_OUT(); return; } AKANTU_DEBUG_INFO("The vector " << name << " does not exist (perhaps already freed)"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void StaticMemory::printself(std::ostream & stream, int indent) const{ std::string space = ""; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); std::streamsize prec = stream.precision(); stream.precision(2); stream << space << "StaticMemory [" << std::endl; UInt nb_memories = memories.size(); stream << space << " + nb memories : " << nb_memories << std::endl; Real tot_size = 0; MemoryMap::const_iterator memory_it; for(memory_it = memories.begin(); memory_it != memories.end(); ++memory_it) { Real mem_size = 0; stream << space << AKANTU_INDENT << "Memory [" << std::endl; UInt mem_id = memory_it->first; stream << space << AKANTU_INDENT << " + memory id : " << mem_id << std::endl; UInt nb_vectors = (memory_it->second).size(); stream << space << AKANTU_INDENT << " + nb vectors : " << nb_vectors << std::endl; stream.precision(prec); VectorMap::const_iterator vector_it; for(vector_it = (memory_it->second).begin(); vector_it != (memory_it->second).end(); ++vector_it) { (vector_it->second)->printself(stream, indent + 2); mem_size += (vector_it->second)->getMemorySize() / 1024.; } stream.precision(2); stream << space << AKANTU_INDENT << " + total size : " << mem_size << "kB" << std::endl; stream << space << AKANTU_INDENT << "]" << std::endl; tot_size += mem_size; } stream << space << " + total size : " << tot_size << "kB" << std::endl; stream << space << "]" << std::endl; stream.precision(prec); } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/common/aka_static_memory.hh b/common/aka_static_memory.hh index 8497b5f1e..d9c25bfc4 100644 --- a/common/aka_static_memory.hh +++ b/common/aka_static_memory.hh @@ -1,143 +1,157 @@ /** * @file aka_static_memory.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jun 10 14:19:25 2010 * * @brief Memory management * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * * @section DESCRIPTION * * The class handling the memory, allocation/reallocation/desallocation * The objects can register their array and ask for allocation or realocation */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_STATIC_MEMORY_HH__ #define __AKANTU_STATIC_MEMORY_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_vector.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ typedef std::map<VectorID, VectorBase *> VectorMap; typedef std::map<MemoryID, VectorMap> MemoryMap; /** * @class StaticMemory * @brief Class for memory management common to all objects (this class as to * be accessed by an interface class memory) */ class StaticMemory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ private: /// Default constructor StaticMemory() {}; public: virtual ~StaticMemory(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// Get the global instance of the StaticMemory static StaticMemory * getStaticMemory(); static bool isInstantiated() { return is_instantiated; }; /// remove a reference on the static memory void destroy(); /// access to an Vector inline const VectorBase & getVector(const MemoryID & memory_id, const VectorID & name) const; /// get all vectors of a memory inline const VectorMap & getMemory(const MemoryID & memory_id) const; /* ------------------------------------------------------------------------ */ /* Class Methods */ /* ------------------------------------------------------------------------ */ public: /** * Allocation of an array of type * * @param memory_id the id of the memory accessing to the static memory * @param name name of the array (for example connectivity) * @param size number of size (for example number of nodes) * @param nb_component number of component (for example spatial dimension) * @param type the type code of the array to be allocated * * @return pointer to an array of size nb_tupes * nb_component * sizeof(T) */ template<typename T> Vector<T> & smalloc(const MemoryID & memory_id, const VectorID & name, UInt size, UInt nb_component); template<typename T> Vector<T> & smalloc(const MemoryID & memory_id, const VectorID & name, UInt size, UInt nb_component, const T & init_value); /** * free the memory associated to the array name * * @param memory_id the id of the memory accessing to the static memory * @param name the name of an existing array */ void sfree(const MemoryID & memory_id, const VectorID & name); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// is the static memory instantiated static bool is_instantiated; /// unique instance of the StaticMemory static StaticMemory * single_static_memory; /// map of all allocated arrays, indexed by their names MemoryMap memories; /// number of references on the static memory static UInt nb_reference; }; #include "aka_static_memory_inline_impl.cc" /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const StaticMemory & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_STATIC_MEMORY_HH__ */ diff --git a/common/aka_static_memory_inline_impl.cc b/common/aka_static_memory_inline_impl.cc index ace503ba1..90630a12e 100644 --- a/common/aka_static_memory_inline_impl.cc +++ b/common/aka_static_memory_inline_impl.cc @@ -1,99 +1,113 @@ /** * @file aka_static_memory_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jul 15 00:32:05 2010 * * @brief Implementation of inline functions of the class StaticMemory * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ inline const VectorMap & StaticMemory::getMemory(const MemoryID & memory_id) const { AKANTU_DEBUG_IN(); MemoryMap::const_iterator memory_it; memory_it = memories.find(memory_id); if(memory_it == memories.end()) { AKANTU_EXCEPTION("StaticMemory as no memory with ID " << memory_id); } AKANTU_DEBUG_OUT(); return memory_it->second; } /* -------------------------------------------------------------------------- */ inline const VectorBase & StaticMemory::getVector(const MemoryID & memory_id, const VectorID & name) const { AKANTU_DEBUG_IN(); const VectorMap & vectors = getMemory(memory_id); VectorMap::const_iterator vectors_it; vectors_it = vectors.find(name); if(vectors_it == vectors.end()) { AKANTU_EXCEPTION("StaticMemory as no array named " << name << " for the Memory " << memory_id); } AKANTU_DEBUG_OUT(); return *(vectors_it->second); } /* -------------------------------------------------------------------------- */ template<typename T> Vector<T> & StaticMemory::smalloc(const MemoryID & memory_id, const VectorID & name, UInt size, UInt nb_component) { AKANTU_DEBUG_IN(); MemoryMap::iterator memory_it; memory_it = memories.find(memory_id); if(memory_it == memories.end()){ memories[memory_id] = VectorMap(); memory_it = memories.find(memory_id); } if((memory_it->second).find(name) != (memory_it->second).end()) { AKANTU_DEBUG_ERROR("The vector \"" << name << "\" is already registred in the memory " << memory_id); } Vector<T> * tmp_vect = new Vector<T>(size, nb_component, name); (memory_it->second)[name] = dynamic_cast<VectorBase *>(tmp_vect); AKANTU_DEBUG_OUT(); return *tmp_vect; } /* -------------------------------------------------------------------------- */ template<typename T> Vector<T> & StaticMemory::smalloc(const MemoryID & memory_id, const VectorID & name, UInt size, UInt nb_component, const T & init_value) { AKANTU_DEBUG_IN(); MemoryMap::iterator memory_it; memory_it = memories.find(memory_id); if(memory_it == memories.end()){ memories[memory_id] = VectorMap(); memory_it = memories.find(memory_id); } if((memory_it->second).find(name) != (memory_it->second).end()) { AKANTU_DEBUG_ERROR("The vector \"" << name << "\" is already registred in the memory " << memory_id); } Vector<T> * tmp_vect = new Vector<T>(size, nb_component, init_value, name); (memory_it->second)[name] = dynamic_cast<VectorBase *>(tmp_vect); AKANTU_DEBUG_OUT(); return *tmp_vect; } /* -------------------------------------------------------------------------- */ diff --git a/common/aka_vector.cc b/common/aka_vector.cc index e93c86495..e39f6684a 100644 --- a/common/aka_vector.cc +++ b/common/aka_vector.cc @@ -1,309 +1,323 @@ /** * @file aka_vector.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jun 17 15:14:24 2010 * * @brief class vector * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_vector.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Functions VectorBase */ /* -------------------------------------------------------------------------- */ VectorBase::VectorBase(const VectorID & id) : id(id), allocated_size(0), size(0), nb_component(1), size_of_type(0) { } /* -------------------------------------------------------------------------- */ VectorBase::~VectorBase() { } /* -------------------------------------------------------------------------- */ void VectorBase::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "VectorBase [" << std::endl; stream << space << " + size : " << size << std::endl; stream << space << " + nb component : " << nb_component << std::endl; stream << space << " + allocated size : " << allocated_size << std::endl; Real mem_size = (allocated_size * nb_component * size_of_type) / 1024.; stream << space << " + size of type : " << size_of_type << "B" << std::endl; stream << space << " + memory allocated : " << mem_size << "kB" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ /* Functions Vector<T> */ /* -------------------------------------------------------------------------- */ template <class T> Vector<T>::Vector (UInt size, UInt nb_component, const VectorID & id) : VectorBase(id), values(NULL) { AKANTU_DEBUG_IN(); allocate(size, nb_component); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T> Vector<T>::Vector (UInt size, UInt nb_component, const T def_values[], const VectorID & id) : VectorBase(id), values(NULL) { AKANTU_DEBUG_IN(); allocate(size, nb_component); for (UInt i = 0; i < size; ++i) { for (UInt j = 0; j < nb_component; ++j) { values[i*nb_component + j] = def_values[j]; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T> Vector<T>::Vector (UInt size, UInt nb_component, const T & value, const VectorID & id) : VectorBase(id), values(NULL) { AKANTU_DEBUG_IN(); allocate(size, nb_component); for (UInt i = 0; i < nb_component*size; ++i) { values[i] = value; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T> Vector<T>::Vector(const Vector<T>& vect, bool deep) { AKANTU_DEBUG_IN(); this->id = vect.id; if (deep) { allocate(vect.size, vect.nb_component); for (UInt i = 0; i < size; ++i) { for (UInt j = 0; j < nb_component; ++j) { values[i*nb_component + j] = vect.values[i*nb_component + j]; } } } else { this->values = vect.values; this->size = vect.size; this->nb_component = vect.nb_component; this->allocated_size = vect.allocated_size; this->size_of_type = vect.size_of_type; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T> Vector<T>::~Vector () { AKANTU_DEBUG_IN(); AKANTU_DEBUG(dblAccessory, "Freeing " << allocated_size*nb_component*sizeof(T) / 1024. << "kB (" << id <<")"); if(values) free(values); size = allocated_size = 0; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T> void Vector<T>::allocate(UInt size, UInt nb_component) { AKANTU_DEBUG_IN(); if (size == 0){ values = NULL; } else { values = static_cast<T*>(malloc(nb_component * size * sizeof(T))); AKANTU_DEBUG_ASSERT(values != NULL, "Cannot allocate " << nb_component * size * sizeof(T) / 1024. << "kB (" << id <<")"); } if (values == NULL) { this->size = this->allocated_size = 0; } else { AKANTU_DEBUG(dblAccessory, "Allocated " << size * nb_component * sizeof(T) / 1024. << "kB (" << id <<")"); this->size = this->allocated_size = size; } this->size_of_type = sizeof(T); this->nb_component = nb_component; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T> void Vector<T>::resize(UInt new_size) { AKANTU_DEBUG_IN(); /// free some memory if(new_size <= allocated_size) { if(allocated_size - new_size > AKANTU_MIN_ALLOCATION) { AKANTU_DEBUG(dblAccessory, "Freeing " << (allocated_size - size)*nb_component*sizeof(T) / 1024. << "kB (" << id <<")"); /// Normally there are no allocation problem when reducing an array T * tmp_ptr = static_cast<T*>(realloc(values, new_size * nb_component * sizeof(T))); if(new_size != 0 && tmp_ptr == NULL) { AKANTU_DEBUG_ERROR("Cannot free data (" << id << ")" << " [current allocated size : " << allocated_size << " | " << "requested size : " << new_size << "]"); } values = tmp_ptr; allocated_size = new_size; } size = new_size; AKANTU_DEBUG_OUT(); return; } /// allocate more memory UInt size_to_alloc = (new_size - allocated_size < AKANTU_MIN_ALLOCATION) ? allocated_size + AKANTU_MIN_ALLOCATION : new_size; T *tmp_ptr = static_cast<T*>(realloc(values, size_to_alloc * nb_component * sizeof(T))); AKANTU_DEBUG_ASSERT(tmp_ptr != NULL, "Cannot allocate " << size_to_alloc * nb_component * sizeof(T) / 1024. << "kB"); if (tmp_ptr == NULL) { AKANTU_DEBUG_ERROR("Cannot allocate more data (" << id << ")" << " [current allocated size : " << allocated_size << " | " << "requested size : " << new_size << "]"); } AKANTU_DEBUG(dblAccessory, "Allocating " << (size_to_alloc - allocated_size)*nb_component*sizeof(T) / 1024. << "kB"); allocated_size = size_to_alloc; size = new_size; values = tmp_ptr; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T> void Vector<T>::extendComponentsInterlaced(UInt multiplicator, UInt stride) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(multiplicator > 1, "you can only extend a vector by changing the number of components"); AKANTU_DEBUG_ASSERT(nb_component%stride == 0, "stride must divide actual number of components"); values = static_cast<T*>(realloc(values, nb_component*multiplicator*size* sizeof(T))); UInt strided_component = nb_component/stride; UInt new_component = strided_component * multiplicator; for (UInt i = 0,k=size-1; i < size; ++i,--k) { for (UInt j = 0; j < new_component; ++j) { UInt m = new_component - j -1; UInt n = m*strided_component/new_component; for (UInt l = 0,p=stride-1; l < stride; ++l,--p) { values[k*new_component*stride+m*stride+p] = values[k*strided_component*stride+n*stride+p]; } } } nb_component = new_component*stride; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T> Int Vector<T>::find(const T & elem) const { AKANTU_DEBUG_IN(); UInt i = 0; for (; (i < size) && (values[i] != elem); ++i); AKANTU_DEBUG_OUT(); return (i == size) ? -1 : (Int) i; } /* -------------------------------------------------------------------------- */ template <> Int Vector<Real>::find(const Real & elem) const { AKANTU_DEBUG_IN(); UInt i = 0; Real epsilon = std::numeric_limits<Real>::epsilon(); for (; (i < size) && (fabs(values[i] - elem) <= epsilon); ++i); AKANTU_DEBUG_OUT(); return (i == size) ? -1 : (Int) i; } /* -------------------------------------------------------------------------- */ template <class T> void Vector<T>::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); Real real_size = allocated_size * nb_component * size_of_type / 1024.0; std::streamsize prec = stream.precision(); std::ios_base::fmtflags ff = stream.flags(); stream.setf (std::ios_base::showbase); stream.precision(2); stream << space << "Vector<" << typeid(T).name() << "> [" << std::endl; stream << space << " + id : " << this->id << std::endl; stream << space << " + size : " << this->size << std::endl; stream << space << " + nb_component : " << this->nb_component << std::endl; stream << space << " + allocated size : " << this->allocated_size << std::endl; stream << space << " + memory size : " << real_size << "kB" << std::endl; stream << space << " + address : " << std::hex << this->values << std::dec << std::endl; stream.precision(prec); stream.flags(ff); if(AKANTU_DEBUG_TEST(dblDump)) { stream << space << " + values : {"; for (UInt i = 0; i < this->size; ++i) { stream << "{"; for (UInt j = 0; j < this->nb_component; ++j) { stream << this->values[i*nb_component + j]; if(j != this->nb_component - 1) stream << ", "; } stream << "}"; if(i != this->size - 1) stream << ", "; } stream << "}" << std::endl; } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ class MaterialBase; template class Vector<Int>; template class Vector<UInt>; template class Vector<Real>; template class Vector<bool>; __END_AKANTU__ diff --git a/common/aka_vector.hh b/common/aka_vector.hh index dece15897..c46f740d5 100644 --- a/common/aka_vector.hh +++ b/common/aka_vector.hh @@ -1,194 +1,208 @@ /** * @file aka_vector.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jun 17 10:04:55 2010 * * @brief class of vectors * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_VECTOR_HH__ #define __AKANTU_VECTOR_HH__ /* -------------------------------------------------------------------------- */ #include <typeinfo> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /// class that afford to store vectors in static memory class VectorBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: VectorBase(const VectorID & id = ""); virtual ~VectorBase(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// get the amount of space allocated in bytes inline UInt getMemorySize() const; /// set the size to zero without freeing the allocated space inline void empty(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(AllocatedSize, allocated_size, UInt); AKANTU_GET_MACRO(Size, size, UInt); AKANTU_GET_MACRO(NbComponent, nb_component, UInt); AKANTU_GET_MACRO(ID, id, const VectorID &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the vector VectorID 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; }; /* -------------------------------------------------------------------------- */ template<class T> class Vector : public VectorBase { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /// Allocation of a new vector Vector(UInt size = 0, UInt nb_component = 1, const VectorID & id = ""); /// Allocation of a new vector with a default value Vector(UInt size, UInt nb_component, const T def_values[], const VectorID & id = ""); /// Allocation of a new vector with a default value Vector(UInt size, UInt nb_component, const T & value, const VectorID & id = ""); /// Copy constructor (deep copy if deep=true) \todo to implement Vector(const Vector<T>& vect, bool deep = true); virtual ~Vector(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// get jth componemt of the ith tuple in read-only inline const T & get(UInt i, UInt j = 0) const; /// get jth componemt of the ith tuple inline T & at(UInt i, UInt j = 0); /// add an element at the and of the vector with the value value for all /// component inline void push_back(const T& value); /// add an element at the and of the vector inline void push_back(const T new_elem[]); /** * remove an element and move the last one in the hole * /!\ change the order in the vector */ inline void erase(UInt i); /// change the size of the vector and allocate more memory if needed void resize(UInt size); /// change the number of components by interlacing data void extendComponentsInterlaced(UInt multiplicator,UInt stride); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; // Vector<T>& operator=(const Vector<T>& vect); /// search elem in the vector, return the position of the first occurrence or /// -1 if not found Int find(const T & elem) const; protected: /// perform the allocation for the constructors void allocate(UInt size, UInt nb_component = 1); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: UInt getSize() const{ return this->size; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ public: /// array of values T *values; // /!\ very dangerous }; #include "aka_vector_inline_impl.cc" /* -------------------------------------------------------------------------- */ /* Inline Functions Vector<T> */ /* -------------------------------------------------------------------------- */ template <class T> inline std::ostream & operator<<(std::ostream & stream, const Vector<T> & _this) { _this.printself(stream); return stream; } /* -------------------------------------------------------------------------- */ /* Inline Functions VectorBase */ /* -------------------------------------------------------------------------- */ inline std::ostream & operator<<(std::ostream & stream, const VectorBase & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_VECTOR_HH__ */ diff --git a/common/aka_vector_inline_impl.cc b/common/aka_vector_inline_impl.cc index b2ee74183..581982acf 100644 --- a/common/aka_vector_inline_impl.cc +++ b/common/aka_vector_inline_impl.cc @@ -1,95 +1,109 @@ /** * @file aka_vector_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jul 15 00:09:33 2010 * * @brief Inline functions of the classes Vector<T> and VectorBase * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* Inline Functions Vector<T> */ /* -------------------------------------------------------------------------- */ template <class T> inline T & Vector<T>::at(UInt i, UInt j) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(size > 0, "The vector is empty"); AKANTU_DEBUG_ASSERT((i < size) && (j < nb_component), "The value at position [" << i << "," << j << "] is out of range"); AKANTU_DEBUG_OUT(); return values[i*nb_component + j]; } template <class T> inline const T & Vector<T>::get(UInt i, UInt j) const{ AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(size > 0, "The vector is empty"); AKANTU_DEBUG_ASSERT((i < size) && (j < nb_component), "The value at position [" << i << "," << j << "] is out of range"); AKANTU_DEBUG_OUT(); return values[i*nb_component + j]; } /* -------------------------------------------------------------------------- */ template <class T> inline void Vector<T>::push_back(const T & value) { AKANTU_DEBUG_IN(); UInt pos = size; resize(size+1); /// @todo see if with std::uninitialized_fill it allow to build vector of objects for (UInt i = 0; i < nb_component; ++i) { values[pos*nb_component + i] = value; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T> inline void Vector<T>::push_back(const T new_elem[]) { AKANTU_DEBUG_IN(); UInt pos = size; resize(size+1); for (UInt i = 0; i < nb_component; ++i) { values[pos*nb_component + i] = new_elem[i]; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template <class T> inline void Vector<T>::erase(UInt i){ AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT((size > 0), "The vector is empty"); AKANTU_DEBUG_ASSERT((i < size), "The element at position [" << i << "] is out of range"); if(i != (size - 1)) { for (UInt j = 0; j < nb_component; ++j) { values[i*nb_component + j] = values[(size-1)*nb_component + j]; } } resize(size - 1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Inline Functions VectorBase */ /* -------------------------------------------------------------------------- */ inline UInt VectorBase::getMemorySize() const { return allocated_size * nb_component * size_of_type; } inline void VectorBase::empty() { size = 0; } diff --git a/doc/doxygen/CMakeLists.txt b/doc/doxygen/CMakeLists.txt index 6deed7188..593e38334 100644 --- a/doc/doxygen/CMakeLists.txt +++ b/doc/doxygen/CMakeLists.txt @@ -1,39 +1,53 @@ #=============================================================================== # @file CMakeLists.txt # @author Nicolas Richart <nicolas.richart@epfl.ch> # @date Mon Sep 27 17:35:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== set(DOXYGEN_INPUT ${CMAKE_CURRENT_BINARY_DIR}/akantu.dox) set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/html) set(DOXYGEN_OUTPUT ${DOXYGEN_OUTPUT_DIR}/index.html) make_directory(${DOXYGEN_OUTPUT_DIR}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/akantu.dox.cmake ${CMAKE_CURRENT_BINARY_DIR}/akantu.dox) add_custom_command( OUTPUT ${DOXYGEN_OUTPUT} COMMAND ${CMAKE_COMMAND} -E echo "${DOXYGEN_EXECUTABLE} ${DOXYGEN_INPUT}" COMMAND ${CMAKE_COMMAND} -E echo_append "Building akantu Documentation..." COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_INPUT} COMMAND ${CMAKE_COMMAND} -E echo "Done." DEPENDS ${DOXYGEN_INPUT} ) add_custom_target(akantu-doc ALL DEPENDS ${DOXYGEN_OUTPUT}) add_custom_target(akantu-doc-forced COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_INPUT} ) install(DIRECTORY ${DOXYGEN_OUTPUT_DIR} DESTINATION share/akantu-${akantu_VERSION}/doc) diff --git a/examples/2d_compression/2d_compression.cc b/examples/2d_compression/2d_compression.cc index 599097e91..c23bfd728 100644 --- a/examples/2d_compression/2d_compression.cc +++ b/examples/2d_compression/2d_compression.cc @@ -1,229 +1,243 @@ /** * @file 2d_compression.cc * @author Leo * @date Thu Sep 30 17:05:00 2010 * * @brief 2d dynamic explicit compression test with akantu * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #include "io_helper.h" #endif //AKANTU_USE_IOHELPER //using namespace akantu; static void setInitialConditions(akantu::SolidMechanicsModel *); static void setBoundaryConditions(akantu::SolidMechanicsModel *, akantu::Vector<akantu::UInt> *); static void Apply_Displacement(akantu::SolidMechanicsModel *, akantu::Vector<akantu::UInt> *, akantu::Real); static void reduceVelocities(akantu::SolidMechanicsModel *, akantu::Real); #ifdef AKANTU_USE_IOHELPER static void InitParaview(akantu::SolidMechanicsModel *); DumperParaview dumper; #endif //AKANTU_USE_IOHELPER int main(int argc, char *argv[]) { akantu::UInt spatial_dimension = 2; akantu::UInt max_steps = 30000; akantu::Real time_factor = 0.2; akantu::Mesh mesh(spatial_dimension); akantu::MeshIOMSH mesh_io; mesh_io.read("square_2d.msh", mesh); akantu::SolidMechanicsModel * model = new akantu::SolidMechanicsModel(mesh); akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); akantu::UInt nb_elements = model->getFEM().getMesh().getNbElement(akantu::_triangle_3); /// model initialization model->initVectors(); model->readMaterials("material.dat"); model->initMaterials(); model->initModel(); std::cout << model->getMaterial(0) << std::endl; model->assembleMassLumped(); /// Paraview Helper memset(model->getResidual().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getMaterial(0).getStrain(akantu::_triangle_3).values, 0, spatial_dimension*spatial_dimension*nb_elements*sizeof(akantu::Real)); memset(model->getMaterial(0).getStress(akantu::_triangle_3).values, 0, spatial_dimension*spatial_dimension*nb_elements*sizeof(akantu::Real)); /// boundary and initial conditions setInitialConditions(model); akantu::Vector<akantu::UInt> * face_node = new akantu::Vector<akantu::UInt>(0, 2, "face_node"); setBoundaryConditions(model, face_node); #ifdef AKANTU_USE_IOHELPER /// Paraview Helper InitParaview(model); #endif //AKANTU_USE_IOHELPER akantu::Real time_step = model->getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); for(akantu::UInt s = 1; s <= max_steps; ++s) { if(s<=100) Apply_Displacement(model, face_node, -0.01/100); model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); #ifdef AKANTU_USE_IOHELPER if(s % 200 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER if(s%100 == 0 && s>499) reduceVelocities(model, 0.95); if(s % 100 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } delete face_node; return EXIT_SUCCESS; } /************************** ** Static Functions ** **************************/ static void setInitialConditions(akantu::SolidMechanicsModel * model) { akantu::UInt spatial_dimension = model->getSpatialDimension(); akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); /// set vectors to 0 memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getVelocity().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getAcceleration().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getDisplacement().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); } static void setBoundaryConditions(akantu::SolidMechanicsModel * model, akantu::Vector<akantu::UInt> * face_node) { akantu::Real eps = 1e-16; akantu::Real * coord = model->getFEM().getMesh().getNodes().values; bool * id = model->getBoundary().values; akantu::Real y_min = std::numeric_limits<akantu::Real>::max(); akantu::Real y_max = std::numeric_limits<akantu::Real>::min(); akantu::UInt temp[2] = {0,0}, i; akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); akantu::UInt spatial_dimension = model->getSpatialDimension(); for(i = 0; i < nb_nodes; ++i) { y_min = (coord[spatial_dimension*i+1] < y_min) ? coord[spatial_dimension*i+1] : y_min; y_max = (coord[spatial_dimension*i+1] > y_max) ? coord[spatial_dimension*i+1] : y_max; } for (i = 0; i < nb_nodes; ++i) { if(coord[spatial_dimension*i+1]-eps <= y_min) { id[spatial_dimension*i+1] = true; temp[0] = 1; // face id temp[1] = i; // node id face_node->push_back(temp); continue; } if(coord[spatial_dimension*i+1]+eps >= y_max) id[spatial_dimension*i+1] = true; } } static void Apply_Displacement(akantu::SolidMechanicsModel * model, akantu::Vector<akantu::UInt> * face_node, akantu::Real delta) { akantu::Real * disp_val = model->getDisplacement().values; const akantu::UInt nb_face_nodes = face_node->getSize(); for(akantu::UInt i=0; i<nb_face_nodes; ++i) if(face_node->values[2*i] == 1) { /// Node on top surface disp_val[2*(face_node->values[2*i+1])+1] += delta; } } // Artificial damping of velocities in order to reach a global static equilibrium static void reduceVelocities(akantu::SolidMechanicsModel * model, akantu::Real ratio) { akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); akantu::Real * velocities = model->getVelocity().values; if(ratio>1.) { fprintf(stderr,"**error** in Reduce_Velocities ratio bigger than 1!\n"); exit(-1); } for(akantu::UInt i =0; i<nb_nodes; i++) { velocities[2*i] *= ratio; velocities[2*i+1] *= ratio; } } #ifdef AKANTU_USE_IOHELPER static void InitParaview(akantu::SolidMechanicsModel * model) { akantu::UInt spatial_dimension = model->getSpatialDimension(); akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); akantu::UInt nb_elements = model->getFEM().getMesh().getNbElement(akantu::_triangle_3); dumper.SetMode(TEXT); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, "coordinates"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(akantu::_triangle_3).values, TRIANGLE1, nb_elements, C_MODE); dumper.AddNodeDataField(model->getDisplacement().values, spatial_dimension, "displacements"); dumper.AddNodeDataField(model->getVelocity().values, spatial_dimension, "velocity"); dumper.AddNodeDataField(model->getResidual().values, spatial_dimension, "force"); dumper.AddElemDataField(model->getMaterial(0).getStrain(akantu::_triangle_3).values, spatial_dimension*spatial_dimension, "strain"); dumper.AddElemDataField(model->getMaterial(0).getStress(akantu::_triangle_3).values, spatial_dimension*spatial_dimension, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); } #endif //AKANTU_USE_IOHELPER diff --git a/examples/2d_compression/CMakeLists.txt b/examples/2d_compression/CMakeLists.txt index c1595f3a3..d923e9de0 100644 --- a/examples/2d_compression/CMakeLists.txt +++ b/examples/2d_compression/CMakeLists.txt @@ -1,27 +1,41 @@ #=============================================================================== # @file CMakeLists.txt # @author Leo # @date Fri Sep 29 16:46:30 2010 ...più precisi di così # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_mesh(2d_compression_mesh square_2d.geo 2 1) register_example(2d_compression 2d_compression.cc) add_dependencies(2d_compression 2d_compression_mesh) #=============================================================================== configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/material.dat ${CMAKE_CURRENT_BINARY_DIR}/material.dat COPYONLY ) \ No newline at end of file diff --git a/examples/3d_cube_compression/3d_cube_compression.cc b/examples/3d_cube_compression/3d_cube_compression.cc index 0a293816a..429ec376f 100644 --- a/examples/3d_cube_compression/3d_cube_compression.cc +++ b/examples/3d_cube_compression/3d_cube_compression.cc @@ -1,186 +1,200 @@ /** * @file 3d_cube_compression.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Nov 24 23:15:47 2010 * * @brief 3d cube compression * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "static_communicator.hh" #include "communicator.hh" #include "mesh_partition_scotch.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER int main(int argc, char *argv[]) { akantu::ElementType type = akantu::_tetrahedron_4; #ifdef AKANTU_USE_IOHELPER akantu::UInt paraview_type = TETRA1; #endif //AKANTU_USE_IOHELPER akantu::UInt spatial_dimension = 3; akantu::UInt max_steps = 5000; akantu::Real time_step = 1e-6; akantu::initialize(&argc, &argv); akantu::StaticCommunicator * comm = akantu::StaticCommunicator::getStaticCommunicator(); akantu::Int psize = comm->getNbProc(); akantu::Int prank = comm->whoAmI(); // akantu::Real epot, ekin; akantu::Mesh mesh(spatial_dimension); /* ------------------------------------------------------------------------ */ /* Parallel initialization */ /* ------------------------------------------------------------------------ */ akantu::Communicator * communicator; if(prank == 0) { akantu::MeshIOMSH mesh_io; mesh_io.read("cube.msh", mesh); akantu::MeshPartition * partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); communicator = akantu::Communicator::createCommunicatorDistributeMesh(mesh, partition); delete partition; } else { communicator = akantu::Communicator::createCommunicatorDistributeMesh(mesh, NULL); } // akantu::Mesh mesh(spatial_dimension); // akantu::MeshIOMSH mesh_io; // mesh_io.read("cube.msh", mesh); akantu::SolidMechanicsModel * model = new akantu::SolidMechanicsModel(mesh); akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); akantu::UInt nb_element = model->getFEM().getMesh().getNbElement(type); std::cout << "Nb nodes : " << nb_nodes << " - nb elements : " << nb_element << std::endl; /// model initialization model->initVectors(); /// set vectors to 0 memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getVelocity().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getAcceleration().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getDisplacement().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); model->readMaterials("material.dat"); model->initMaterials(); model->registerSynchronizer(*communicator); model->initModel(); std::cout << model->getMaterial(0) << std::endl; model->assembleMassLumped(); #ifdef AKANTU_USE_IOHELPER /// set to 0 only for the first paraview dump memset(model->getResidual().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getMaterial(0).getStrain(type).values, 0, spatial_dimension*spatial_dimension*nb_element*sizeof(akantu::Real)); memset(model->getMaterial(0).getStress(type).values, 0, spatial_dimension*spatial_dimension*nb_element*sizeof(akantu::Real)); #endif //AKANTU_USE_IOHELPER /// boundary conditions akantu::Real eps = 1e-16; for (akantu::UInt i = 0; i < nb_nodes; ++i) { // if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] >= 9) // model->getDisplacement().values[spatial_dimension*i] = (model->getFEM().getMesh().getNodes().values[spatial_dimension*i] - 9) / 100. ; if(fabs(model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 2] - 1) <= eps) model->getForce().values[spatial_dimension*i + 2] = -250; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 2] <= eps) model->getBoundary().values[spatial_dimension*i + 2] = true; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 0] <= eps) { model->getBoundary().values[spatial_dimension*i + 0] = true; } } // akantu::Real time_step = model->getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); // model->setTimeStep(3.54379e-07); #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, "coordinates"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(model->getDisplacement().values, spatial_dimension, "displacements"); dumper.AddNodeDataField(model->getVelocity().values, spatial_dimension, "velocity"); dumper.AddNodeDataField(model->getResidual().values, spatial_dimension, "force"); dumper.AddElemDataField(model->getMaterial(0).getStrain(type).values, spatial_dimension*spatial_dimension, "strain"); dumper.AddElemDataField(model->getMaterial(0).getStress(type).values, spatial_dimension*spatial_dimension, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER double total_time = 0.; for(akantu::UInt s = 1; s <= max_steps; ++s) { double start = MPI_Wtime(); model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); double end = MPI_Wtime(); total_time += end - start; #ifdef AKANTU_USE_IOHELPER if(s % 1 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } if(prank == 0) std::cout << "Time : " << psize << " " << total_time / max_steps << " " << total_time << std::endl; return EXIT_SUCCESS; } diff --git a/examples/3d_cube_compression/CMakeLists.txt b/examples/3d_cube_compression/CMakeLists.txt index ea76823ad..0b4d5969a 100644 --- a/examples/3d_cube_compression/CMakeLists.txt +++ b/examples/3d_cube_compression/CMakeLists.txt @@ -1,29 +1,43 @@ #=============================================================================== # @file CMakeLists.txt # @author Leo # @date Fri Sep 29 16:46:30 2010 ...più precisi di così # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_mesh(3d_cube_compression_mesh cube.geo 3 1) register_example(3d_cube_compression 3d_cube_compression.cc) add_dependencies(3d_cube_compression 3d_cube_compression_mesh) #=============================================================================== configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/material.dat ${CMAKE_CURRENT_BINARY_DIR}/material.dat COPYONLY ) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) \ No newline at end of file diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index c493fcd6c..868fe3ad0 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,28 +1,42 @@ #=============================================================================== # @file CMakeLists.txt # @author Nicolas Richart <nicolas.richart@epfl.ch> # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== INCLUDE(${AKANTU_CMAKE_DIR}/AkantuTestAndExamples.cmake) #=============================================================================== # List of examples #=============================================================================== add_example(2d_compression "Compression example") if(AKANTU_SCOTCH_ON AND AKANTU_MPI_ON) add_example(3d_cube_compression "Cube compression example") endif(AKANTU_SCOTCH_ON AND AKANTU_MPI_ON) if(AKANTU_EPSN_ON) add_example(epsn "Example of steering akantu with EPSN") endif(AKANTU_EPSN_ON) \ No newline at end of file diff --git a/examples/epsn/CMakeLists.txt b/examples/epsn/CMakeLists.txt index 24ba67c1e..a4f4c969e 100644 --- a/examples/epsn/CMakeLists.txt +++ b/examples/epsn/CMakeLists.txt @@ -1,35 +1,49 @@ #=============================================================================== # @file CMakeLists.txt # @author Nicolas Richart <nicolas.richart@epfl.ch> # @date Wed Dec 8 2010 16:46:30 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_mesh(epsn_bar_mesh bar.geo 2 1) register_example(akantu_epsn_example akantu_epsn_example.cc) add_dependencies(akantu_epsn_example epsn_bar_mesh) #=============================================================================== configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/material.dat ${CMAKE_CURRENT_BINARY_DIR}/material.dat COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/bar_traction.xml ${CMAKE_CURRENT_BINARY_DIR}/bar_traction.xml COPYONLY ) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) \ No newline at end of file diff --git a/examples/epsn/akantu_epsn_example.cc b/examples/epsn/akantu_epsn_example.cc index 58ba8cf5e..1e56749bc 100644 --- a/examples/epsn/akantu_epsn_example.cc +++ b/examples/epsn/akantu_epsn_example.cc @@ -1,311 +1,325 @@ /** * @file akantu_epsn_example.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 14:34:13 2010 * * @brief test of the class SolidMechanicsModel * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include <EpsnSimulation_Interface.hh> #include <RedSYM.hh> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "static_communicator.hh" #include "communicator.hh" #include "mesh_partition_scotch.hh" /* -------------------------------------------------------------------------- */ #undef AKANTU_USE_IOHELPER #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER int main(int argc, char *argv[]) { std::string simulation_name = "bar_traction"; std::string xml_filename = "bar_traction.xml"; akantu::ElementType type = akantu::_quadrangle_4; RedSYM::CellType redsym_type = RedSYM::_quadrilateral; // akantu::ElementType type = akantu::_triangle_3; // RedSYM::CellType redsym_type = RedSYM::_triangle akantu::UInt spatial_dimension = 2; akantu::UInt max_steps = 5000; akantu::Real time_factor = 0.8; akantu::initialize(&argc, &argv); akantu::debug::setDebugLevel(akantu::dblWarning); // akantu::Real epot, ekin; akantu::Mesh mesh(spatial_dimension); akantu::StaticCommunicator * comm = akantu::StaticCommunicator::getStaticCommunicator(); akantu::Int psize = comm->getNbProc(); akantu::Int prank = comm->whoAmI(); /* ------------------------------------------------------------------------ */ /* Parallel initialization */ /* ------------------------------------------------------------------------ */ akantu::Communicator * communicator; if(prank == 0) { akantu::MeshIOMSH mesh_io; mesh_io.read("bar.msh", mesh); akantu::MeshPartition * partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); communicator = akantu::Communicator::createCommunicatorDistributeMesh(mesh, partition); delete partition; } else { communicator = akantu::Communicator::createCommunicatorDistributeMesh(mesh, NULL); } akantu::SolidMechanicsModel * model = new akantu::SolidMechanicsModel(mesh); akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); akantu::UInt nb_element = model->getFEM().getMesh().getNbElement(type); EPSN::Simulation::Interface * epsn_itfc; epsn_itfc = new EPSN::Simulation::Interface; epsn_itfc->initORB(argc,argv); if(prank == 0) epsn_itfc->initProxyAndNode(simulation_name, xml_filename, prank, psize); else epsn_itfc->initNode(simulation_name, prank, psize); /* ------------------------------------------------------------------------ */ /* Initialization */ /* ------------------------------------------------------------------------ */ /// model initialization model->initVectors(); /// set vectors to 0 memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getResidual().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getVelocity().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getAcceleration().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getDisplacement().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); model->readMaterials("material.dat"); model->initMaterials(); model->registerSynchronizer(*communicator); model->initModel(); if(prank == 0) std::cout << model->getMaterial(0) << std::endl; model->assembleMassLumped(); /* ------------------------------------------------------------------------ */ /* Boundary + initial conditions */ /* ------------------------------------------------------------------------ */ akantu::Real eps = 1e-16; for (akantu::UInt i = 0; i < nb_nodes; ++i) { // model->getDisplacement().values[spatial_dimension*i] // = model->getFEM().getMesh().getNodes().values[spatial_dimension*i] / 100.; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] >= 9) model->getDisplacement().values[spatial_dimension*i] = (model->getFEM().getMesh().getNodes().values[spatial_dimension*i] - 9) / 100.; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] <= eps) model->getBoundary().values[spatial_dimension*i] = true; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] <= eps || model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] >= 1 - eps ) { model->getBoundary().values[spatial_dimension*i + 1] = true; } } model->synchronizeBoundaries(); #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetParallelContext(prank, psize); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, "bar2d_para"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type).values, TRIANGLE2, nb_element, C_MODE); dumper.AddNodeDataField(model->getDisplacement().values, spatial_dimension, "displacements"); dumper.AddNodeDataField(model->getMass().values, 1, "mass"); dumper.AddNodeDataField(model->getVelocity().values, spatial_dimension, "velocity"); dumper.AddNodeDataField(model->getResidual().values, spatial_dimension, "force"); dumper.AddNodeDataField(model->getAcceleration().values, spatial_dimension, "acceleration"); dumper.AddElemDataField(model->getMaterial(0).getStrain(type).values, spatial_dimension*spatial_dimension, "strain"); dumper.AddElemDataField(model->getMaterial(0).getStress(type).values, spatial_dimension*spatial_dimension, "stress"); // akantu::UInt nb_quadrature_points = akantu::FEM::getNbQuadraturePoints(type); // double * part = new double[nb_element*nb_quadrature_points]; // for (unsigned int i = 0; i < nb_element; ++i) // for (unsigned int q = 0; q < nb_quadrature_points; ++q) // part[i*nb_quadrature_points + q] = prank; // dumper.AddElemDataField(part, 1, "partitions"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER akantu::UInt nb_nodes_per_element = akantu::Mesh::getNbNodesPerElement(type); RedSYM::Mesh * rs_mesh = new RedSYM::Mesh("bar", prank, psize, spatial_dimension, redsym_type, RedSYM::_c_numbering); int cell_variable = rs_mesh->addVariable("connectivity", RedSYM::_long, nb_nodes_per_element); int node_variable = rs_mesh->addVariable("nodes", RedSYM::_double, spatial_dimension); int displacements_variable = rs_mesh->addVariable("displacements", RedSYM::_double, spatial_dimension ); int mass_variable = rs_mesh->addVariable("mass" , RedSYM::_double, 1 ); int velocity_variable = rs_mesh->addVariable("velocity" , RedSYM::_double, spatial_dimension ); int force_variable = rs_mesh->addVariable("force" , RedSYM::_double, spatial_dimension ); int acceleration_variable = rs_mesh->addVariable("acceleration" , RedSYM::_double, spatial_dimension ); int strain_variable = rs_mesh->addVariable("strain" , RedSYM::_double, spatial_dimension*spatial_dimension); int stress_variable = rs_mesh->addVariable("stress" , RedSYM::_double, spatial_dimension*spatial_dimension); rs_mesh->setCellVariable(cell_variable); rs_mesh->setNodeVariable(node_variable); rs_mesh->setNodeDataVariable(displacements_variable); rs_mesh->setNodeDataVariable(mass_variable ); rs_mesh->setNodeDataVariable(velocity_variable ); rs_mesh->setNodeDataVariable(force_variable ); rs_mesh->setNodeDataVariable(acceleration_variable ); rs_mesh->setCellDataVariable(strain_variable ); rs_mesh->setCellDataVariable(stress_variable ); RedSYM::Key region = rs_mesh->addRegion(nb_element, nb_nodes); rs_mesh->setRegionTag(region, prank*100); rs_mesh->setNumberOfCells(region, nb_element); rs_mesh->setNumberOfNodes(region, nb_nodes); rs_mesh->wrapCells(region, model->getFEM().getMesh().getConnectivity(type).values); rs_mesh->wrapNodes(region, model->getFEM().getMesh().getNodes().values); rs_mesh->wrap(displacements_variable, region, model->getDisplacement().values ); rs_mesh->wrap(mass_variable , region, model->getMass().values ); rs_mesh->wrap(velocity_variable , region, model->getVelocity().values ); rs_mesh->wrap(force_variable , region, model->getResidual().values ); rs_mesh->wrap(acceleration_variable , region, model->getAcceleration().values ); rs_mesh->wrap(strain_variable , region, model->getMaterial(0).getStrain(type).values); rs_mesh->wrap(stress_variable , region, model->getMaterial(0).getStress(type).values); epsn_itfc->addData(rs_mesh); epsn_itfc->ready(); std::ofstream energy; if(prank == 0) { energy.open("energy.csv"); energy << "id,epot,ekin,tot" << std::endl; } double total_time = 0.; /// Setting time step akantu::Real time_step = model->getStableTimeStep() * time_factor; if(prank == 0) std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ epsn_itfc->beginHTM(); epsn_itfc->beginLoop("main"); for(akantu::UInt s = 1; s <= max_steps; ++s) { epsn_itfc->beginTask("body"); double start = MPI_Wtime(); epsn_itfc->beginTask("predictor"); model->explicitPred(); epsn_itfc->endTask("predictor"); epsn_itfc->beginTask("updateResidual"); model->updateResidual(); epsn_itfc->endTask("updateResidual"); epsn_itfc->beginTask("updateAcceleration"); model->updateAcceleration(); epsn_itfc->endTask("updateAcceleration"); epsn_itfc->beginTask("corrector"); model->explicitCorr(); epsn_itfc->endTask("corrector"); epsn_itfc->endTask("body"); double end = MPI_Wtime(); akantu::Real epot = model->getPotentialEnergy(); akantu::Real ekin = model->getKineticEnergy(); total_time += end - start; if(prank == 0 && (s % 10 == 0)) { std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; } #ifdef AKANTU_USE_IOHELPER if(s % 10 == 0) { dumper.Dump(); } #endif //AKANTU_USE_IOHELPER } epsn_itfc->endLoop("main"); epsn_itfc->endHTM(); epsn_itfc->finalize(); epsn_itfc->killORB(); if(prank == 0) std::cout << "Time : " << psize << " " << total_time / max_steps << " " << total_time << std::endl; // delete [] part; delete model; energy.close(); akantu::finalize(); return EXIT_SUCCESS; } diff --git a/fem/element_class.cc b/fem/element_class.cc index 6bab63755..ee701dbf1 100644 --- a/fem/element_class.cc +++ b/fem/element_class.cc @@ -1,143 +1,157 @@ /** * @file element_class.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 20 10:12:44 2010 * * @brief Common part of element_classes * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template<ElementType type> UInt ElementClass<type>::nb_nodes_per_element = 0; template<ElementType type> ElementType ElementClass<type>::p1_element_type = _not_defined; template<ElementType type> UInt ElementClass<type>::nb_quadrature_points = 0; template<ElementType type> UInt ElementClass<type>::spatial_dimension = 0; template<ElementType type> ElementType ElementClass<type>::facet_type = _not_defined; /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_point>::nb_nodes_per_element = 1; template<> ElementType ElementClass<_point>::p1_element_type = _point; template<> ElementType ElementClass<_point>::facet_type = _not_defined; template<> UInt ElementClass<_point>::spatial_dimension = 0; template<> UInt ElementClass<_point>::nb_facets = 0; template<> UInt * ElementClass<_point>::facet_connectivity[] = {}; /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_segment_2>::nb_nodes_per_element = 2; template<> ElementType ElementClass<_segment_2>::p1_element_type = _segment_2; template<> UInt ElementClass<_segment_2>::nb_quadrature_points = 1; template<> Real ElementClass<_segment_2>::quad[] = {0}; template<> UInt ElementClass<_segment_2>::spatial_dimension = 1; template<> UInt ElementClass<_segment_2>::nb_facets = 2; template<> ElementType ElementClass<_segment_2>::facet_type = _point; template<> UInt ElementClass<_segment_2>::vec_facet_connectivity[]= {0, 1}; template<> UInt * ElementClass<_segment_2>::facet_connectivity[] = {&vec_facet_connectivity[0], &vec_facet_connectivity[1]}; /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_segment_3>::nb_nodes_per_element = 3; template<> ElementType ElementClass<_segment_3>::p1_element_type = _segment_2; template<> UInt ElementClass<_segment_3>::nb_quadrature_points = 2; template<> Real ElementClass<_segment_3>::quad[] = {-1./sqrt(3.), 1./sqrt(3.)}; template<> UInt ElementClass<_segment_3>::spatial_dimension = 1; template<> UInt ElementClass<_segment_3>::nb_facets = 2; template<> ElementType ElementClass<_segment_3>::facet_type = _point; template<> UInt ElementClass<_segment_3>::vec_facet_connectivity[]= {0, 1}; template<> UInt * ElementClass<_segment_3>::facet_connectivity[] = {&vec_facet_connectivity[0], &vec_facet_connectivity[1]}; /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_triangle_3>::nb_nodes_per_element = 3; template<> ElementType ElementClass<_triangle_3>::p1_element_type = _triangle_3; template<> UInt ElementClass<_triangle_3>::nb_quadrature_points = 1; template<> Real ElementClass<_triangle_3>::quad[] = {1./3., 1./3.}; template<> UInt ElementClass<_triangle_3>::spatial_dimension = 2; template<> UInt ElementClass<_triangle_3>::nb_facets = 3; template<> ElementType ElementClass<_triangle_3>::facet_type = _segment_2; template<> UInt ElementClass<_triangle_3>::vec_facet_connectivity[]= {0, 1, 1, 2, 2, 0}; template<> UInt * ElementClass<_triangle_3>::facet_connectivity[] = {&vec_facet_connectivity[0], &vec_facet_connectivity[2], &vec_facet_connectivity[4]}; /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_triangle_6>::nb_nodes_per_element = 6; template<> ElementType ElementClass<_triangle_6>::p1_element_type = _triangle_3; template<> UInt ElementClass<_triangle_6>::nb_quadrature_points = 3; template<> Real ElementClass<_triangle_6>::quad[] = {1./6., 1./6., 2./3., 1./6., 1./6., 2./3.}; template<> UInt ElementClass<_triangle_6>::spatial_dimension = 2; template<> UInt ElementClass<_triangle_6>::nb_facets = 3; template<> ElementType ElementClass<_triangle_6>::facet_type = _segment_3; template<> UInt ElementClass<_triangle_6>::vec_facet_connectivity[]= {0, 1, 3, 1, 2, 4, 2, 0, 5}; template<> UInt * ElementClass<_triangle_6>::facet_connectivity[] = {&vec_facet_connectivity[0], &vec_facet_connectivity[3], &vec_facet_connectivity[6]}; /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_tetrahedron_4>::nb_nodes_per_element = 4; template<> ElementType ElementClass<_tetrahedron_4>::p1_element_type = _tetrahedron_4; template<> UInt ElementClass<_tetrahedron_4>::nb_quadrature_points = 1; template<> Real ElementClass<_tetrahedron_4>::quad[] = {1./4., 1./4., 1./4.}; template<> UInt ElementClass<_tetrahedron_4>::spatial_dimension = 3; template<> UInt ElementClass<_tetrahedron_4>::nb_facets = 4; template<> ElementType ElementClass<_tetrahedron_4>::facet_type = _triangle_3; template<> UInt ElementClass<_tetrahedron_4>::vec_facet_connectivity[]= {0, 2, 1, 1, 2, 3, 2, 0, 3, 0, 1, 3}; template<> UInt * ElementClass<_tetrahedron_4>::facet_connectivity[] = {&vec_facet_connectivity[0], &vec_facet_connectivity[3], &vec_facet_connectivity[6], &vec_facet_connectivity[9]}; /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_tetrahedron_10>::nb_nodes_per_element = 10; template<> ElementType ElementClass<_tetrahedron_10>::p1_element_type = _tetrahedron_4; template<> UInt ElementClass<_tetrahedron_10>::nb_quadrature_points = 4; template<> Real ElementClass<_tetrahedron_10>::quad[] = {0.1381966011250, 0.1381966011250, 0.1381966011250, // a = (5-sqrt(5))/20 0.5854101966250, 0.1381966011250, 0.1381966011250, // b = (5+3*sqrt(5))/20 0.1381966011250, 0.5854101966250, 0.1381966011250, 0.1381966011250, 0.1381966011250, 0.5854101966250}; template<> UInt ElementClass<_tetrahedron_10>::spatial_dimension = 3; template<> UInt ElementClass<_tetrahedron_10>::nb_facets = 4; template<> ElementType ElementClass<_tetrahedron_10>::facet_type = _triangle_6; template<> UInt ElementClass<_tetrahedron_10>::vec_facet_connectivity[]= {0, 2, 1, 6, 5, 4, 1, 2, 3, 5, 9, 8, 2, 0, 3, 6, 7, 9, 0, 1, 3, 4, 8, 7}; template<> UInt * ElementClass<_tetrahedron_10>::facet_connectivity[] = {&vec_facet_connectivity[0], &vec_facet_connectivity[6], &vec_facet_connectivity[12], &vec_facet_connectivity[18]}; /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_quadrangle_4>::nb_nodes_per_element = 4; template<> ElementType ElementClass<_quadrangle_4>::p1_element_type = _quadrangle_4; template<> UInt ElementClass<_quadrangle_4>::nb_quadrature_points = 1; template<> Real ElementClass<_quadrangle_4>::quad[] = {0, 0}; template<> UInt ElementClass<_quadrangle_4>::spatial_dimension = 2; template<> UInt ElementClass<_quadrangle_4>::nb_facets = 4; template<> ElementType ElementClass<_quadrangle_4>::facet_type = _segment_2; template<> UInt ElementClass<_quadrangle_4>::vec_facet_connectivity[]= {0, 1, 1, 2, 2, 3, 3, 0}; template<> UInt * ElementClass<_quadrangle_4>::facet_connectivity[] = {&vec_facet_connectivity[0], &vec_facet_connectivity[2], &vec_facet_connectivity[4], &vec_facet_connectivity[6]}; /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/fem/element_class.hh b/fem/element_class.hh index dc0fea346..65b17b252 100644 --- a/fem/element_class.hh +++ b/fem/element_class.hh @@ -1,183 +1,197 @@ /** * @file element_class.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Jun 16 18:48:25 2010 * * @brief * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_ELEMENT_CLASS_HH__ #define __AKANTU_ELEMENT_CLASS_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_math.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /** * Class describing the different type of element for mesh or finite element * purpose * * @tparam type the element type for the specialization of the element class */ template<ElementType type> class ElementClass { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /** * compute the shape functions, the shape functions derivatives and the * jacobians * @param[in] coord coordinates of the nodes * @param[out] shape shape functions [nb_quad*node_per_elem] * @param[out] shape_deriv shape functions derivatives [nb_quad*node_per_elem*spatial_dim] * @param[out] jacobian jacobians * integration weights [nb_quad] */ inline static void preComputeStandards(const Real * coord, const UInt dimension, Real * shape, Real * shape_deriv, Real * jacobian); /// compute the shape values for a point given in natural coordinates inline static void computeShapes(const Real * natural_coords, Real * shapes); /// compute the shape values for a set of points given in natural coordinates inline static void computeShapes(const Real * natural_coords, const UInt nb_points, Real * shapes); /** compute dxds the variation of real coordinates along with variation of natural coordinates * on a given point in natural coordinates */ inline static void computeDXDS(const Real * dnds, const Real * node_coords, const UInt dimension, Real * dxds); /** compute dxds the variation of real coordinates along with variation of natural coordinates * on a given set of points in natural coordinates */ inline static void computeDXDS(const Real * dnds, const UInt nb_points, const Real * node_coords, const UInt dimension, Real * dxds); /** compute dnds the variation of real shape functions along with variation of natural coordinates * on a given point in natural coordinates */ inline static void computeDNDS(const Real * natural_coords, Real * dnds); /** compute dnds the variation of shape functions along with variation of natural coordinates * on a given set of points in natural coordinates */ inline static void computeDNDS(const Real * natural_coords, const UInt nb_points, Real * dnds); /// compute jacobian (or integration variable change factor) for a set of points inline static void computeJacobian(const Real * dxds, const UInt nb_points, const UInt dimension, Real * jac); /// compute jacobian (or integration variable change factor) for a given point inline static void computeJacobian(const Real * dxds, const UInt dimension, Real & jac); /// compute shape derivatives (input is dxds) for a set of points inline static void computeShapeDerivatives(const Real * dxds, const Real * dnds, const UInt nb_points, const UInt dimension, Real * shape_deriv); /// compute shape derivatives (input is dxds) for a given point inline static void computeShapeDerivatives(const Real * dxds, const Real * dnds, Real * shape_deriv); /// compute normals on quad points inline static void computeNormalsOnQuadPoint(const Real * dxds, const UInt dimension, Real * normals); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const {}; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: static AKANTU_GET_MACRO_NOT_CONST(NbNodesPerElement, nb_nodes_per_element, UInt); static AKANTU_GET_MACRO_NOT_CONST(P1ElementType, p1_element_type, ElementType); static AKANTU_GET_MACRO_NOT_CONST(NbQuadraturePoints, nb_quadrature_points, UInt); static AKANTU_GET_MACRO_NOT_CONST(SpatialDimension, spatial_dimension, UInt); static AKANTU_GET_MACRO_NOT_CONST(FacetElementType, facet_type, const ElementType &); static AKANTU_GET_MACRO_NOT_CONST(NbFacetsPerElement, nb_facets, UInt); static AKANTU_GET_MACRO_NOT_CONST(FacetLocalConnectivityPerElement, facet_connectivity, UInt**); static inline UInt getNbQuadraturePoint(); static inline UInt getShapeSize(); static inline UInt getShapeDerivativesSize(); /// compute the in-radius static inline Real getInradius(const Real * coord); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// Number of nodes per element static UInt nb_nodes_per_element; /// Number of quadrature points per element static UInt nb_quadrature_points; /// Dimension of the element static UInt spatial_dimension; /// Type of the facet elements static ElementType facet_type; /// number of facets for element static UInt nb_facets; /// local connectivity of facets static UInt * facet_connectivity[]; /// vectorial connectivity of facets static UInt vec_facet_connectivity[]; /// type of element P1 associated static ElementType p1_element_type; /// quadrature points in natural coordinates static Real quad[]; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "element_class_inline_impl.cc" /* -------------------------------------------------------------------------- */ __END_AKANTU__ #endif /* __AKANTU_ELEMENT_CLASS_HH__ */ diff --git a/fem/element_class_inline_impl.cc b/fem/element_class_inline_impl.cc index a41e8ab42..e6b5c95f7 100644 --- a/fem/element_class_inline_impl.cc +++ b/fem/element_class_inline_impl.cc @@ -1,224 +1,238 @@ /** * @file element_class_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @date Thu Jul 15 10:28:28 2010 * * @brief Implementation of the inline functions of the class element_class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ template<ElementType type> inline UInt ElementClass<type>::getNbQuadraturePoint() { return nb_quadrature_points; } /* -------------------------------------------------------------------------- */ template<ElementType type> inline UInt ElementClass<type>::getShapeSize() { return nb_nodes_per_element; } /* -------------------------------------------------------------------------- */ template<ElementType type> inline UInt ElementClass<type>::getShapeDerivativesSize() { return nb_nodes_per_element * spatial_dimension; } /* -------------------------------------------------------------------------- */ template<ElementType type> void ElementClass<type>::preComputeStandards(const Real * coord, const UInt dimension, Real * shape, Real * dshape, Real * jacobians) { // ask for computation of shapes computeShapes(quad, nb_quadrature_points, shape); // compute dnds Real dnds[nb_nodes_per_element * spatial_dimension * nb_quadrature_points]; computeDNDS(quad, nb_quadrature_points, dnds); // compute dxds Real dxds[dimension * spatial_dimension * nb_quadrature_points]; computeDXDS(dnds, nb_quadrature_points, coord, dimension, dxds); // jacobian computeJacobian(dxds, nb_quadrature_points, dimension, jacobians); // if dimension == spatial_dimension compute shape derivatives if (dimension == spatial_dimension) { computeShapeDerivatives(dxds, dnds, nb_quadrature_points, dimension, dshape); } } /* -------------------------------------------------------------------------- */ template <ElementType type> inline void ElementClass<type>::computeShapes(const Real * natural_coords, const UInt nb_points, Real * shapes) { Real * cpoint = const_cast<Real *>(natural_coords); for (UInt p = 0; p < nb_points; ++p) { computeShapes(cpoint, shapes); shapes += nb_nodes_per_element; cpoint += spatial_dimension; } } /* -------------------------------------------------------------------------- */ template<ElementType type> inline void ElementClass<type>::computeDNDS(const Real * natural_coords, const UInt nb_points, Real * dnds) { Real * cpoint = const_cast<Real *>(natural_coords); Real * cdnds = dnds; for (UInt p = 0; p < nb_points; ++p) { computeDNDS(cpoint, cdnds); cpoint += spatial_dimension; cdnds += nb_nodes_per_element * spatial_dimension; } } /* -------------------------------------------------------------------------- */ template<ElementType type> inline void ElementClass<type>::computeDXDS(const Real * dnds, const UInt nb_points, const Real * node_coords, const UInt dimension, Real * dxds) { Real * cdnds = const_cast<Real *>(dnds); Real * cdxds = dxds; for (UInt p = 0; p < nb_points; ++p) { computeDXDS(cdnds, node_coords, dimension, cdxds); cdnds += nb_nodes_per_element * spatial_dimension; cdxds += spatial_dimension * dimension; } } /* -------------------------------------------------------------------------- */ template <ElementType type> inline void ElementClass<type>::computeDXDS(const Real * dnds, const Real * node_coords, const UInt dimension, Real * dxds) { /// @f$ J = dxds = dnds * x @f$ Math::matrix_matrix(spatial_dimension, dimension, nb_nodes_per_element, dnds, node_coords, dxds); } /* -------------------------------------------------------------------------- */ template <ElementType type> inline void ElementClass<type>::computeJacobian(const Real * dxds, const UInt nb_points, const UInt dimension, Real * jac) { Real * cdxds = const_cast<Real *>(dxds); Real * cjac = jac; for (UInt p = 0; p < nb_points; ++p) { computeJacobian(cdxds, dimension, *cjac); AKANTU_DEBUG_ASSERT((cjac[0] > 0), "Negative jacobian computed, possible problem in the element node order."); cdxds += spatial_dimension * dimension; cjac++; } } /* -------------------------------------------------------------------------- */ template <ElementType type> inline void ElementClass<type>::computeShapeDerivatives(const Real * dxds, const Real * dnds, const UInt nb_points, const UInt dimension, Real * shape_deriv) { AKANTU_DEBUG_ASSERT(dimension == spatial_dimension,"gradient in space " << dimension << " cannot be evaluated for element of dimension " << spatial_dimension); Real * cdxds = const_cast<Real *>(dxds); Real * cdnds = const_cast<Real *>(dnds); for (UInt p = 0; p < nb_points; ++p) { computeShapeDerivatives(cdxds, cdnds, shape_deriv); cdnds += spatial_dimension * nb_nodes_per_element; cdxds += spatial_dimension * spatial_dimension; shape_deriv += nb_nodes_per_element * spatial_dimension; } } /* -------------------------------------------------------------------------- */ template <ElementType type> inline void ElementClass<type>::computeShapeDerivatives(const Real * dxds, const Real * dnds, Real * shape_deriv) { /// @f$ dxds = J^{-1} @f$ Real inv_dxds[spatial_dimension * spatial_dimension]; if (spatial_dimension == 1) inv_dxds[0] = 1./dxds[0]; if (spatial_dimension == 2) Math::inv2(dxds, inv_dxds); if (spatial_dimension == 3) Math::inv3(dxds, inv_dxds); Math::matrixt_matrixt(nb_nodes_per_element, spatial_dimension, spatial_dimension, dnds, inv_dxds, shape_deriv); } /* -------------------------------------------------------------------------- */ template<ElementType type> inline Real ElementClass<type>::getInradius(__attribute__ ((unused)) const Real * coord) { AKANTU_DEBUG_ERROR("Function not implemented for type : " << type); return 0; } /* -------------------------------------------------------------------------- */ template<ElementType type> inline void ElementClass<type>::computeNormalsOnQuadPoint(const Real * coord, const UInt dimension, Real * normals) { AKANTU_DEBUG_ASSERT((dimension - 1) == spatial_dimension, "cannot extract a normal because of dimension mismatch " << dimension << " " << spatial_dimension); Real * cpoint = const_cast<Real *>(quad); Real * cnormals = normals; Real dnds[spatial_dimension*nb_nodes_per_element]; Real dxds[spatial_dimension*dimension]; for (UInt p = 0; p < nb_quadrature_points; ++p) { computeDNDS(cpoint,dnds); computeDXDS(dnds,coord,dimension,dxds); if (dimension == 2) { Math::normal2(dxds,cnormals); } if (dimension == 3){ Math::normal3(dxds,dxds+dimension,cnormals); } cpoint += spatial_dimension; cnormals += dimension; } } /* -------------------------------------------------------------------------- */ template <ElementType type> inline void ElementClass<type>::computeShapes(__attribute__ ((unused)) const Real * natural_coords, __attribute__ ((unused)) Real * shapes){ AKANTU_DEBUG_ERROR("Function not implemented for type : " << type); } /* -------------------------------------------------------------------------- */ template <ElementType type> inline void ElementClass<type>::computeDNDS(__attribute__ ((unused)) const Real * natural_coords, __attribute__ ((unused)) Real * dnds){ AKANTU_DEBUG_ERROR("Function not implemented for type : " << type); } /* -------------------------------------------------------------------------- */ template <ElementType type> inline void ElementClass<type>::computeJacobian(__attribute__ ((unused)) const Real * dxds, __attribute__ ((unused)) const UInt dimension, __attribute__ ((unused)) Real & jac){ AKANTU_DEBUG_ERROR("Function not implemented for type : " << type); } #include "element_classes/element_class_segment_2.cc" #include "element_classes/element_class_segment_3.cc" #include "element_classes/element_class_triangle_3.cc" #include "element_classes/element_class_triangle_6.cc" #include "element_classes/element_class_tetrahedron_4.cc" #include "element_classes/element_class_tetrahedron_10.cc" #include "element_classes/element_class_quadrangle_4.cc" diff --git a/fem/element_classes/element_class_quadrangle_4.cc b/fem/element_classes/element_class_quadrangle_4.cc index 91dfb0e52..1b45e691f 100644 --- a/fem/element_classes/element_class_quadrangle_4.cc +++ b/fem/element_classes/element_class_quadrangle_4.cc @@ -1,130 +1,144 @@ /** * @file element_class_quadrangle_4.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Oct 27 17:27:44 2010 * * @brief Specialization of the element_class class for the type _quadrangle_4 * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * * @verbatim \eta ^ (-1,1) | (1,1) x---------x | | | | | | --|---------|-----> \xi | | | | | | x---------x (-1,-1) | (1,-1) @endverbatim * * @subsection shapes Shape functions * \begin{array}{lll} * N1 = (1 - \xi) (1 - \eta) / 4 * & \frac{\partial N1}{\partial \xi} = - (1 - \eta) / 4 * & \frac{\partial N1}{\partial \eta} = - (1 - \xi) / 4 \\ * N2 = (1 + \xi) (1 - \eta) / 4 \\ * & \frac{\partial N2}{\partial \xi} = (1 - \eta) / 4 * & \frac{\partial N2}{\partial \eta} = - (1 + \xi) / 4 \\ * N3 = (1 + \xi) (1 + \eta) / 4 \\ * & \frac{\partial N3}{\partial \xi} = (1 + \eta) / 4 * & \frac{\partial N3}{\partial \eta} = (1 + \xi) / 4 \\ * N4 = (1 - \xi) (1 + \eta) / 4 * & \frac{\partial N4}{\partial \xi} = - (1 + \eta) / 4 * & \frac{\partial N4}{\partial \eta} = (1 - \xi) / 4 \\ * \end{array} * @f} * * @subsection quad_points Position of quadrature points * @f{eqnarray*}{ * \xi_{q0} &=& 0 \qquad \eta_{q0} = 0 * @f} */ /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_quadrangle_4>::nb_nodes_per_element; template<> UInt ElementClass<_quadrangle_4>::nb_quadrature_points; template<> UInt ElementClass<_quadrangle_4>::spatial_dimension; /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_quadrangle_4>::computeShapes(const Real * natural_coords, Real * shapes) { /// Natural coordinates const Real * c = natural_coords; shapes[0] = .25 * (1 - c[0]) * (1 - c[1]); /// N1(q_0) shapes[1] = .25 * (1 + c[0]) * (1 - c[1]); /// N2(q_0) shapes[2] = .25 * (1 + c[0]) * (1 + c[1]); /// N3(q_0) shapes[3] = .25 * (1 - c[0]) * (1 + c[1]); /// N4(q_0) } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_quadrangle_4>::computeDNDS(const Real * natural_coords, Real * dnds) { /** * @f[ * dnds = \left( * \begin{array}{cccc} * \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial \xi} * & \frac{\partial N3}{\partial \xi} & \frac{\partial N4}{\partial \xi}\\ * \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial \eta} * & \frac{\partial N3}{\partial \eta} & \frac{\partial N4}{\partial \eta} * \end{array} * \right) * @f] */ const Real * c = natural_coords; dnds[0] = - .25 * (1 - c[1]); dnds[1] = .25 * (1 - c[1]); dnds[2] = .25 * (1 + c[1]); dnds[3] = - .25 * (1 + c[1]); dnds[4] = - .25 * (1 - c[0]); dnds[5] = - .25 * (1 + c[0]); dnds[6] = .25 * (1 + c[0]); dnds[7] = .25 * (1 - c[0]); } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_quadrangle_4>::computeJacobian(const Real * dxds, const UInt dimension, Real & jac){ Real weight = 4.; if (dimension == spatial_dimension){ Real det_dxds = Math::det2(dxds); jac = det_dxds * weight; } else { AKANTU_DEBUG_ERROR("to be implemented"); } } /* -------------------------------------------------------------------------- */ template<> inline Real ElementClass<_quadrangle_4>::getInradius(const Real * coord) { Real a = Math::distance_2d(coord + 0, coord + 2); Real b = Math::distance_2d(coord + 2, coord + 4); Real c = Math::distance_2d(coord + 4, coord + 6); Real d = Math::distance_2d(coord + 6, coord + 0); // Real septimetre = (a + b + c + d) / 2.; // Real p = Math::distance_2d(coord + 0, coord + 4); // Real q = Math::distance_2d(coord + 2, coord + 6); // Real area = sqrt(4*(p*p * q*q) - (a*a + b*b + c*c + d*d)*(a*a + c*c - b*b - d*d)) / 4.; // Real h = sqrt(area); // to get a length // Real h = area / septimetre; // formula of inradius for circumscritable quadrelateral Real h = std::min(a, std::min(b, std::min(c, d))); return h; } diff --git a/fem/element_classes/element_class_segment_2.cc b/fem/element_classes/element_class_segment_2.cc index a9f335379..98bb5ea02 100644 --- a/fem/element_classes/element_class_segment_2.cc +++ b/fem/element_classes/element_class_segment_2.cc @@ -1,78 +1,92 @@ /** * @file element_class_segment_2.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jul 15 10:28:28 2010 * * @brief Specialization of the element_class class for the type _segment_2 * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * * @section DESCRIPTION * * @verbatim q --x--------|--------x---> x -1 0 1 @endverbatim * * @subsection shapes Shape functions * @f{eqnarray*}{ * w_1(x) &=& 1/2(1 - x) \\ * w_2(x) &=& 1/2(1 + x) * @f} * * @subsection quad_points Position of quadrature points * @f{eqnarray*}{ * x_{q} &=& 0 * @f} */ /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_segment_2>::nb_nodes_per_element; template<> UInt ElementClass<_segment_2>::nb_quadrature_points; template<> UInt ElementClass<_segment_2>::spatial_dimension; /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_segment_2>::computeShapes(const Real * natural_coords, Real * shapes){ /// natural coordinate Real c = natural_coords[0]; /// shape functions shapes[0] = 0.5*(1-c); shapes[1] =0.5*(1+c); } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_segment_2>::computeDNDS(__attribute__ ((unused)) const Real * natural_coords, Real * dnds){ /// dN1/de dnds[0] = - .5; /// dN2/de dnds[1] = .5; } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_segment_2>::computeJacobian(const Real * dxds, const UInt dimension, Real & jac){ if (dimension == spatial_dimension){ jac = dxds[0]; } else { jac = Math::norm2(dxds); } // multiplication by integration weight jac *= 2; } /* -------------------------------------------------------------------------- */ template<> inline Real ElementClass<_segment_2>::getInradius(const Real * coord) { return sqrt((coord[0] - coord[1])*(coord[0] - coord[1])); } diff --git a/fem/element_classes/element_class_segment_3.cc b/fem/element_classes/element_class_segment_3.cc index d67fa298e..5527b7402 100644 --- a/fem/element_classes/element_class_segment_3.cc +++ b/fem/element_classes/element_class_segment_3.cc @@ -1,93 +1,107 @@ /** * @file element_class_segment_3.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Sun Oct 3 10:28:28 2010 * * @brief Specialization of the element_class class for the type _segment_3 * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * * @section DESCRIPTION * * @verbatim -1 0 1 -----x---------x---------x-----> x 1 3 2 @endverbatim * * @subsection coords Nodes coordinates * * @f[ * \begin{array}{lll} * x_{1} = -1 & x_{2} = 1 & x_{3} = 0 * \end{array} * @f] * * @subsection shapes Shape functions * @f[ * \begin{array}{ll} * w_1(x) = \frac{x}{2}(x - 1) & w'_1(x) = x - \frac{1}{2}\\ * w_2(x) = \frac{x}{2}(x + 1) & w'_2(x) = x + \frac{1}{2}\\ * w_3(x) = 1-x^2 & w'_3(x) = -2x * \end{array} * @f] * * @subsection quad_points Position of quadrature points * @f[ * \begin{array}{ll} * x_{q1} = -1/\sqrt{3} & x_{q2} = 1/\sqrt{3} * \end{array} * @f] */ /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_segment_3>::nb_nodes_per_element; template<> UInt ElementClass<_segment_3>::nb_quadrature_points; template<> UInt ElementClass<_segment_3>::spatial_dimension; /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_segment_3>::computeShapes(const Real * natural_coords, Real * shapes){ Real c = natural_coords[0]; shapes[0] = (c - 1) * c / 2; shapes[1] = (c + 1) * c / 2; shapes[2] = 1 - c * c; } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_segment_3>::computeDNDS(const Real * natural_coords, Real * dnds){ Real c = natural_coords[0]; dnds[0] = c - .5; dnds[1] = c + .5; dnds[2] = -2 * c; } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_segment_3>::computeJacobian(const Real * dxds, const UInt dimension, Real & jac){ Real weight = 1; if (dimension == spatial_dimension){ jac = dxds[0]; } else { jac = Math::norm2(dxds); } jac *= weight; } /* -------------------------------------------------------------------------- */ template<> inline Real ElementClass<_segment_3>::getInradius(const Real * coord) { Real dist1 = sqrt((coord[0] - coord[1])*(coord[0] - coord[1])); Real dist2 = sqrt((coord[1] - coord[2])*(coord[1] - coord[2])); return dist1 < dist2 ? dist1 : dist2; } diff --git a/fem/element_classes/element_class_tetrahedron_10.cc b/fem/element_classes/element_class_tetrahedron_10.cc index 22fcaf457..6f4275d99 100644 --- a/fem/element_classes/element_class_tetrahedron_10.cc +++ b/fem/element_classes/element_class_tetrahedron_10.cc @@ -1,255 +1,269 @@ /** * @file element_class_tetrahedron_10.cc * @author Peter Spijker <peter.spijker@epfl.ch> * @date Thu Dec 1 10:28:28 2010 * * @brief Specialization of the element_class class for the type _tetrahedron_10 * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * * @section DESCRIPTION * * @verbatim \zeta ^ | (0,0,1) x |` . | ` . | ` . | ` . (0,0.5,0.5) | ` x. | q4 o ` . \eta | ` . -, (0,0,0.5) x ` x (0.5,0,0.5) - | ` x-(0,1,0) | q3 o` - ' | (0,0.5,0) - ` ' | x- ` x (0.5,0.5,0) | q1 o - o q2` ' | - ` ' | - ` ' x---------------x--------------` x-----> \xi (0,0,0) (0.5,0,0) (1,0,0) @endverbatim * * @subsection coords Nodes coordinates * * @f[ * \begin{array}{lll} * \xi_{0} = 0 & \eta_{0} = 0 & \zeta_{0} = 0 \\ * \xi_{1} = 1 & \eta_{1} = 0 & \zeta_{1} = 0 \\ * \xi_{2} = 0 & \eta_{2} = 1 & \zeta_{2} = 0 \\ * \xi_{3} = 0 & \eta_{3} = 0 & \zeta_{3} = 1 \\ * \xi_{4} = 1/2 & \eta_{4} = 0 & \zeta_{4} = 0 \\ * \xi_{5} = 1/2 & \eta_{5} = 1/2 & \zeta_{5} = 0 \\ * \xi_{6} = 0 & \eta_{6} = 1/2 & \zeta_{6} = 0 \\ * \xi_{7} = 0 & \eta_{7} = 0 & \zeta_{7} = 1/2 \\ * \xi_{8} = 1/2 & \eta_{8} = 0 & \zeta_{8} = 1/2 \\ * \xi_{9} = 0 & \eta_{9} = 1/2 & \zeta_{9} = 1/2 * \end{array} * @f] * * @subsection shapes Shape functions * @f[ * \begin{array}{llll} * N1 = (1 - \xi - \eta - \zeta) (1 - 2 \xi - 2 \eta - 2 \zeta) * & \frac{\partial N1}{\partial \xi} = 4 \xi + 4 \eta + 4 \zeta - 3 * & \frac{\partial N1}{\partial \eta} = 4 \xi + 4 \eta + 4 \zeta - 3 * & \frac{\partial N1}{\partial \zeta} = 4 \xi + 4 \eta + 4 \zeta - 3 \\ * N2 = \xi (2 \xi - 1) * & \frac{\partial N2}{\partial \xi} = 4 \xi - 1 * & \frac{\partial N2}{\partial \eta} = 0 * & \frac{\partial N2}{\partial \zeta} = 0 \\ * N3 = \eta (2 \eta - 1) * & \frac{\partial N3}{\partial \xi} = 0 * & \frac{\partial N3}{\partial \eta} = 4 \eta - 1 * & \frac{\partial N3}{\partial \zeta} = 0 \\ * N4 = \zeta (2 \zeta - 1) * & \frac{\partial N4}{\partial \xi} = 0 * & \frac{\partial N4}{\partial \eta} = 0 * & \frac{\partial N4}{\partial \zeta} = 4 \zeta - 1 \\ * N5 = 4 \xi (1 - \xi - \eta - \zeta) * & \frac{\partial N5}{\partial \xi} = 4 - 8 \xi - 4 \eta - 4 \zeta * & \frac{\partial N5}{\partial \eta} = -4 \xi * & \frac{\partial N5}{\partial \zeta} = -4 \xi \\ * N6 = 4 \xi \eta * & \frac{\partial N6}{\partial \xi} = 4 \eta * & \frac{\partial N6}{\partial \eta} = 4 \xi * & \frac{\partial N6}{\partial \zeta} = 0 \\ * N7 = 4 \eta (1 - \xi - \eta - \zeta) * & \frac{\partial N7}{\partial \xi} = -4 \eta * & \frac{\partial N7}{\partial \eta} = 4 - 4 \xi - 8 \eta - 4 \zeta * & \frac{\partial N7}{\partial \zeta} = -4 \eta \\ * N8 = 4 \zeta (1 - \xi - \eta - \zeta) * & \frac{\partial N8}{\partial \xi} = -4 \zeta * & \frac{\partial N8}{\partial \eta} = -4 \zeta * & \frac{\partial N8}{\partial \zeta} = 4 - 4 \xi - 4 \eta - 8 \zeta \\ * N9 = 4 \zeta \xi * & \frac{\partial N9}{\partial \xi} = 4 \zeta * & \frac{\partial N9}{\partial \eta} = 0 * & \frac{\partial N9}{\partial \zeta} = 4 \xi \\ * N10 = 4 \eta \zeta * & \frac{\partial N10}{\partial \xi} = 0 * & \frac{\partial N10}{\partial \eta} = 4 \zeta * & \frac{\partial N10}{\partial \zeta} = 4 \eta \\ * \end{array} * @f] * * @subsection quad_points Position of quadrature points * @f[ * a = \frac{5 - \sqrt{5}}{20}\\ * b = \frac{5 + 3 \sqrt{5}}{20} * \begin{array}{lll} * \xi_{q_0} = a & \eta_{q_0} = a & \zeta_{q_0} = a \\ * \xi_{q_1} = b & \eta_{q_1} = a & \zeta_{q_1} = a \\ * \xi_{q_2} = a & \eta_{q_2} = b & \zeta_{q_2} = a \\ * \xi_{q_3} = a & \eta_{q_3} = a & \zeta_{q_3} = b * \end{array} * @f] */ /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_tetrahedron_10>::nb_nodes_per_element; template<> UInt ElementClass<_tetrahedron_10>::nb_quadrature_points; template<> UInt ElementClass<_tetrahedron_10>::spatial_dimension; /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_tetrahedron_10>::computeShapes(const Real * natural_coords, Real * shapes){ /// Natural coordinates Real xi = natural_coords[0]; Real eta = natural_coords[1]; Real zeta = natural_coords[2]; Real sum = xi + eta + zeta; Real c0 = 1 - sum; Real c1 = 1 - 2*sum; Real c2 = 2*xi - 1; Real c3 = 2*eta - 1; Real c4 = 2*zeta - 1; /// Shape functions shapes[0] = c0 * c1; shapes[1] = xi * c2; shapes[2] = eta * c3; shapes[3] = zeta * c4; shapes[4] = 4 * xi * c0; shapes[5] = 4 * xi * eta; shapes[6] = 4 * eta * c0; shapes[7] = 4 * zeta * c0; shapes[8] = 4 * xi * zeta; shapes[9] = 4 * eta * zeta; } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_tetrahedron_10>::computeDNDS(__attribute__ ((unused)) const Real * natural_coords, Real * dnds) { /** * @f[ * dnds = \left( * \begin{array}{cccccccccc} * \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial \xi} * & \frac{\partial N3}{\partial \xi} & \frac{\partial N4}{\partial \xi} * & \frac{\partial N5}{\partial \xi} & \frac{\partial N6}{\partial \xi} * & \frac{\partial N7}{\partial \xi} & \frac{\partial N8}{\partial \xi} * & \frac{\partial N9}{\partial \xi} & \frac{\partial N10}{\partial \xi} \\ * \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial \eta} * & \frac{\partial N3}{\partial \eta} & \frac{\partial N4}{\partial \eta} * & \frac{\partial N5}{\partial \eta} & \frac{\partial N6}{\partial \eta} * & \frac{\partial N7}{\partial \eta} & \frac{\partial N8}{\partial \eta} * & \frac{\partial N9}{\partial \eta} & \frac{\partial N10}{\partial \eta} \\ * \frac{\partial N1}{\partial \zeta} & \frac{\partial N2}{\partial \zeta} * & \frac{\partial N3}{\partial \zeta} & \frac{\partial N4}{\partial \zeta} * & \frac{\partial N5}{\partial \zeta} & \frac{\partial N6}{\partial \zeta} * & \frac{\partial N7}{\partial \zeta} & \frac{\partial N8}{\partial \zeta} * & \frac{\partial N9}{\partial \zeta} & \frac{\partial N10}{\partial \zeta} * \end{array} * \right) * @f] */ /// Natural coordinates Real xi = natural_coords[0]; Real eta = natural_coords[1]; Real zeta = natural_coords[2]; Real sum = xi + eta + zeta; /// dN/dxi dnds[0] = 4 * sum - 3; dnds[1] = 4 * xi - 1; dnds[2] = 0; dnds[3] = 0; dnds[4] = 4 * (1 - sum - xi); dnds[5] = 4 * eta; dnds[6] = -4 * eta; dnds[7] = -4 * zeta; dnds[8] = 4 * zeta; dnds[9] = 0; /// dN/deta dnds[10] = 4 * sum - 3; dnds[11] = 0; dnds[12] = 4 * eta - 1; dnds[13] = 0; dnds[14] = -4 * xi; dnds[15] = 4 * xi; dnds[16] = 4 * (1 - sum - eta); dnds[17] = -4 * zeta; dnds[18] = 0; dnds[19] = 4 * zeta; /// dN/dzeta dnds[20] = 4 * sum - 3; dnds[21] = 0; dnds[22] = 0; dnds[23] = 4 * zeta - 1; dnds[24] = -4 * xi; dnds[25] = 0; dnds[26] = -4 * eta; dnds[27] = 4 * (1 - sum - zeta); dnds[28] = 4 * xi; dnds[29] = 4 * eta; } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_tetrahedron_10>::computeJacobian(const Real * dxds, const UInt dimension, Real & jac) { if (dimension == spatial_dimension){ Real weight = 1./24.; Real det_dxds = Math::det3(dxds); jac = det_dxds * weight; } else { AKANTU_DEBUG_ERROR("to be implemented"); } } /* -------------------------------------------------------------------------- */ template<> inline Real ElementClass<_tetrahedron_10>::getInradius(const Real * coord) { // Only take the four corner tetrahedra UInt tetrahedra[4][4] = { {0, 4, 6, 7}, {4, 1, 5, 8}, {6, 5, 2, 9}, {7, 8, 9, 3} }; Real inradius = std::numeric_limits<Real>::max(); for (UInt t = 0; t < 4; t++) { Real ir = Math::tetrahedron_inradius(coord + tetrahedra[t][0] * spatial_dimension, coord + tetrahedra[t][1] * spatial_dimension, coord + tetrahedra[t][2] * spatial_dimension, coord + tetrahedra[t][3] * spatial_dimension); inradius = ir < inradius ? ir : inradius; } return inradius; } diff --git a/fem/element_classes/element_class_tetrahedron_4.cc b/fem/element_classes/element_class_tetrahedron_4.cc index 355741e7c..be891fd8f 100644 --- a/fem/element_classes/element_class_tetrahedron_4.cc +++ b/fem/element_classes/element_class_tetrahedron_4.cc @@ -1,118 +1,132 @@ /** * @file element_class_tetrahedron_4.cc * @author Guillaume ANCIAUX <anciaux@epfl.ch> * @date Mon Aug 16 18:09:53 2010 * * @brief Specialization of the element_class class for the type _tetrahedron_4 * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * * @section DESCRIPTION * * @verbatim \eta ^ | x (0,0,1,0) |` | ` ° \xi | ` ° - | ` x (0,0,0,1) | q.` - ' | -` ' | - ` ' | - ` ' x------------------x-----> \zeta (1,0,0,0) (0,1,0,0) @endverbatim * * @subsection shapes Shape functions * @f{eqnarray*}{ * N1 &=& 1 - \xi - \eta - \zeta \\ * N2 &=& \xi \\ * N3 &=& \eta \\ * N4 &=& \zeta * @f} * * @subsection quad_points Position of quadrature points * @f[ * \xi_{q0} = 1/4 \qquad \eta_{q0} = 1/4 \qquad \zeta_{q0} = 1/4 * @f] */ /* -------------------------------------------------------------------------- */ // /// shape functions // shape[0] = 1./4.; /// N1(q_0) // shape[1] = 1./4.; /// N2(q_0) // shape[2] = 1./4.; /// N3(q_0) // shape[3] = 1./4.; /// N4(q_0) /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_tetrahedron_4>::nb_nodes_per_element; template<> UInt ElementClass<_tetrahedron_4>::nb_quadrature_points; template<> UInt ElementClass<_tetrahedron_4>::spatial_dimension; /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_tetrahedron_4>::computeShapes(const Real * natural_coords, Real * shapes){ Real c0 = natural_coords[1]; /// @f$ c0 = \eta @f$ Real c1 = natural_coords[2]; /// @f$ c1 = \zeta @f$ Real c2 = 1 - natural_coords[0] - natural_coords[1] - natural_coords[2];/// @f$ c2 = 1 - \xi - \eta - \zeta @f$ Real c3 = natural_coords[0]; /// @f$ c2 = \xi @f$ shapes[0] = c0; shapes[1] = c1; shapes[2] = c2; shapes[3] = c3; } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_tetrahedron_4>::computeDNDS(__attribute__ ((unused)) const Real * natural_coords, Real * dnds) { /** * @f[ * dnds = \left( * \begin{array}{cccccc} * \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial \xi} * & \frac{\partial N3}{\partial \xi} & \frac{\partial N4}{\partial \xi} \\ * \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial \eta} * & \frac{\partial N3}{\partial \eta} & \frac{\partial N4}{\partial \eta} \\ * \frac{\partial N1}{\partial \zeta} & \frac{\partial N2}{\partial \zeta} * & \frac{\partial N3}{\partial \zeta} & \frac{\partial N4}{\partial \zeta} * \end{array} * \right) * @f] */ dnds[0] = -1.; dnds[1] = 1.; dnds[2] = 0.; dnds[3] = 0.; dnds[4] = -1.; dnds[5] = 0.; dnds[6] = 1.; dnds[7] = 0.; dnds[8] = -1.; dnds[9] = 0.; dnds[10] = 0.; dnds[11] = 1.; } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_tetrahedron_4>::computeJacobian(const Real * dxds, const UInt dimension, Real & jac) { if (dimension == spatial_dimension){ Real weight = 1./6.; Real det_dxds = Math::det3(dxds); jac = det_dxds * weight; } else { AKANTU_DEBUG_ERROR("to be implemented"); } } /* -------------------------------------------------------------------------- */ template<> inline Real ElementClass<_tetrahedron_4>::getInradius(const Real * coord) { return Math::tetrahedron_inradius(coord, coord+3, coord+6, coord+9); } diff --git a/fem/element_classes/element_class_triangle_3.cc b/fem/element_classes/element_class_triangle_3.cc index 0cb022d2d..e9dc3c065 100644 --- a/fem/element_classes/element_class_triangle_3.cc +++ b/fem/element_classes/element_class_triangle_3.cc @@ -1,108 +1,122 @@ /** * @file element_class_triangle_3.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jul 15 10:28:28 2010 * * @brief Specialization of the element_class class for the type _triangle_3 * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * * @section DESCRIPTION * * @verbatim \eta ^ | x (0,0,1) |` | ` | q ` | ° ` x--------x-----> \xi (1,0,0) (0,1,0) @endverbatim * * @subsection shapes Shape functions * @f{eqnarray*}{ * N1 &=& 1 - \xi - \eta \\ * N2 &=& \xi \\ * N3 &=& \eta * @f} * * @subsection quad_points Position of quadrature points * @f{eqnarray*}{ * \xi_{q0} &=& 1/3 \qquad \eta_{q0} = 1/3 * @f} */ // /// shape functions // shape[0] = 1./3.; /// N1(q_0) // shape[1] = 1./3.; /// N2(q_0) // shape[2] = 1./3.; /// N3(q_0) /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_triangle_3>::nb_nodes_per_element; template<> UInt ElementClass<_triangle_3>::nb_quadrature_points; template<> UInt ElementClass<_triangle_3>::spatial_dimension; /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_triangle_3>::computeShapes(const Real * natural_coords, Real * shapes){ /// Natural coordinates Real c0 = 1 - natural_coords[0] - natural_coords[1]; /// @f$ c0 = 1 - \xi - \eta @f$ Real c1 = natural_coords[0]; /// @f$ c1 = \xi @f$ Real c2 = natural_coords[1]; /// @f$ c2 = \eta @f$ shapes[0] = c0; /// N1(q_0) shapes[1] = c1; /// N2(q_0) shapes[2] = c2; /// N3(q_0) } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_triangle_3>::computeDNDS(__attribute__ ((unused)) const Real * natural_coords, Real * dnds){ /** * @f[ * dnds = \left( * \begin{array}{cccccc} * \frac{\partial N1}{\partial \xi} & \frac{\partial N2}{\partial \xi} & \frac{\partial N3}{\partial \xi} \\ * \frac{\partial N1}{\partial \eta} & \frac{\partial N2}{\partial \eta} & \frac{\partial N3}{\partial \eta} * \end{array} * \right) * @f] */ dnds[0] = -1.; dnds[1] = 1.; dnds[2] = 0.; dnds[3] = -1.; dnds[4] = 0.; dnds[5] = 1.; } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_triangle_3>::computeJacobian(const Real * dxds, const UInt dimension, Real & jac){ const Real weight = .5; if (dimension == spatial_dimension){ Real det_dxds = Math::det2(dxds); jac = det_dxds; } else { Real vprod[dimension]; Math::vectorProduct3(dxds,dxds+3,vprod); jac = Math::norm3(vprod); } jac *= weight; } /* -------------------------------------------------------------------------- */ template<> inline Real ElementClass<_triangle_3>::getInradius(const Real * coord) { return Math::triangle_inradius(coord, coord+2, coord+4); } diff --git a/fem/element_classes/element_class_triangle_6.cc b/fem/element_classes/element_class_triangle_6.cc index a8dbff132..260828c70 100644 --- a/fem/element_classes/element_class_triangle_6.cc +++ b/fem/element_classes/element_class_triangle_6.cc @@ -1,193 +1,207 @@ /** * @file element_class_triangle_6.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jul 15 10:28:28 2010 * * @brief Specialization of the element_class class for the type _triangle_6 * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * * @section DESCRIPTION * * @verbatim \eta ^ | x 2 | ` | ` | . ` | q2 ` 5 x x 4 | ` | ` | .q0 q1. ` | ` x---------x---------x-----> \xi 0 3 1 @endverbatim * * @subsection coords Nodes coordinates * * @f[ * \begin{array}{ll} * \xi_{0} = 0 & \eta_{0} = 0 \\ * \xi_{1} = 1 & \eta_{1} = 0 \\ * \xi_{2} = 0 & \eta_{2} = 1 \\ * \xi_{3} = 1/2 & \eta_{3} = 0 \\ * \xi_{4} = 1/2 & \eta_{4} = 1/2 \\ * \xi_{5} = 0 & \eta_{5} = 1/2 * \end{array} * @f] * * @subsection shapes Shape functions * @f[ * \begin{array}{lll} * N1 = -(1 - \xi - \eta) (1 - 2 (1 - \xi - \eta)) * & \frac{\partial N1}{\partial \xi} = 1 - 4(1 - \xi - \eta) * & \frac{\partial N1}{\partial \eta} = 1 - 4(1 - \xi - \eta) \\ * N2 = - \xi (1 - 2 \xi) * & \frac{\partial N1}{\partial \xi} = - 1 + 4 \xi * & \frac{\partial N1}{\partial \eta} = 0 \\ * N3 = - \eta (1 - 2 \eta) * & \frac{\partial N1}{\partial \xi} = 0 * & \frac{\partial N1}{\partial \eta} = - 1 + 4 \eta \\ * N4 = 4 \xi (1 - \xi - \eta) * & \frac{\partial N1}{\partial \xi} = 4 (1 - 2 \xi - \eta) * & \frac{\partial N1}{\partial \eta} = - 4 \eta \\ * N5 = 4 \xi \eta * & \frac{\partial N1}{\partial \xi} = 4 \xi * & \frac{\partial N1}{\partial \eta} = 4 \eta \\ * N6 = 4 \eta (1 - \xi - \eta) * & \frac{\partial N1}{\partial \xi} = - 4 \xi * & \frac{\partial N1}{\partial \eta} = 4 (1 - \xi - 2 \eta) * \end{array} * @f] * * @subsection quad_points Position of quadrature points * @f{eqnarray*}{ * \xi_{q0} &=& 1/6 \qquad \eta_{q0} = 1/6 \\ * \xi_{q1} &=& 2/3 \qquad \eta_{q1} = 1/6 \\ * \xi_{q2} &=& 1/6 \qquad \eta_{q2} = 2/3 * @f} */ // /// quadrature point position // quad[0] = 1./6.; /// q0_{\xi} // quad[1] = 1./6.; /// q0_{\eta} // quad[2] = 2./3.; /// q1_{\xi} // quad[3] = 1./6.; /// q1_{\eta} // quad[4] = 1./6.; /// q2_{\xi} // quad[5] = 2./3.; /// q2_{\eta} /* -------------------------------------------------------------------------- */ template<> UInt ElementClass<_triangle_6>::nb_nodes_per_element; template<> UInt ElementClass<_triangle_6>::nb_quadrature_points; template<> UInt ElementClass<_triangle_6>::spatial_dimension; /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_triangle_6>::computeShapes(const Real * natural_coords, Real * shapes){ /// Natural coordinates Real c0 = 1 - natural_coords[0] - natural_coords[1]; /// @f$ c0 = 1 - \xi - \eta @f$ Real c1 = natural_coords[0]; /// @f$ c1 = \xi @f$ Real c2 = natural_coords[1]; /// @f$ c2 = \eta @f$ shapes[0] = c0 * (2 * c0 - 1.); shapes[1] = c1 * (2 * c1 - 1.); shapes[2] = c2 * (2 * c2 - 1.); shapes[3] = 4 * c0 * c1; shapes[4] = 4 * c1 * c2; shapes[5] = 4 * c2 * c0; } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_triangle_6>::computeDNDS(const Real * natural_coords, Real * dnds){ /** * @f[ * dnds = \left( * \begin{array}{cccccc} * \frac{\partial N1}{\partial \xi} * & \frac{\partial N2}{\partial \xi} * & \frac{\partial N3}{\partial \xi} * & \frac{\partial N4}{\partial \xi} * & \frac{\partial N5}{\partial \xi} * & \frac{\partial N6}{\partial \xi} \\ * * \frac{\partial N1}{\partial \eta} * & \frac{\partial N2}{\partial \eta} * & \frac{\partial N3}{\partial \eta} * & \frac{\partial N4}{\partial \eta} * & \frac{\partial N5}{\partial \eta} * & \frac{\partial N6}{\partial \eta} * \end{array} * \right) @f] */ /// Natural coordinates Real c0 = 1 - natural_coords[0] - natural_coords[1]; /// @f$ c0 = 1 - \xi - \eta @f$ Real c1 = natural_coords[0]; /// @f$ c1 = \xi @f$ Real c2 = natural_coords[1]; /// @f$ c2 = \eta @f$ dnds[0] = 1 - 4 * c0; dnds[1] = 4 * c1 - 1.; dnds[2] = 0.; dnds[3] = 4 * (c0 - c1); dnds[4] = 4 * c2; dnds[5] = - 4 * c2; dnds[6] = 1 - 4 * c0; dnds[7] = 0.; dnds[8] = 4 * c2 - 1.; dnds[9] = - 4 * c1; dnds[10] = 4 * c1; dnds[11] = 4 * (c0 - c2); } /* -------------------------------------------------------------------------- */ template <> inline void ElementClass<_triangle_6>::computeJacobian(const Real * dxds, const UInt dimension, Real & jac){ // if element dimension is the same as the space dimension // then jacobian factor is the determinent of dxds if (dimension == spatial_dimension){ Real weight = 1./6.; jac = Math::det2(dxds)*weight; AKANTU_DEBUG_ASSERT(jac > 0, "Negative jacobian computed, possible problem in the element node order."); } else { AKANTU_DEBUG_ERROR("to implement"); } } /* -------------------------------------------------------------------------- */ template<> inline Real ElementClass<_triangle_6>::getInradius(const Real * coord) { UInt triangles[4][3] = { {0, 3, 5}, {3, 1, 4}, {3, 4, 5}, {5, 4, 2} }; Real inradius = std::numeric_limits<Real>::max(); for (UInt t = 0; t < 4; t++) { Real ir = Math::triangle_inradius(coord + triangles[t][0] * spatial_dimension, coord + triangles[t][1] * spatial_dimension, coord + triangles[t][2] * spatial_dimension); inradius = ir < inradius ? ir : inradius; } return inradius; } diff --git a/fem/fem.cc b/fem/fem.cc index 13670bcee..2fa24b58a 100644 --- a/fem/fem.cc +++ b/fem/fem.cc @@ -1,663 +1,677 @@ /** * @file fem.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Jul 16 11:03:02 2010 * * @brief Implementation of the FEM class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "fem.hh" #include "mesh.hh" #include "element_class.hh" #include "aka_math.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ FEM::FEM(Mesh & mesh, UInt element_dimension, FEMID id, MemoryID memory_id) : Memory(memory_id), id(id) { AKANTU_DEBUG_IN(); this->element_dimension = (element_dimension != 0) ? element_dimension : mesh.getSpatialDimension(); init(); this->mesh = &mesh; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEM::init() { for(UInt t = _not_defined; t < _max_element_type; ++t) { this->shapes [t] = NULL; this->shapes_derivatives[t] = NULL; this->jacobians [t] = NULL; this->normals_on_quad_points[t] = NULL; this->ghost_shapes [t] = NULL; this->ghost_shapes_derivatives[t] = NULL; this->ghost_jacobians [t] = NULL; } } /* -------------------------------------------------------------------------- */ FEM::~FEM() { AKANTU_DEBUG_IN(); mesh = NULL; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEM::initShapeFunctions(GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * coord = mesh->getNodes().values; UInt spatial_dimension = mesh->getSpatialDimension(); const Mesh::ConnectivityTypeList & type_list = mesh->getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; UInt element_type_spatial_dimension = Mesh::getSpatialDimension(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt size_of_shapes = FEM::getShapeSize(type); UInt size_of_shapesd = FEM::getShapeDerivativesSize(type); UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); if(element_type_spatial_dimension != element_dimension) continue; UInt * elem_val; UInt nb_element; std::string ghost = ""; if(ghost_type == _not_ghost) { elem_val = mesh->getConnectivity(type).values; nb_element = mesh->getConnectivity(type).getSize(); } else { ghost = "ghost_"; elem_val = mesh->getGhostConnectivity(type).values; nb_element = mesh->getGhostConnectivity(type).getSize(); } std::stringstream sstr_shapes; sstr_shapes << id << ":" << ghost << "shapes:" << type; Vector<Real> * shapes_tmp = &(alloc<Real>(sstr_shapes.str(), nb_element*nb_quadrature_points, size_of_shapes)); std::stringstream sstr_shapesd; sstr_shapesd << id << ":" << ghost << "shapes_derivatives:" << type; Vector<Real> * shapes_derivatives_tmp = &(alloc<Real>(sstr_shapesd.str(), nb_element*nb_quadrature_points, size_of_shapesd)); std::stringstream sstr_jacobians; sstr_jacobians << id << ":" << ghost << "jacobians:" << type; Vector<Real> * jacobians_tmp = &(alloc<Real>(sstr_jacobians.str(), nb_element*nb_quadrature_points, 1)); Real * shapes_val = shapes_tmp->values; Real * shapesd_val = shapes_derivatives_tmp->values; Real * jacobians_val = jacobians_tmp->values; /* -------------------------------------------------------------------------- */ /* compute shapes when no rotation is required */ #define COMPUTE_SHAPES(type) \ do { \ Real local_coord[spatial_dimension * nb_nodes_per_element]; \ for (UInt elem = 0; elem < nb_element; ++elem) { \ int offset = elem * nb_nodes_per_element; \ for (UInt id = 0; id < nb_nodes_per_element; ++id) { \ memcpy(local_coord + id * spatial_dimension, \ coord + elem_val[offset + id] * spatial_dimension, \ spatial_dimension*sizeof(Real)); \ } \ ElementClass<type>::preComputeStandards(local_coord, \ spatial_dimension, \ shapes_val, \ shapesd_val, \ jacobians_val); \ shapes_val += size_of_shapes*nb_quadrature_points; \ shapesd_val += size_of_shapesd*nb_quadrature_points; \ jacobians_val += nb_quadrature_points; \ } \ } while(0) /* -------------------------------------------------------------------------- */ switch(type) { case _segment_2 : { COMPUTE_SHAPES(_segment_2 ); break; } case _segment_3 : { COMPUTE_SHAPES(_segment_3 ); break; } case _triangle_3 : { COMPUTE_SHAPES(_triangle_3 ); break; } case _triangle_6 : { COMPUTE_SHAPES(_triangle_6 ); break; } case _tetrahedron_4 : { COMPUTE_SHAPES(_tetrahedron_4 ); break; } case _tetrahedron_10 : { COMPUTE_SHAPES(_tetrahedron_10); break; } case _quadrangle_4 : { COMPUTE_SHAPES(_quadrangle_4 ); break; } case _point: case _not_defined: case _max_element_type: { AKANTU_DEBUG_ERROR("Wrong type : " << type); break; } } #undef COMPUTE_SHAPES if(ghost_type == _not_ghost) { shapes[type] = shapes_tmp; shapes_derivatives[type] = shapes_derivatives_tmp; jacobians[type] = jacobians_tmp; } else { ghost_shapes[type] = shapes_tmp; ghost_shapes_derivatives[type] = shapes_derivatives_tmp; ghost_jacobians[type] = jacobians_tmp; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEM::computeNormalsOnQuadPoints(GhostType ghost_type) { AKANTU_DEBUG_IN(); Real * coord = mesh->getNodes().values; UInt spatial_dimension = mesh->getSpatialDimension(); const Mesh::ConnectivityTypeList & type_list = mesh->getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; UInt element_type_spatial_dimension = Mesh::getSpatialDimension(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quad_points = FEM::getNbQuadraturePoints(type); if(element_type_spatial_dimension != element_dimension) continue; UInt * elem_val; UInt nb_element; std::string ghost = ""; if(ghost_type == _not_ghost) { elem_val = mesh->getConnectivity(type).values; nb_element = mesh->getConnectivity(type).getSize(); } else { ghost = "ghost_"; elem_val = mesh->getGhostConnectivity(type).values; nb_element = mesh->getGhostConnectivity(type).getSize(); } std::stringstream sstr_normals_on_quad; sstr_normals_on_quad << id << ":" << ghost << "normals_onquad:" << type; Vector<Real> * normals_on_quad_tmp = &(alloc<Real>(sstr_normals_on_quad.str(), nb_element*nb_quad_points, spatial_dimension)); Real * normals_on_quad_val = normals_on_quad_tmp->values; #define COMPUTE_NORMALS_ON_QUAD(type) \ do { \ Real local_coord[spatial_dimension * nb_nodes_per_element]; \ for (UInt elem = 0; elem < nb_element; ++elem) { \ int offset = elem * nb_nodes_per_element; \ for (UInt id = 0; id < nb_nodes_per_element; ++id) { \ memcpy(local_coord + id * spatial_dimension, \ coord + elem_val[offset + id] * spatial_dimension, \ spatial_dimension*sizeof(Real)); \ } \ ElementClass<type>::computeNormalsOnQuadPoint(local_coord, \ spatial_dimension, \ normals_on_quad_val); \ normals_on_quad_val += spatial_dimension*nb_quad_points; \ } \ } while(0) switch(type) { case _segment_2 : { COMPUTE_NORMALS_ON_QUAD(_segment_2 ); break; } case _segment_3 : { COMPUTE_NORMALS_ON_QUAD(_segment_3 ); break; } case _triangle_3 : { COMPUTE_NORMALS_ON_QUAD(_triangle_3 ); break; } case _triangle_6 : { COMPUTE_NORMALS_ON_QUAD(_triangle_6 ); break; } case _tetrahedron_4 : { COMPUTE_NORMALS_ON_QUAD(_tetrahedron_4 ); break; } case _tetrahedron_10 : { COMPUTE_NORMALS_ON_QUAD(_tetrahedron_10); break; } case _quadrangle_4 : { COMPUTE_NORMALS_ON_QUAD(_quadrangle_4 ); break; } case _point: case _not_defined: case _max_element_type: { AKANTU_DEBUG_ERROR("Wrong type : " << type); break; } } #undef COMPUTE_NORMALS_ON_QUAD if(ghost_type == _not_ghost) { normals_on_quad_points[type] = normals_on_quad_tmp; } else { AKANTU_DEBUG_ERROR("to be implemented"); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEM::interpolateOnQuadraturePoints(const Vector<Real> &in_u, Vector<Real> &out_uq, UInt nb_degre_of_freedom, const ElementType & type, GhostType ghost_type, const Vector<UInt> * filter_elements) const { AKANTU_DEBUG_IN(); Vector<Real> * shapes_loc; UInt nb_element; UInt * conn_val; if(ghost_type == _not_ghost) { shapes_loc = shapes[type]; nb_element = mesh->getNbElement(type); conn_val = mesh->getConnectivity(type).values; } else { shapes_loc = ghost_shapes[type]; nb_element = mesh->getNbGhostElement(type); conn_val = mesh->getGhostConnectivity(type).values; } AKANTU_DEBUG_ASSERT(shapes_loc != NULL, "No shapes for the type " << type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); UInt size_of_shapes = FEM::getShapeSize(type); AKANTU_DEBUG_ASSERT(in_u.getSize() == mesh->getNbNodes(), "The vector in_u(" << in_u.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(in_u.getNbComponent() == nb_degre_of_freedom, "The vector in_u(" << in_u.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(out_uq.getNbComponent() == nb_degre_of_freedom , "The vector out_uq(" << out_uq.getID() << ") has not the good number of component."); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } out_uq.resize(nb_element * nb_quadrature_points); Real * shape_val = shapes_loc->values; Real * u_val = in_u.values; Real * uq_val = out_uq.values; UInt offset_uq = out_uq.getNbComponent()*nb_quadrature_points; Real * shape = shape_val; Real * u = static_cast<Real *>(calloc(nb_nodes_per_element * nb_degre_of_freedom, sizeof(Real))); for (UInt el = 0; el < nb_element; ++el) { UInt el_offset = el * nb_nodes_per_element; if(filter_elements != NULL) { shape = shape_val + filter_elem_val[el] * size_of_shapes*nb_quadrature_points; el_offset = filter_elem_val[el] * nb_nodes_per_element; } for (UInt n = 0; n < nb_nodes_per_element; ++n) { memcpy(u + n * nb_degre_of_freedom, u_val + conn_val[el_offset + n] * nb_degre_of_freedom, nb_degre_of_freedom * sizeof(Real)); } /// Uq = Shape * U : matrix product Math::matrix_matrix(nb_quadrature_points, nb_degre_of_freedom, nb_nodes_per_element, shape, u, uq_val); uq_val += offset_uq; if(filter_elements == NULL) { shape += size_of_shapes*nb_quadrature_points; } } free(u); #undef INIT_VARIABLES AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEM::gradientOnQuadraturePoints(const Vector<Real> &in_u, Vector<Real> &out_nablauq, UInt nb_degre_of_freedom, const ElementType & type, GhostType ghost_type, const Vector<UInt> * filter_elements) const { AKANTU_DEBUG_IN(); Vector<Real> * shapesd_loc; UInt nb_element; UInt * conn_val; if(ghost_type == _not_ghost) { shapesd_loc = shapes_derivatives[type]; nb_element = mesh->getNbElement(type); conn_val = mesh->getConnectivity(type).values; } else { shapesd_loc = ghost_shapes_derivatives[type]; nb_element = mesh->getNbGhostElement(type); conn_val = mesh->getGhostConnectivity(type).values; } AKANTU_DEBUG_ASSERT(shapesd_loc != NULL, "No shapes for the type " << type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt size_of_shapes_derivatives = FEM::getShapeDerivativesSize(type); UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } AKANTU_DEBUG_ASSERT(in_u.getSize() == mesh->getNbNodes(), "The vector in_u(" << in_u.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(in_u.getNbComponent() == nb_degre_of_freedom , "The vector in_u(" << in_u.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(out_nablauq.getNbComponent() == nb_degre_of_freedom * element_dimension, "The vector out_nablauq(" << out_nablauq.getID() << ") has not the good number of component."); out_nablauq.resize(nb_element * nb_quadrature_points); Real * shaped_val = shapesd_loc->values; Real * u_val = in_u.values; Real * nablauq_val = out_nablauq.values; UInt offset_nablauq = nb_degre_of_freedom * element_dimension; UInt offset_shaped = nb_nodes_per_element * element_dimension; Real * shaped = shaped_val; Real * u = static_cast<Real *>(calloc(nb_nodes_per_element * nb_degre_of_freedom, sizeof(Real))); for (UInt el = 0; el < nb_element; ++el) { UInt el_offset = el * nb_nodes_per_element; if(filter_elements != NULL) { shaped = shaped_val + filter_elem_val[el] * size_of_shapes_derivatives*nb_quadrature_points; el_offset = filter_elem_val[el] * nb_nodes_per_element; } for (UInt n = 0; n < nb_nodes_per_element; ++n) { memcpy(u + n * nb_degre_of_freedom, u_val + conn_val[el_offset + n] * nb_degre_of_freedom, nb_degre_of_freedom * sizeof(Real)); } for (UInt q = 0; q < nb_quadrature_points; ++q) { /// \nabla(U) = U^t * dphi/dx Math::matrixt_matrix(nb_degre_of_freedom, element_dimension, nb_nodes_per_element, u, shaped, nablauq_val); nablauq_val += offset_nablauq; shaped += offset_shaped; } } free(u); #undef INIT_VARIABLES AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEM::integrate(const Vector<Real> & in_f, Vector<Real> &intf, UInt nb_degre_of_freedom, const ElementType & type, GhostType ghost_type, const Vector<UInt> * filter_elements) const { AKANTU_DEBUG_IN(); Vector<Real> * jac_loc; UInt nb_element; if(ghost_type == _not_ghost) { jac_loc = jacobians[type]; nb_element = mesh->getNbElement(type); } else { jac_loc = ghost_jacobians[type]; nb_element = mesh->getNbGhostElement(type); } UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } AKANTU_DEBUG_ASSERT(in_f.getSize() == nb_element * nb_quadrature_points, "The vector in_f(" << in_f.getID() << " size " << in_f.getSize() << ") has not the good size (" << nb_element << ")."); AKANTU_DEBUG_ASSERT(in_f.getNbComponent() == nb_degre_of_freedom , "The vector in_f(" << in_f.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degre_of_freedom, "The vector intf(" << intf.getID() << ") has not the good number of component."); intf.resize(nb_element); Real * in_f_val = in_f.values; Real * intf_val = intf.values; Real * jac_val = jac_loc->values; UInt offset_in_f = in_f.getNbComponent()*nb_quadrature_points; UInt offset_intf = intf.getNbComponent(); Real * jac = jac_val; for (UInt el = 0; el < nb_element; ++el) { if(filter_elements != NULL) { jac = jac_val + filter_elem_val[el] * nb_quadrature_points; } integrate(in_f_val, jac, intf_val, nb_degre_of_freedom, nb_quadrature_points); in_f_val += offset_in_f; intf_val += offset_intf; if(filter_elements == NULL) { jac += nb_quadrature_points; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real FEM::integrate(const Vector<Real> & in_f, const ElementType & type, GhostType ghost_type, const Vector<UInt> * filter_elements) const { AKANTU_DEBUG_IN(); Vector<Real> * jac_loc; UInt nb_element; if(ghost_type == _not_ghost) { jac_loc = jacobians[type]; nb_element = mesh->getNbElement(type); } else { jac_loc = ghost_jacobians[type]; nb_element = mesh->getNbGhostElement(type); } UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } AKANTU_DEBUG_ASSERT(in_f.getSize() == nb_element * nb_quadrature_points, "The vector in_f(" << in_f.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(in_f.getNbComponent() == 1, "The vector in_f(" << in_f.getID() << ") has not the good number of component."); Real intf = 0.; Real * in_f_val = in_f.values; Real * jac_val = jac_loc->values; UInt offset_in_f = in_f.getNbComponent() * nb_quadrature_points; Real * jac = jac_val; for (UInt el = 0; el < nb_element; ++el) { if(filter_elements != NULL) { jac = jac_val + filter_elem_val[el] * nb_quadrature_points; } Real el_intf = 0; integrate(in_f_val, jac, &el_intf, 1, nb_quadrature_points); intf += el_intf; in_f_val += offset_in_f; if(filter_elements == NULL) { jac += nb_quadrature_points; } } AKANTU_DEBUG_OUT(); return intf; } /* -------------------------------------------------------------------------- */ void FEM::assembleVector(const Vector<Real> & elementary_vect, Vector<Real> & nodal_values, UInt nb_degre_of_freedom, const ElementType & type, GhostType ghost_type, const Vector<UInt> * filter_elements, Real scale_factor) const { AKANTU_DEBUG_IN(); UInt nb_element; UInt * conn_val; if(ghost_type == _not_ghost) { nb_element = mesh->getNbElement(type); conn_val = mesh->getConnectivity(type).values; } else { nb_element = mesh->getNbGhostElement(type); conn_val = mesh->getGhostConnectivity(type).values; } UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_nodes = mesh->getNbNodes(); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } 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_degre_of_freedom*nb_nodes_per_element, "The vector elementary_vect(" << elementary_vect.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(nodal_values.getNbComponent() == nb_degre_of_freedom, "The vector nodal_values(" << nodal_values.getID() << ") has not the good number of component."); nodal_values.resize(nb_nodes); Real * elementary_vect_val = elementary_vect.values; Real * nodal_values_val = nodal_values.values; for (UInt el = 0; el < nb_element; ++el) { UInt el_offset = el * nb_nodes_per_element; if(filter_elements != NULL) { el_offset = filter_elem_val[el] * nb_nodes_per_element; } for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = conn_val[el_offset + n]; UInt offset_node = node * nb_degre_of_freedom; for (UInt d = 0; d < nb_degre_of_freedom; ++d) { nodal_values_val[offset_node + d] += scale_factor * elementary_vect_val[d]; } elementary_vect_val += nb_degre_of_freedom; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEM::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "FEM [" << 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 << " + connectivity type information [" << std::endl; const Mesh::ConnectivityTypeList & type_list = mesh->getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if (mesh->getSpatialDimension(*it) != element_dimension) continue; stream << space << AKANTU_INDENT << AKANTU_INDENT << " + " << *it <<" [" << std::endl; if(shapes[*it]) { shapes [*it]->printself(stream, indent + 3); shapes_derivatives[*it]->printself(stream, indent + 3); jacobians [*it]->printself(stream, indent + 3); } stream << space << AKANTU_INDENT << AKANTU_INDENT << "]" << std::endl; } stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/fem/fem.hh b/fem/fem.hh index 903a43a11..f74440a3b 100644 --- a/fem/fem.hh +++ b/fem/fem.hh @@ -1,208 +1,222 @@ /** * @file fem.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Jul 16 10:24:24 2010 * * @brief FEM class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_FEM_HH__ #define __AKANTU_FEM_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "mesh.hh" #include "element_class.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class FEM : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FEM(Mesh & mesh, UInt spatial_dimension = 0, FEMID id = "fem", MemoryID memory_id = 0); virtual ~FEM(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// pre-compute all the shape functions, their derivatives and the jacobians void initShapeFunctions(GhostType ghost_type = _not_ghost); /// build the profile of the sparse matrix corresponding to the mesh void initSparseMatrixProfile(SparseMatrixType sparse_matrix_type = _unsymmetric); /// pre-compute normals on quadrature points void computeNormalsOnQuadPoints(GhostType ghost_type = _not_ghost); /// interpolate nodal values on the quadrature points void interpolateOnQuadraturePoints(const Vector<Real> &u, Vector<Real> &uq, UInt nb_degre_of_freedom, const ElementType & type, GhostType ghost_type = _not_ghost, const Vector<UInt> * filter_elements = NULL) const; /// compute the gradient of u on the quadrature points void gradientOnQuadraturePoints(const Vector<Real> &u, Vector<Real> &nablauq, UInt nb_degre_of_freedom, const ElementType & type, GhostType ghost_type = _not_ghost, const Vector<UInt> * filter_elements = NULL) const; /// integrate f for all elements of type "type" void integrate(const Vector<Real> & f, Vector<Real> &intf, UInt nb_degre_of_freedom, const ElementType & type, GhostType ghost_type = _not_ghost, const Vector<UInt> * filter_elements = NULL) const; /// integrate f on the element "elem" of type "type" inline void integrate(const Vector<Real> & f, Real *intf, UInt nb_degre_of_freedom, const Element & elem, GhostType ghost_type = _not_ghost) const; /// integrate a scalar value on all elements of type "type" Real integrate(const Vector<Real> & f, const ElementType & type, GhostType ghost_type = _not_ghost, const Vector<UInt> * filter_elements = NULL) const; /// assemble vectors void assembleVector(const Vector<Real> & elementary_vect, Vector<Real> & nodal_values, UInt nb_degre_of_freedom, const ElementType & type, GhostType ghost_type = _not_ghost, const Vector<UInt> * filter_elements = NULL, Real scale_factor = 1) const; /// assemble matrix in the complete sparse matrix void assembleMatrix() {}; /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; private: /// initialise the class void init(); /// integrate on one element inline void integrate(Real *f, Real *jac, Real * inte, UInt nb_degre_of_freedom, UInt nb_quadrature_points) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(ElementDimension, element_dimension, UInt); /// get the mesh contained in the fem object inline Mesh & getMesh() const; /// get the size of the shapes returned by the element class static inline UInt getShapeSize(const ElementType & type); /// get the number of quadrature points static inline UInt getNbQuadraturePoints(const ElementType & type); /// get the size of the shapes derivatives returned by the element class static inline UInt getShapeDerivativesSize(const ElementType & type); /// get the in-radius of an element static inline Real getElementInradius(Real * coord, const ElementType & type); /// get a the shapes vector AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Shapes, shapes, const Vector<Real> &); /// get a the shapes derivatives vector AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ShapesDerivatives, shapes_derivatives, const Vector<Real> &); /// get the normals on quadrature points AKANTU_GET_MACRO_BY_ELEMENT_TYPE(NormalsOnQuadPoints, normals_on_quad_points, const Vector<Real> &); /// get a the ghost shapes vector AKANTU_GET_MACRO_BY_ELEMENT_TYPE(GhostShapes, ghost_shapes, const Vector<Real> &); /// get a the ghost shapes derivatives vector AKANTU_GET_MACRO_BY_ELEMENT_TYPE(GhostShapesDerivatives, ghost_shapes_derivatives, const Vector<Real> &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// id of the fem object FEMID id; /// spatial dimension of the problem UInt element_dimension; /// the mesh on which all computation are made Mesh * mesh; /// shape functions for all elements ByElementTypeReal shapes; /// shape derivatives for all elements ByElementTypeReal shapes_derivatives; /// jacobians for all elements ByElementTypeReal jacobians; /// normals at quadrature points ByElementTypeReal normals_on_quad_points; /// shape functions for all elements ByElementTypeReal ghost_shapes; /// shape derivatives for all elements ByElementTypeReal ghost_shapes_derivatives; /// jacobians for all elements ByElementTypeReal ghost_jacobians; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "fem_inline_impl.cc" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const FEM & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_FEM_HH__ */ diff --git a/fem/fem_inline_impl.cc b/fem/fem_inline_impl.cc index 0de9607f2..6ac1a2a66 100644 --- a/fem/fem_inline_impl.cc +++ b/fem/fem_inline_impl.cc @@ -1,178 +1,192 @@ /** * @file fem_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 12:21:36 2010 * * @brief Implementation of the inline functions of the FEM Class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ inline void FEM::integrate(const Vector<Real> & f, Real * intf, UInt nb_degre_of_freedom, const Element & elem, GhostType ghost_type) const { Vector<Real> * jac_loc; if(ghost_type == _not_ghost) { jac_loc = jacobians[elem.type]; } else { jac_loc = ghost_jacobians[elem.type]; } UInt nb_quadrature_points = FEM::getNbQuadraturePoints(elem.type); AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degre_of_freedom , "The vector f do not have the good number of component."); Real * f_val = f.values + elem.element * f.getNbComponent(); Real * jac_val = jac_loc->values + elem.element * nb_quadrature_points; integrate(f_val, jac_val, intf, nb_degre_of_freedom, nb_quadrature_points); } /* -------------------------------------------------------------------------- */ inline void FEM::integrate(Real *f, Real *jac, Real * inte, UInt nb_degre_of_freedom, UInt nb_quadrature_points) const { memset(inte, 0, nb_degre_of_freedom * sizeof(Real)); Real *cjac = jac; for (UInt q = 0; q < nb_quadrature_points; ++q) { for (UInt dof = 0; dof < nb_degre_of_freedom; ++dof) { inte[dof] += *f * *cjac; ++f; } ++cjac; } } /* -------------------------------------------------------------------------- */ inline Mesh & FEM::getMesh() const { return *mesh; } /* -------------------------------------------------------------------------- */ inline UInt FEM::getNbQuadraturePoints(const ElementType & type) { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = 0; #define GET_NB_QUAD_POINTS(type) \ nb_quadrature_points = ElementClass<type>::getNbQuadraturePoints() switch(type) { case _segment_2 : { GET_NB_QUAD_POINTS(_segment_2 ); break; } case _segment_3 : { GET_NB_QUAD_POINTS(_segment_3 ); break; } case _triangle_3 : { GET_NB_QUAD_POINTS(_triangle_3 ); break; } case _triangle_6 : { GET_NB_QUAD_POINTS(_triangle_6 ); break; } case _tetrahedron_4 : { GET_NB_QUAD_POINTS(_tetrahedron_4 ); break; } case _tetrahedron_10 : { GET_NB_QUAD_POINTS(_tetrahedron_10); break; } case _quadrangle_4 : { GET_NB_QUAD_POINTS(_quadrangle_4 ); break; } case _point: case _not_defined: case _max_element_type: { AKANTU_DEBUG_ERROR("Wrong type : " << type); break; } } #undef GET_NB_QUAD_POINTS AKANTU_DEBUG_OUT(); return nb_quadrature_points; } /* -------------------------------------------------------------------------- */ inline UInt FEM::getShapeSize(const ElementType & type) { AKANTU_DEBUG_IN(); UInt shape_size = 0; #define GET_SHAPE_SIZE(type) \ shape_size = ElementClass<type>::getShapeSize() switch(type) { case _segment_2 : { GET_SHAPE_SIZE(_segment_2 ); break; } case _segment_3 : { GET_SHAPE_SIZE(_segment_3 ); break; } case _triangle_3 : { GET_SHAPE_SIZE(_triangle_3 ); break; } case _triangle_6 : { GET_SHAPE_SIZE(_triangle_6 ); break; } case _tetrahedron_4 : { GET_SHAPE_SIZE(_tetrahedron_4 ); break; } case _tetrahedron_10 : { GET_SHAPE_SIZE(_tetrahedron_10); break; } case _quadrangle_4 : { GET_SHAPE_SIZE(_quadrangle_4 ); break; } case _point: case _not_defined: case _max_element_type: { AKANTU_DEBUG_ERROR("Wrong type : " << type); break; } } #undef GET_SHAPE_SIZE AKANTU_DEBUG_OUT(); return shape_size; } /* -------------------------------------------------------------------------- */ inline UInt FEM::getShapeDerivativesSize(const ElementType & type) { AKANTU_DEBUG_IN(); UInt shape_derivatives_size = 0; #define GET_SHAPE_DERIVATIVES_SIZE(type) \ shape_derivatives_size = ElementClass<type>::getShapeDerivativesSize() switch(type) { case _segment_2 : { GET_SHAPE_DERIVATIVES_SIZE(_segment_2 ); break; } case _segment_3 : { GET_SHAPE_DERIVATIVES_SIZE(_segment_3 ); break; } case _triangle_3 : { GET_SHAPE_DERIVATIVES_SIZE(_triangle_3 ); break; } case _triangle_6 : { GET_SHAPE_DERIVATIVES_SIZE(_triangle_6 ); break; } case _tetrahedron_4 : { GET_SHAPE_DERIVATIVES_SIZE(_tetrahedron_4 ); break; } case _tetrahedron_10 : { GET_SHAPE_DERIVATIVES_SIZE(_tetrahedron_10); break; } case _quadrangle_4 : { GET_SHAPE_DERIVATIVES_SIZE(_quadrangle_4 ); break; } case _point: case _not_defined: case _max_element_type: { AKANTU_DEBUG_ERROR("Wrong type : " << type); break; } } #undef GET_SHAPE_DERIVATIVES_SIZE AKANTU_DEBUG_OUT(); return shape_derivatives_size; } /* -------------------------------------------------------------------------- */ inline Real FEM::getElementInradius(Real * coord, const ElementType & type) { AKANTU_DEBUG_IN(); Real inradius = 0; #define GET_INRADIUS(type) \ inradius = ElementClass<type>::getInradius(coord); \ switch(type) { case _segment_2 : { GET_INRADIUS(_segment_2 ); break; } case _segment_3 : { GET_INRADIUS(_segment_3 ); break; } case _triangle_3 : { GET_INRADIUS(_triangle_3 ); break; } case _triangle_6 : { GET_INRADIUS(_triangle_6 ); break; } case _tetrahedron_4 : { GET_INRADIUS(_tetrahedron_4 ); break; } case _tetrahedron_10 : { GET_INRADIUS(_tetrahedron_10); break; } case _quadrangle_4 : { GET_INRADIUS(_quadrangle_4 ); break; } case _point: case _not_defined: case _max_element_type: { AKANTU_DEBUG_ERROR("Wrong type : " << type); break; } } #undef GET_INRADIUS AKANTU_DEBUG_OUT(); return inradius; } /* -------------------------------------------------------------------------- */ diff --git a/fem/mesh.cc b/fem/mesh.cc index 77e6a1c65..ac51df6b7 100644 --- a/fem/mesh.cc +++ b/fem/mesh.cc @@ -1,145 +1,159 @@ /** * @file mesh.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Jun 16 12:02:26 2010 * * @brief class handling meshes * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <sstream> /* -------------------------------------------------------------------------- */ #include "mesh.hh" #include "element_class.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void Element::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Element [" << type << ", " << element << "]"; } /* -------------------------------------------------------------------------- */ Mesh::Mesh(UInt spatial_dimension, const MeshID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), nodes_global_ids(NULL), created_nodes(true), spatial_dimension(spatial_dimension), internal_facets_mesh(NULL), types_offsets(Vector<UInt>(_max_element_type + 1, 1)), ghost_types_offsets(Vector<UInt>(_max_element_type + 1, 1)), nb_surfaces(0) { AKANTU_DEBUG_IN(); initConnectivities(); std::stringstream sstr; sstr << id << ":coordinates"; this->nodes = &(alloc<Real>(sstr.str(), 0, this->spatial_dimension)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Mesh::Mesh(UInt spatial_dimension, const VectorID & nodes_id, const MeshID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), nodes_global_ids(NULL), created_nodes(false), spatial_dimension(spatial_dimension), internal_facets_mesh(NULL), types_offsets(Vector<UInt>(_max_element_type + 1, 1)), ghost_types_offsets(Vector<UInt>(_max_element_type + 1, 1)) { AKANTU_DEBUG_IN(); initConnectivities(); this->nodes = &(getVector<Real>(nodes_id)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Mesh::Mesh(UInt spatial_dimension, Vector<Real> & nodes, const MeshID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), created_nodes(false), spatial_dimension(spatial_dimension), internal_facets_mesh(NULL), types_offsets(Vector<UInt>(_max_element_type + 1, 1)), ghost_types_offsets(Vector<UInt>(_max_element_type + 1, 1)) { AKANTU_DEBUG_IN(); initConnectivities(); this->nodes = &(nodes); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Mesh::initConnectivities() { for(UInt t = _not_defined; t < _max_element_type; ++t) { connectivities[t] = NULL; ghost_connectivities[t] = NULL; surface_id[t] = NULL; } this->types_offsets.resize(_max_element_type); } /* -------------------------------------------------------------------------- */ Mesh::~Mesh() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ // Vector<Real> & Mesh::createNormals(ElementType type) { // AKANTU_DEBUG_IN(); // AKANTU_DEBUG_ERROR("TOBEIMPLEMENTED"); // AKANTU_DEBUG_OUT(); // return *normals[type]; // } /* -------------------------------------------------------------------------- */ void Mesh::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Mesh [" << std::endl; stream << space << " + id : " << this->id << std::endl; stream << space << " + spatial dimension : " << this->spatial_dimension << std::endl; stream << space << " + nodes [" << std::endl; nodes->printself(stream, indent+2); stream << space << " ]" << std::endl; ConnectivityTypeList::const_iterator it; for(it = type_set.begin(); it != type_set.end(); ++it) { stream << space << " + connectivities ("<< *it <<") [" << std::endl; (connectivities[*it])->printself(stream, indent+2); stream << space << " ]" << std::endl; } for(it = ghost_type_set.begin(); it != ghost_type_set.end(); ++it) { stream << space << " + ghost_connectivities ("<< *it <<") [" << std::endl; (ghost_connectivities[*it])->printself(stream, indent+2); stream << space << " ]" << std::endl; } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/fem/mesh.hh b/fem/mesh.hh index e941f0f48..a6c251510 100644 --- a/fem/mesh.hh +++ b/fem/mesh.hh @@ -1,318 +1,332 @@ /** * @file mesh.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Jun 16 11:53:53 2010 * * @brief the class representing the meshes * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_HH__ #define __AKANTU_MESH_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "aka_vector.hh" #include "element_class.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /// to store data Vector<Real> by element type typedef Vector<Real> * ByElementTypeReal[_max_element_type]; /// to store data Vector<Int> by element type typedef Vector<Int> * ByElementTypeInt [_max_element_type]; /// to store data Vector<UInt> by element type typedef Vector<UInt> * ByElementTypeUInt[_max_element_type]; /* -------------------------------------------------------------------------- */ class Element { public: Element(ElementType type = _not_defined, UInt element = 0) : type(type), element(element) {}; Element(const Element & element) { this->type = element.type; this->element = element.element; } ~Element() {}; /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; public: ElementType type; UInt element; }; /* -------------------------------------------------------------------------- */ /** * @class Mesh this contain the coordinates of the nodes in the Mesh.nodes Vector, * and the connectivity. The connectivity are stored in by element types. * * To know all the element types present in a mesh you can get the Mesh::ConnectivityTypeList * * In order to loop on all element you have to loop on all types like this : * @code const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { UInt nb_element = mesh.getNbElement(*it); UInt * conn = mesh.getConnectivity(*it).values; for(UInt e = 0; e < nb_element; ++e) { ... } } @endcode */ class Mesh : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /// constructor that create nodes coordinates array Mesh(UInt spatial_dimension, const MeshID & id = "mesh", const MemoryID & memory_id = 0); /// constructor that use an existing nodes coordinates array, by knowing its ID Mesh(UInt spatial_dimension, const VectorID & nodes_id, const MeshID & id = "mesh", const MemoryID & memory_id = 0); /** * constructor that use an existing nodes coordinates * array, by getting the vector of coordinates */ Mesh(UInt spatial_dimension, Vector<Real> & nodes, const MeshID & id = "mesh", const MemoryID & memory_id = 0); virtual ~Mesh(); /// @typedef ConnectivityTypeList list of the types present in a Mesh typedef std::set<ElementType> ConnectivityTypeList; typedef Vector<Real> * NormalsMap[_max_element_type]; private: /// initialize the connectivity to NULL void initConnectivities(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; // Vector<UInt> & createConnectivity(ElementType type, UInt nb_element); // Vector<UInt> & createGhostConnectivity(ElementType type, UInt nb_element); /// create the array of normals // Vector<Real> & createNormals(ElementType type); /// convert a element to a linearized element inline UInt elementToLinearized(const Element & elem); /// convert a linearized element to an element inline Element linearizedToElement (UInt linearized_element); /// update the types offsets array for the conversions inline void updateTypesOffsets(); /// convert a element to a linearized element inline UInt ghostElementToLinearized(const Element & elem); /// convert a linearized element to an element inline Element ghostLinearizedToElement (UInt linearized_element); /// update the types offsets array for the conversions inline void updateGhostTypesOffsets(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(ID, id, const MeshID &); /// get the spatial dimension of the mesh = number of component of the coordinates AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); /// get the nodes Vector aka coordinates AKANTU_GET_MACRO(Nodes, *nodes, const Vector<Real> &); /// get the number of nodes AKANTU_GET_MACRO(NbNodes, nodes->getSize(), UInt); /// get the Vector of global ids of the nodes (only used in parallel) AKANTU_GET_MACRO(GlobalNodesIds, *nodes_global_ids, const Vector<UInt> &); /// get the number of surfaces AKANTU_GET_MACRO(NbSurfaces, nb_surfaces, UInt); /// get the connectivity Vector for a given type AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Connectivity, connectivities, const Vector<UInt> &); /// get the connecticity of ghost elements of a given type AKANTU_GET_MACRO_BY_ELEMENT_TYPE(GhostConnectivity, ghost_connectivities, const Vector<UInt> &); // AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Normals, normals, const Vector<Real> &); /// get the number of element of a type in the mesh inline UInt getNbElement(const ElementType & type) const; /// get the number of ghost element of a type in the mesh inline UInt getNbGhostElement(const ElementType & type) const; /// get the connectivity list either for the elements or the ghost elements inline const ConnectivityTypeList & getConnectivityTypeList(GhostType ghost_type = _not_ghost) const; /// get the mesh of the internal facets inline const Mesh & getInternalFacetsMesh() const; /// compute the barycenter of a given element inline void getBarycenter(UInt element, ElementType type, Real * barycenter, GhostType ghost_type = _not_ghost) const; /// get the surface values of facets inline const Vector<UInt> & getSurfaceId(const ElementType & type) const; /* ------------------------------------------------------------------------ */ /* Wrappers on ElementClass functions */ /* ------------------------------------------------------------------------ */ public: /// get the number of nodes per element for a given element type static inline UInt getNbNodesPerElement(const ElementType & type); /// get the number of nodes per element for a given element type considered as /// a first order element static inline ElementType getP1ElementType(const ElementType & type); /// get spatial dimension of a type of element static inline UInt getSpatialDimension(const ElementType & type); /// get number of facets of a given element type static inline UInt getNbFacetsPerElement(const ElementType & type); /// get number of facets of a given element type static inline UInt ** getFacetLocalConnectivity(const ElementType & type); /// get the type of the surface element associated to a given element static inline ElementType getFacetElementType(const ElementType & type); private: friend class MeshIOMSH; friend class MeshUtils; friend class Communicator; AKANTU_GET_MACRO(NodesPointer, nodes, Vector<Real> *); inline Vector<UInt> * getNodesGlobalIdsPointer(); inline Vector<UInt> * getConnectivityPointer(ElementType type); inline Vector<UInt> * getGhostConnectivityPointer(ElementType type); inline Mesh * getInternalFacetsMeshPointer(); // inline Vector<Real> * getNormalsPointer(ElementType type) const; inline Vector<UInt> * getSurfaceIdPointer(ElementType type); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// id of the mesh MeshID id; /// array of the nodes coordinates Vector<Real> * nodes; /// global node ids Vector<UInt> * nodes_global_ids; /// boolean to know if the nodes have to be deleted with the mesh or not bool created_nodes; /// all class of elements present in this mesh (for heterogenous meshes) ByElementTypeUInt connectivities; /// map to normals for all class of elements present in this mesh ByElementTypeReal normals; /// list of all existing types in the mesh ConnectivityTypeList type_set; /// the spatial dimension of this mesh UInt spatial_dimension; /// internal facets mesh Mesh * internal_facets_mesh; /// types offsets Vector<UInt> types_offsets; /// all class of elements present in this mesh (for heterogenous meshes) ByElementTypeUInt ghost_connectivities; /// list of all existing types in the mesh ConnectivityTypeList ghost_type_set; /// ghost types offsets Vector<UInt> ghost_types_offsets; /// number of surfaces present in this mesh UInt nb_surfaces; /// surface id of the surface elements in this mesh ByElementTypeUInt surface_id; }; /* -------------------------------------------------------------------------- */ /* Inline functions */ /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Element & _this) { _this.printself(stream); return stream; } #include "mesh_inline_impl.cc" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Mesh & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_MESH_HH__ */ diff --git a/fem/mesh_inline_impl.cc b/fem/mesh_inline_impl.cc index 3672c6cde..db47136a2 100644 --- a/fem/mesh_inline_impl.cc +++ b/fem/mesh_inline_impl.cc @@ -1,446 +1,460 @@ /** * @file mesh_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Jul 14 23:58:08 2010 * * @brief Implementation of the inline functions of the mesh class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ inline UInt Mesh::elementToLinearized(const Element & elem) { AKANTU_DEBUG_ASSERT(elem.type < _max_element_type && elem.element < types_offsets.values[elem.type+1], "The element " << elem << "does not exists in the mesh " << id); return types_offsets.values[elem.type] + elem.element; } /* -------------------------------------------------------------------------- */ inline Element Mesh::linearizedToElement (UInt linearized_element) { UInt t; for (t = _not_defined + 1; linearized_element > types_offsets.values[t] && t <= _max_element_type; ++t); AKANTU_DEBUG_ASSERT(t < _max_element_type, "The linearized element " << linearized_element << "does not exists in the mesh " << id); return Element((ElementType) t, linearized_element-types_offsets.values[t]); } /* -------------------------------------------------------------------------- */ inline void Mesh::updateTypesOffsets() { UInt count = 0; for (UInt t = _not_defined; t <= _max_element_type; ++t) { types_offsets.values[t] = count; count += (t == _max_element_type || connectivities[t] == NULL) ? 0 : connectivities[t]->getSize(); } } /* -------------------------------------------------------------------------- */ inline UInt Mesh::ghostElementToLinearized(const Element & elem) { AKANTU_DEBUG_ASSERT(elem.type < _max_element_type && elem.element < ghost_types_offsets.values[elem.type+1], "The ghost element " << elem << "does not exists in the mesh " << id); return ghost_types_offsets.values[elem.type] + elem.element + types_offsets.values[_max_element_type]; } /* -------------------------------------------------------------------------- */ inline Element Mesh::ghostLinearizedToElement (UInt linearized_element) { AKANTU_DEBUG_ASSERT(linearized_element >= types_offsets.values[_max_element_type], "The linearized element " << linearized_element << "is not a ghost element in the mesh " << id); linearized_element -= types_offsets.values[_max_element_type]; UInt t; for (t = _not_defined + 1; linearized_element > ghost_types_offsets.values[t] && t <= _max_element_type; ++t); AKANTU_DEBUG_ASSERT(t < _max_element_type, "The ghost linearized element " << linearized_element << "does not exists in the mesh " << id); t--; return Element((ElementType) t, linearized_element - ghost_types_offsets.values[t]); } /* -------------------------------------------------------------------------- */ inline void Mesh::updateGhostTypesOffsets() { UInt count = 0; for (UInt t = _not_defined; t <= _max_element_type; ++t) { ghost_types_offsets.values[t] = count; count += (t == _max_element_type || ghost_connectivities[t] == NULL) ? 0 : ghost_connectivities[t]->getSize(); } } /* -------------------------------------------------------------------------- */ inline const Mesh::ConnectivityTypeList & Mesh::getConnectivityTypeList(GhostType ghost_type) const { if(ghost_type == _not_ghost) return type_set; else return ghost_type_set; } /* -------------------------------------------------------------------------- */ inline Vector<UInt> * Mesh::getNodesGlobalIdsPointer() { AKANTU_DEBUG_IN(); if(nodes_global_ids == NULL) { std::stringstream sstr; sstr << id << ":nodes_global_ids"; nodes_global_ids = &(alloc<UInt>(sstr.str(), nodes->getSize(), 1)); } AKANTU_DEBUG_OUT(); return nodes_global_ids; } /* -------------------------------------------------------------------------- */ inline Vector<UInt> * Mesh::getConnectivityPointer(ElementType type) { AKANTU_DEBUG_IN(); if(connectivities[type] == NULL) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); std::stringstream sstr; sstr << id << ":connectivity:" << type; connectivities[type] = &(alloc<UInt>(sstr.str(), 0, nb_nodes_per_element)); type_set.insert(type); AKANTU_DEBUG_INFO("The connectivity vector for the type " << type << " created"); updateTypesOffsets(); } AKANTU_DEBUG_OUT(); return connectivities[type]; } /* -------------------------------------------------------------------------- */ inline Vector<UInt> * Mesh::getGhostConnectivityPointer(ElementType type) { AKANTU_DEBUG_IN(); if(ghost_connectivities[type] == NULL) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); std::stringstream sstr; sstr << id << ":ghost_connectivity:" << type; ghost_connectivities[type] = &(alloc<UInt>(sstr.str(), 0, nb_nodes_per_element)); ghost_type_set.insert(type); AKANTU_DEBUG_INFO("The connectivity vector for the type " << type << " created"); updateGhostTypesOffsets(); } AKANTU_DEBUG_OUT(); return ghost_connectivities[type]; } /* -------------------------------------------------------------------------- */ // inline Vector<Real> * Mesh::getNormalsPointer(ElementType type) const { // AKANTU_DEBUG_IN(); // AKANTU_DEBUG_OUT(); // return normals[type]; // } /* -------------------------------------------------------------------------- */ inline const Mesh & Mesh::getInternalFacetsMesh() const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); if (!internal_facets_mesh) AKANTU_DEBUG_ERROR("internal facets mesh was not created before access => use mesh utils to that purpose"); return *internal_facets_mesh; } /* -------------------------------------------------------------------------- */ inline Mesh * Mesh::getInternalFacetsMeshPointer() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); if (!internal_facets_mesh){ std::stringstream name(this->id); name << ":internalfacets"; internal_facets_mesh = new Mesh(this->spatial_dimension-1,*this->nodes,name.str()); } return internal_facets_mesh; } /* -------------------------------------------------------------------------- */ inline Vector<UInt> * Mesh::getSurfaceIdPointer(ElementType type) { AKANTU_DEBUG_IN(); if(surface_id[type] == NULL) { std::stringstream sstr; sstr << id << ":surface_id:" << type; surface_id[type] = &(alloc<UInt>(sstr.str(), 0, 1)); AKANTU_DEBUG_INFO("The surface id vector for the type " << type << " created"); } AKANTU_DEBUG_OUT(); return surface_id[type]; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbElement(const ElementType & type) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(connectivities[type] != NULL, "No element of kind : " << type << " in " << id); AKANTU_DEBUG_OUT(); return connectivities[type]->getSize(); } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbGhostElement(const ElementType & type) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(ghost_connectivities[type] != NULL, "No element of kind : " << type << " in " << id); AKANTU_DEBUG_OUT(); return ghost_connectivities[type]->getSize(); } /* -------------------------------------------------------------------------- */ inline void Mesh::getBarycenter(UInt element, ElementType type, Real * barycenter, GhostType ghost_type) const { AKANTU_DEBUG_IN(); UInt * conn_val; if (ghost_type == _not_ghost) { conn_val = getConnectivity(type).values; } else { conn_val = getGhostConnectivity(type).values; } UInt nb_nodes_per_element = getNbNodesPerElement(type); Real local_coord[spatial_dimension * nb_nodes_per_element]; UInt offset = element * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { memcpy(local_coord + n * spatial_dimension, nodes->values + conn_val[offset + n] * spatial_dimension, spatial_dimension*sizeof(Real)); } Math::barycenter(local_coord, nb_nodes_per_element, spatial_dimension, barycenter); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline const Vector<UInt> & Mesh::getSurfaceId(const ElementType & type) const{ AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(surface_id[type] != NULL, "No element of kind : " << type << " in " << id); AKANTU_DEBUG_OUT(); return *surface_id[type]; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbNodesPerElement(const ElementType & type) { AKANTU_DEBUG_IN(); UInt nb_nodes_per_element = 0; #define GET_NB_NODES_PER_ELEMENT(type) \ nb_nodes_per_element = ElementClass<type>::getNbNodesPerElement() switch(type) { case _segment_2 : { GET_NB_NODES_PER_ELEMENT(_segment_2 ); break; } case _segment_3 : { GET_NB_NODES_PER_ELEMENT(_segment_3 ); break; } case _triangle_3 : { GET_NB_NODES_PER_ELEMENT(_triangle_3 ); break; } case _triangle_6 : { GET_NB_NODES_PER_ELEMENT(_triangle_6 ); break; } case _tetrahedron_4 : { GET_NB_NODES_PER_ELEMENT(_tetrahedron_4 ); break; } case _tetrahedron_10 : { GET_NB_NODES_PER_ELEMENT(_tetrahedron_10); break; } case _quadrangle_4 : { GET_NB_NODES_PER_ELEMENT(_quadrangle_4 ); break; } case _point : { GET_NB_NODES_PER_ELEMENT(_point ); break; } case _not_defined: case _max_element_type: { AKANTU_DEBUG_ERROR("Wrong type : " << type); break; } } #undef GET_NB_NODES_PER_ELEMENT AKANTU_DEBUG_OUT(); return nb_nodes_per_element; } /* -------------------------------------------------------------------------- */ inline ElementType Mesh::getP1ElementType(const ElementType & type) { AKANTU_DEBUG_IN(); ElementType element_p1 = _not_defined; #define GET_ELEMENT_P1(type) \ element_p1 = ElementClass<type>::getP1ElementType() switch(type) { case _segment_2 : { GET_ELEMENT_P1(_segment_2 ); break; } case _segment_3 : { GET_ELEMENT_P1(_segment_3 ); break; } case _triangle_3 : { GET_ELEMENT_P1(_triangle_3 ); break; } case _triangle_6 : { GET_ELEMENT_P1(_triangle_6 ); break; } case _tetrahedron_4 : { GET_ELEMENT_P1(_tetrahedron_4 ); break; } case _tetrahedron_10 : { GET_ELEMENT_P1(_tetrahedron_10); break; } case _quadrangle_4 : { GET_ELEMENT_P1(_quadrangle_4 ); break; } case _point : { GET_ELEMENT_P1(_point ); break; } case _not_defined: case _max_element_type: { AKANTU_DEBUG_ERROR("Wrong type : " << type); break; } } #undef GET_NB_NODES_PER_ELEMENT_P1 AKANTU_DEBUG_OUT(); return element_p1; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getSpatialDimension(const ElementType & type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = 0; #define GET_SPATIAL_DIMENSION(type) \ spatial_dimension = ElementClass<type>::getSpatialDimension() switch(type) { case _segment_2 : { GET_SPATIAL_DIMENSION(_segment_2 ); break; } case _segment_3 : { GET_SPATIAL_DIMENSION(_segment_3 ); break; } case _triangle_3 : { GET_SPATIAL_DIMENSION(_triangle_3 ); break; } case _triangle_6 : { GET_SPATIAL_DIMENSION(_triangle_6 ); break; } case _tetrahedron_4 : { GET_SPATIAL_DIMENSION(_tetrahedron_4 ); break; } case _tetrahedron_10 : { GET_SPATIAL_DIMENSION(_tetrahedron_10); break; } case _quadrangle_4 : { GET_SPATIAL_DIMENSION(_quadrangle_4 ); break; } case _point : { GET_SPATIAL_DIMENSION(_point ); break; } case _not_defined: case _max_element_type: { AKANTU_DEBUG_ERROR("Wrong type : " << type); break; } } #undef GET_SPATIAL_DIMENSION AKANTU_DEBUG_OUT(); return spatial_dimension; } /* -------------------------------------------------------------------------- */ inline ElementType Mesh::getFacetElementType(const ElementType & type) { AKANTU_DEBUG_IN(); ElementType surface_type = _not_defined; #define GET_FACET_TYPE(type) \ surface_type = ElementClass<type>::getFacetElementType() switch(type) { case _segment_2 : { GET_FACET_TYPE(_segment_2 ); break; } case _segment_3 : { GET_FACET_TYPE(_segment_3 ); break; } case _triangle_3 : { GET_FACET_TYPE(_triangle_3 ); break; } case _triangle_6 : { GET_FACET_TYPE(_triangle_6 ); break; } case _tetrahedron_4 : { GET_FACET_TYPE(_tetrahedron_4 ); break; } case _tetrahedron_10 : { GET_FACET_TYPE(_tetrahedron_10); break; } case _quadrangle_4 : { GET_FACET_TYPE(_quadrangle_4 ); break; } case _point : { GET_FACET_TYPE(_point ); break; } case _not_defined: case _max_element_type: { AKANTU_DEBUG_ERROR("Wrong type : " << type); break; } } #undef GET_FACET_TYPE AKANTU_DEBUG_OUT(); return surface_type; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbFacetsPerElement(const ElementType & type) { AKANTU_DEBUG_IN(); UInt n_facet = 0; #define GET_NB_FACET(type) \ n_facet = ElementClass<type>::getNbFacetsPerElement() switch(type) { case _segment_2 : { GET_NB_FACET(_segment_2 ); break; } case _segment_3 : { GET_NB_FACET(_segment_3 ); break; } case _triangle_3 : { GET_NB_FACET(_triangle_3 ); break; } case _triangle_6 : { GET_NB_FACET(_triangle_6 ); break; } case _tetrahedron_4 : { GET_NB_FACET(_tetrahedron_4 ); break; } case _tetrahedron_10 : { GET_NB_FACET(_tetrahedron_10); break; } case _quadrangle_4 : { GET_NB_FACET(_quadrangle_4 ); break; } case _point : { GET_NB_FACET(_point ); break; } case _not_defined: case _max_element_type: { AKANTU_DEBUG_ERROR("Wrong type : " << type); break; } } #undef GET_NB_FACET AKANTU_DEBUG_OUT(); return n_facet; } /* -------------------------------------------------------------------------- */ inline UInt ** Mesh::getFacetLocalConnectivity(const ElementType & type) { AKANTU_DEBUG_IN(); UInt ** facet_conn = NULL; #define GET_FACET_CON(type) \ facet_conn = ElementClass<type>::getFacetLocalConnectivityPerElement() switch(type) { case _segment_2 : { GET_FACET_CON(_segment_2 ); break; } case _segment_3 : { GET_FACET_CON(_segment_3 ); break; } case _triangle_3 : { GET_FACET_CON(_triangle_3 ); break; } case _triangle_6 : { GET_FACET_CON(_triangle_6 ); break; } case _tetrahedron_4 : { GET_FACET_CON(_tetrahedron_4 ); break; } case _tetrahedron_10 : { GET_FACET_CON(_tetrahedron_10); break; } case _quadrangle_4 : { GET_FACET_CON(_quadrangle_4 ); break; } case _point : { GET_FACET_CON(_point ); break; } case _not_defined: case _max_element_type: { AKANTU_DEBUG_ERROR("Wrong type : " << type); break; } } #undef GET_FACET_CON AKANTU_DEBUG_OUT(); return facet_conn; } diff --git a/mesh_utils/mesh_io.cc b/mesh_utils/mesh_io.cc index f1e8f035a..9589d1f94 100644 --- a/mesh_utils/mesh_io.cc +++ b/mesh_utils/mesh_io.cc @@ -1,35 +1,49 @@ /** * @file mesh_io.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Jul 14 16:51:22 2010 * * @brief common part for all mesh io classes * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh_io.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MeshIO::MeshIO() { canReadSurface = false; canReadExtendedData = false; } /* -------------------------------------------------------------------------- */ MeshIO::~MeshIO() { } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/mesh_utils/mesh_io.hh b/mesh_utils/mesh_io.hh index afd53342b..c1ae759d5 100644 --- a/mesh_utils/mesh_io.hh +++ b/mesh_utils/mesh_io.hh @@ -1,69 +1,83 @@ /** * @file mesh_io.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Jun 18 10:27:42 2010 * * @brief interface of a mesh io class, reader and writer * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_IO_HH__ #define __AKANTU_MESH_IO_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class MeshIO { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshIO(); virtual ~MeshIO(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// read a mesh from the file virtual void read(const std::string & filename, Mesh & mesh) = 0; /// write a mesh to a file virtual void write(const std::string & filename, const Mesh & mesh) = 0; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: bool canReadSurface; bool canReadExtendedData; // std::string filename; // Mesh & mesh; }; __END_AKANTU__ #endif /* __AKANTU_MESH_IO_HH__ */ #include "mesh_io_msh.hh" diff --git a/mesh_utils/mesh_io/mesh_io_msh.cc b/mesh_utils/mesh_io/mesh_io_msh.cc index 2e0667444..837d57262 100644 --- a/mesh_utils/mesh_io/mesh_io_msh.cc +++ b/mesh_utils/mesh_io/mesh_io_msh.cc @@ -1,396 +1,410 @@ /** * @file mesh_io_msh.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Jun 18 11:36:35 2010 * * @brief Read/Write for MSH files generated by gmsh * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* ----------------------------------------------------------------------------- Version (Legacy) 1.0 $NOD number-of-nodes node-number x-coord y-coord z-coord ... $ENDNOD $ELM number-of-elements elm-number elm-type reg-phys reg-elem number-of-nodes node-number-list ... $ENDELM ----------------------------------------------------------------------------- Version 2.1 $MeshFormat version-number file-type data-size $EndMeshFormat $Nodes number-of-nodes node-number x-coord y-coord z-coord ... $EndNodes $Elements number-of-elements elm-number elm-type number-of-tags < tag > ... node-number-list ... $EndElements $PhysicalNames number-of-names physical-dimension physical-number "physical-name" ... $EndPhysicalNames $NodeData number-of-string-tags < "string-tag" > ... number-of-real-tags < real-tag > ... number-of-integer-tags < integer-tag > ... node-number value ... ... $EndNodeData $ElementData number-of-string-tags < "string-tag" > ... number-of-real-tags < real-tag > ... number-of-integer-tags < integer-tag > ... elm-number value ... ... $EndElementData $ElementNodeData number-of-string-tags < "string-tag" > ... number-of-real-tags < real-tag > ... number-of-integer-tags < integer-tag > ... elm-number number-of-nodes-per-element value ... ... $ElementEndNodeData ----------------------------------------------------------------------------- elem-type 1: 2-node line. 2: 3-node triangle. 3: 4-node quadrangle. 4: 4-node tetrahedron. 5: 8-node hexahedron. 6: 6-node prism. 7: 5-node pyramid. 8: 3-node second order line 9: 6-node second order triangle 10: 9-node second order quadrangle 11: 10-node second order tetrahedron 12: 27-node second order hexahedron 13: 18-node second order prism 14: 14-node second order pyramid 15: 1-node point. 16: 8-node second order quadrangle 17: 20-node second order hexahedron 18: 15-node second order prism 19: 13-node second order pyramid 20: 9-node third order incomplete triangle 21: 10-node third order triangle 22: 12-node fourth order incomplete triangle 23: 15-node fourth order triangle 24: 15-node fifth order incomplete triangle 25: 21-node fifth order complete triangle 26: 4-node third order edge 27: 5-node fourth order edge 28: 6-node fifth order edge 29: 20-node third order tetrahedron 30: 35-node fourth order tetrahedron 31: 56-node fifth order tetrahedron -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Constant arrays initialisation */ /* -------------------------------------------------------------------------- */ UInt MeshIOMSH::_read_order[_max_element_type][MAX_NUMBER_OF_NODE_PER_ELEMENT] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // _not_defined { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, // _line1 { 0, 1, 2, 0, 0, 0, 0, 0, 0, 0 }, // _line2 { 0, 1, 2, 0, 0, 0, 0, 0, 0, 0 }, // _triangle_3 { 0, 1, 2, 3, 4, 5, 6, 0, 0, 0 }, // _triangle_6 { 0, 1, 2, 3, 4, 0, 0, 0, 0, 0 }, // _tetrahedron_4 { 0, 1, 2, 3, 4, 5, 6, 7, 9, 8 }, // _tetrahedron_10 { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0 }, // _quadrangle_4 }; UInt MeshIOMSH::_msh_nodes_per_elem[16] = { 0, // element types began at 1 2, 3, 4, 4, 8, 6, 5, // 1st order 3, 6, 9, 10, 27, 18, 14, // 2st order 1 }; ElementType MeshIOMSH::_msh_to_akantu_element_types[16] = { _not_defined, // element types began at 1 _segment_2, _triangle_3, _quadrangle_4, _tetrahedron_4, // 1st order _not_defined, _not_defined, _not_defined, _segment_3, _triangle_6, _not_defined, _tetrahedron_10, // 2nd order _not_defined, _not_defined, _not_defined, _not_defined }; // MeshIOMSH::MSHElementType MeshIOMSH::_akantu_to_msh_element_types[_max_element_type] = // { // _msh_not_defined, // _not_defined // _msh_segment_2, // _segment_2 // _msh_segment_3, // _segment_3 // _msh_triangle_3, // _triangle_3 // _msh_triangle_6, // _triangle_6 // _msh_tetrahedron_4, // _tetrahedron_4 // _msh_tetrahedron_10 // _tetrahedron_10 // }; /* -------------------------------------------------------------------------- */ /* Methods Implentations */ /* -------------------------------------------------------------------------- */ MeshIOMSH::MeshIOMSH() { canReadSurface = false; canReadExtendedData = false; } /* -------------------------------------------------------------------------- */ MeshIOMSH::~MeshIOMSH() { } /* -------------------------------------------------------------------------- */ void MeshIOMSH::read(const std::string & filename, Mesh & mesh) { std::ifstream infile; infile.open(filename.c_str()); std::string line; UInt first_node_number = 0, last_node_number = 0, file_format = 1, current_line = 0; if(!infile.good()) { AKANTU_DEBUG_ERROR("Cannot open file " << filename); } while(infile.good()) { std::getline(infile, line); current_line++; /// read the header if(line == "$MeshFormat") { std::getline(infile, line); /// the format line std::getline(infile, line); /// the end of block line current_line += 2; file_format = 2; } /// read all nodes if(line == "$Nodes" || line == "$NOD") { UInt nb_nodes; std::getline(infile, line); std::stringstream sstr(line); sstr >> nb_nodes; current_line++; Vector<Real> & nodes = const_cast<Vector<Real> &>(mesh.getNodes()); nodes.resize(nb_nodes); UInt index; Real coord[3]; UInt spatial_dimension = nodes.getNbComponent(); /// for each node, read the coordinates for(UInt i = 0; i < nb_nodes; ++i) { UInt offset = i * spatial_dimension; std::getline(infile, line); std::stringstream sstr_node(line); sstr_node >> index >> coord[0] >> coord[1] >> coord[2]; current_line++; first_node_number = first_node_number < index ? first_node_number : index; last_node_number = last_node_number > index ? last_node_number : index; /// read the coordinates for(UInt j = 0; j < spatial_dimension; ++j) nodes.values[offset + j] = coord[j]; } std::getline(infile, line); /// the end of block line } /// read all elements if(line == "$Elements" || line == "$ELM") { UInt nb_elements; std::getline(infile, line); std::stringstream sstr(line); sstr >> nb_elements; current_line++; Int index; UInt msh_type; ElementType akantu_type, akantu_type_old = _not_defined; Vector<UInt> *connectivity = NULL; UInt node_per_element = 0; for(UInt i = 0; i < nb_elements; ++i) { std::getline(infile, line); std::stringstream sstr_elem(line); current_line++; sstr_elem >> index; sstr_elem >> msh_type; /// get the connectivity vector depending on the element type akantu_type = _msh_to_akantu_element_types[msh_type]; if(akantu_type == _not_defined) continue; if(akantu_type != akantu_type_old) { connectivity = mesh.getConnectivityPointer(akantu_type); connectivity->resize(0); node_per_element = connectivity->getNbComponent(); akantu_type_old = akantu_type; } /// read tags informations if(file_format == 2) { UInt nb_tags; sstr_elem >> nb_tags; for(UInt j = 0; j < nb_tags; ++j) { Int tag; sstr_elem >> tag; ///@todo read to get extended information on elements } } else if (file_format == 1) { Int tag; sstr_elem >> tag; //reg-phys sstr_elem >> tag; //reg-elem sstr_elem >> tag; //number-of-nodes } UInt local_connect[node_per_element]; for(UInt j = 0; j < node_per_element; ++j) { UInt node_index; sstr_elem >> node_index; AKANTU_DEBUG_ASSERT(node_index <= last_node_number, "Node number not in range : line " << current_line); node_index -= first_node_number + 1; local_connect[_read_order[akantu_type][j]] = node_index; } connectivity->push_back(local_connect); } std::getline(infile, line); /// the end of block line } if((line[0] == '$') && (line.find("End") == std::string::npos)) { AKANTU_DEBUG_WARNING("Unsuported block_kind " << line << " at line " << current_line); } } infile.close(); } /* -------------------------------------------------------------------------- */ void MeshIOMSH::write(const std::string & filename, const Mesh & mesh) { std::ofstream outfile; const Vector<Real> & nodes = mesh.getNodes(); outfile.open(filename.c_str()); outfile << "$MeshFormat" << std::endl; outfile << "2 0 8" << std::endl;; outfile << "$EndMeshFormat" << std::endl;; outfile << "$Nodes" << std::endl;; outfile << nodes.getSize() << std::endl;; outfile << std::uppercase; for(UInt i = 0; i < nodes.getSize(); ++i) { Int offset = i * nodes.getNbComponent(); outfile << i+1; for(UInt j = 0; j < nodes.getNbComponent(); ++j) { outfile << " " << nodes.values[offset + j]; } if(nodes.getNbComponent() == 2) outfile << " " << 0.; outfile << std::endl;; } outfile << std::nouppercase; outfile << "$EndNodes" << std::endl;; outfile << "$Elements" << std::endl;; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; Int nb_elements = 0; for(it = type_list.begin(); it != type_list.end(); ++it) { const Vector<UInt> & connectivity = mesh.getConnectivity(*it); nb_elements += connectivity.getSize(); } outfile << nb_elements << std::endl; UInt element_idx = 1; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; const Vector<UInt> & connectivity = mesh.getConnectivity(type); for(UInt i = 0; i < connectivity.getSize(); ++i) { UInt offset = i * connectivity.getNbComponent(); outfile << element_idx << " " << type << " 3 0 0 0"; for(UInt j = 0; j < connectivity.getNbComponent(); ++j) { outfile << " " << connectivity.values[offset + j]; } outfile << std::endl; } element_idx++; } outfile << "$EndElements" << std::endl;; outfile.close(); } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/mesh_utils/mesh_io/mesh_io_msh.hh b/mesh_utils/mesh_io/mesh_io_msh.hh index a8a7cc9cc..9efb1a1a3 100644 --- a/mesh_utils/mesh_io/mesh_io_msh.hh +++ b/mesh_utils/mesh_io/mesh_io_msh.hh @@ -1,97 +1,111 @@ /** * @file mesh_io_msh.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Jun 18 11:30:59 2010 * * @brief Read/Write for MSH files * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_IO_MSH_HH__ #define __AKANTU_MESH_IO_MSH_HH__ /* -------------------------------------------------------------------------- */ #include "mesh_io.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class MeshIOMSH : public MeshIO { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshIOMSH(); virtual ~MeshIOMSH(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// read a mesh from the file virtual void read(const std::string & filename, Mesh & mesh); /// write a mesh to a file virtual void write(const std::string & filename, const Mesh & mesh); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// MSH element types enum MSHElementType { _msh_not_defined = 0, _msh_segment_2 = 1, // 2-node line. _msh_triangle_3 = 2, // 3-node triangle. _msh_quadrangle_1 = 3, // 4-node quadrangle. _msh_tetrahedron_4 = 4, // 4-node tetrahedron. _msh_hexaedron_1 = 5, // 8-node hexahedron. _msh_prism_1 = 6, // 6-node prism. _msh_pyramid_1 = 7, // 5-node pyramid. _msh_segment_3 = 8, // 3-node second order line _msh_triangle_6 = 9, // 6-node second order triangle _msh_quadrangle_2 = 10, // 9-node second order quadrangle _msh_tetrahedron_10 = 11, // 10-node second order tetrahedron _msh_hexaedron_2 = 12, // 27-node second order hexahedron _msh_prism_2 = 13, // 18-node second order prism _msh_pyramid_2 = 14, // 14-node second order pyramid _msh_point = 15 // 1-node point. }; #define MAX_NUMBER_OF_NODE_PER_ELEMENT 10 // tetrahedron of second order /// order in witch element as to be read static UInt _read_order[_max_element_type][MAX_NUMBER_OF_NODE_PER_ELEMENT]; /// number of nodes per msh element static UInt _msh_nodes_per_elem[16]; // 16 = number of recognized // msh element types +1 (for 0) /// correspondance between msh element types and akantu element types static ElementType _msh_to_akantu_element_types[16]; /// correspondance between akantu element types and msh element types static MSHElementType _akantu_to_msh_element_types[_max_element_type]; }; __END_AKANTU__ #endif /* __AKANTU_MESH_IO_MSH_HH__ */ diff --git a/mesh_utils/mesh_partition.cc b/mesh_utils/mesh_partition.cc index e8afb0050..484514842 100644 --- a/mesh_utils/mesh_partition.cc +++ b/mesh_utils/mesh_partition.cc @@ -1,260 +1,274 @@ /** * @file mesh_partition.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Aug 16 17:16:59 2010 * * @brief implementation of common part of all partitioner * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "mesh_partition.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MeshPartition::MeshPartition(const Mesh & mesh, UInt spatial_dimension, const MemoryID & memory_id) : Memory(memory_id), id("MeshPartitioner"), mesh(mesh), spatial_dimension(spatial_dimension) { AKANTU_DEBUG_IN(); for(UInt type = _not_defined; type < _max_element_type; ++type) { partitions[type] = NULL; ghost_partitions[type] = NULL; ghost_partitions_offset[type] = NULL; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ MeshPartition::~MeshPartition() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * conversion in c++ of a the GENDUALMETIS (mesh.c) function wrote by George in * Metis (University of Minnesota) */ void MeshPartition::buildDualGraph(Vector<Int> & dxadj, Vector<Int> & dadjncy) { AKANTU_DEBUG_IN(); const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); UInt nb_types = type_list.size(); UInt nb_good_types = 0; UInt nb_nodes_per_element[nb_types]; UInt nb_nodes_per_element_p1[nb_types]; UInt magic_number[nb_types]; UInt * conn_val[nb_types]; UInt nb_element[nb_types]; Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != mesh.getSpatialDimension()) continue; ElementType type_p1 = Mesh::getP1ElementType(type); nb_nodes_per_element[nb_good_types] = Mesh::getNbNodesPerElement(type); nb_nodes_per_element_p1[nb_good_types] = Mesh::getNbNodesPerElement(type_p1); conn_val[nb_good_types] = mesh.getConnectivity(type).values; nb_element[nb_good_types] = mesh.getConnectivity(type).getSize(); magic_number[nb_good_types] = Mesh::getNbNodesPerElement(Mesh::getFacetElementType(type_p1)); nb_good_types++; } Vector<UInt> node_offset; Vector<UInt> node_index; MeshUtils::buildNode2Elements(mesh, node_offset, node_index); UInt * node_offset_val = node_offset.values; UInt * node_index_val = node_index.values; UInt nb_total_element = 0; UInt nb_total_node_element = 0; for (UInt t = 0; t < nb_good_types; ++t) { nb_total_element += nb_element[t]; nb_total_node_element += nb_element[t]*nb_nodes_per_element_p1[t]; } dxadj.resize(nb_total_element + 1); dadjncy.resize(nb_total_node_element); Int * dxadj_val = dxadj.values; Int * dadjncy_val = dadjncy.values; /// initialize the dxadj array for (UInt t = 0, linerized_el = 0; t < nb_good_types; ++t) for (UInt el = 0; el < nb_element[t]; ++el, ++linerized_el) dxadj_val[linerized_el] = nb_nodes_per_element_p1[t]; /// convert the dxadj_val array in a csr one for (UInt i = 1; i < nb_total_element; ++i) dxadj_val[i] += dxadj_val[i-1]; for (UInt i = nb_total_element; i > 0; --i) dxadj_val[i] = dxadj_val[i-1]; dxadj_val[0] = 0; /// weight map to determine adjacency UInt index[200], weight[200]; /// key, value UInt mask = (1 << 11) - 1; /// hash function Int * mark = new Int[mask + 1]; /// collision detector for (UInt i = 0; i < mask + 1; ++i) mark[i] = -1; for (UInt t = 0, linerized_el = 0; t < nb_good_types; ++t) { for (UInt el = 0; el < nb_element[t]; ++el, ++linerized_el) { UInt el_offset = el*nb_nodes_per_element[t]; /// fill the weight map UInt m = 0; for (UInt n = 0; n < nb_nodes_per_element_p1[t]; ++n) { UInt node = conn_val[t][el_offset + n]; for (UInt k = node_offset_val[node + 1] - 1; k >= node_offset_val[node]; --k) { UInt current_el = node_index_val[k]; if(current_el <= linerized_el) break; UInt mark_offset = current_el & mask; Int current_mark = mark[mark_offset]; if(current_mark == -1) { /// if element not in map index[m] = current_el; weight[m] = 1; mark[mark_offset] = m++; } else if (index[current_mark] == current_el) { /// if element already in map weight[current_mark]++; } else { /// if element already in map but collision in the keys UInt i; for (i = 0; i < m; ++i) { if(index[i] == current_el) { weight[i]++; break; } } if(i == m) { index[m] = current_el; weight[m++] = 1; } } } } /// each element with a weight of the size of a facet are adjacent for (UInt n = 0; n < m; ++n) { if(weight[n] == magic_number[t]) { UInt adjacent_el = index[n]; dadjncy_val[dxadj_val[linerized_el]++] = adjacent_el; dadjncy_val[dxadj_val[adjacent_el ]++] = linerized_el; } mark[index[n] & mask] = -1; } } } Int k_start = 0; for (UInt t = 0, linerized_el = 0, j = 0; t < nb_good_types; ++t) for (UInt el = 0; el < nb_element[t]; ++el, ++linerized_el) { for (Int k = k_start; k < dxadj_val[linerized_el]; ++k, ++j) dadjncy_val[j] = dadjncy_val[k]; dxadj_val[linerized_el] = j; k_start += nb_nodes_per_element_p1[t]; } for (UInt i = nb_total_element; i > 0; --i) dxadj_val[i] = dxadj_val[i-1]; dxadj_val[0] = 0; delete [] mark; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartition::fillPartitionInformations(const Mesh & mesh, const Int * linearized_partitions) { AKANTU_DEBUG_IN(); Vector<UInt> node_offset; Vector<UInt> node_index; MeshUtils::buildNode2Elements(mesh, node_offset, node_index); UInt * node_offset_val = node_offset.values; UInt * node_index_val = node_index.values; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt linearized_el = 0; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != mesh.getSpatialDimension()) continue; UInt nb_element = mesh.getNbElement(*it); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); std::stringstream sstr; sstr << mesh.getID() << ":partition:" << type; std::stringstream sstr_gi; sstr_gi << mesh.getID() << ":ghost_partition_offset:" << type; std::stringstream sstr_g; sstr_g << mesh.getID() << ":ghost_partition:" << type; partitions [type] = &(alloc<UInt>(sstr.str(), nb_element, 1, 0)); ghost_partitions_offset[type] = &(alloc<UInt>(sstr_gi.str(), nb_element + 1, 1, 0)); ghost_partitions [type] = &(alloc<UInt>(sstr_g.str(), 0, 1, 0)); const Vector<UInt> & connectivity = mesh.getConnectivity(type); for (UInt el = 0; el < nb_element; ++el, ++linearized_el) { UInt part = linearized_partitions[linearized_el]; partitions[type]->values[el] = part; std::list<UInt> list_adj_part; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity.values[el * nb_nodes_per_element + n]; for (UInt ne = node_offset_val[node]; ne < node_offset_val[node + 1]; ++ne) { UInt adj_el = node_index_val[ne]; UInt adj_part = linearized_partitions[adj_el]; if(part != adj_part) { list_adj_part.push_back(adj_part); } } } list_adj_part.sort(); list_adj_part.unique(); for(std::list<UInt>::iterator adj_it = list_adj_part.begin(); adj_it != list_adj_part.end(); ++adj_it) { ghost_partitions[type]->push_back(*adj_it); ghost_partitions_offset[type]->values[el]++; } } /// convert the ghost_partitions_offset array in an offset array for (UInt i = 1; i < nb_element; ++i) ghost_partitions_offset[type]->values[i] += ghost_partitions_offset[type]->values[i-1]; for (UInt i = nb_element; i > 0; --i) ghost_partitions_offset[type]->values[i] = ghost_partitions_offset[type]->values[i-1]; ghost_partitions_offset[type]->values[0] = 0; } AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/mesh_utils/mesh_partition.hh b/mesh_utils/mesh_partition.hh index 0f9cdca10..7d0cafb43 100644 --- a/mesh_utils/mesh_partition.hh +++ b/mesh_utils/mesh_partition.hh @@ -1,111 +1,125 @@ /** * @file mesh_partition.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Aug 12 16:24:40 2010 * * @brief tools to partitionate a mesh * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_PARTITION_HH__ #define __AKANTU_MESH_PARTITION_HH__ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class MeshPartition : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshPartition(const Mesh & mesh, UInt spatial_dimension, const MemoryID & memory_id = 0); virtual ~MeshPartition(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void partitionate(UInt nb_part) = 0; virtual void reorder() = 0; /// function to print the contain of the class //virtual void printself(std::ostream & stream, int indent = 0) const = 0; protected: /// build the dual graph of the mesh, for all element of spatial_dimension void buildDualGraph(Vector<Int> & dxadj, Vector<Int> & dadjncy); /// fill the partitions array with a given linearized partition information void fillPartitionInformations(const Mesh & mesh, const Int * linearized_partitions); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Partition, partitions, const Vector<UInt> &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(GhostPartition, ghost_partitions, const Vector<UInt> &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(GhostPartitionOffset, ghost_partitions_offset, const Vector<UInt> &); AKANTU_GET_MACRO(NbPartition, nb_partitions, UInt); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id std::string id; /// the mesh to partition const Mesh & mesh; /// dimension of the elements to consider in the mesh UInt spatial_dimension; /// number of partitions UInt nb_partitions; /// partition numbers ByElementTypeUInt partitions; ByElementTypeUInt ghost_partitions; ByElementTypeUInt ghost_partitions_offset; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "mesh_partition_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const MeshPartition & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_MESH_PARTITION_HH__ */ diff --git a/mesh_utils/mesh_partition/mesh_partition_scotch.cc b/mesh_utils/mesh_partition/mesh_partition_scotch.cc index 3a3a58165..f63513164 100644 --- a/mesh_utils/mesh_partition/mesh_partition_scotch.cc +++ b/mesh_utils/mesh_partition/mesh_partition_scotch.cc @@ -1,362 +1,376 @@ /** * @file mesh_partition_scotch.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Aug 13 11:54:11 2010 * * @brief implementation of the MeshPartitionScotch class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdio> #include <fstream> /* -------------------------------------------------------------------------- */ #include "mesh_partition_scotch.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MeshPartitionScotch::MeshPartitionScotch(const Mesh & mesh, UInt spatial_dimension, const MemoryID & memory_id) : MeshPartition(mesh, spatial_dimension, memory_id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SCOTCH_Mesh * MeshPartitionScotch::createMesh() { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes = mesh.getNbNodes(); UInt total_nb_element = 0; UInt nb_edge = 0; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); total_nb_element += nb_element; nb_edge += nb_element * nb_nodes_per_element; } SCOTCH_Num vnodbas = 0; SCOTCH_Num vnodnbr = nb_nodes; SCOTCH_Num velmbas = vnodnbr; SCOTCH_Num velmnbr = total_nb_element; SCOTCH_Num * verttab = new SCOTCH_Num[vnodnbr + velmnbr + 1]; SCOTCH_Num * vendtab = verttab + 1; SCOTCH_Num * velotab = NULL; SCOTCH_Num * vnlotab = NULL; SCOTCH_Num * vlbltab = NULL; memset(verttab, 0, (vnodnbr + velmnbr + 1) * sizeof(SCOTCH_Num)); for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); const Vector<UInt> & connectivity = mesh.getConnectivity(type); /// count number of occurrence of each node for (UInt el = 0; el < nb_element; ++el) { UInt * conn_val = connectivity.values + el * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { verttab[*(conn_val++)]++; } } } /// convert the occurrence array in a csr one for (UInt i = 1; i < nb_nodes; ++i) verttab[i] += verttab[i-1]; for (UInt i = nb_nodes; i > 0; --i) verttab[i] = verttab[i-1]; verttab[0] = 0; /// rearrange element to get the node-element list SCOTCH_Num edgenbr = verttab[vnodnbr] + nb_edge; SCOTCH_Num * edgetab = new SCOTCH_Num[edgenbr]; UInt linearized_el = 0; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); const Vector<UInt> & connectivity = mesh.getConnectivity(type); for (UInt el = 0; el < nb_element; ++el, ++linearized_el) { UInt * conn_val = connectivity.values + el * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) edgetab[verttab[*(conn_val++)]++] = linearized_el + velmbas; } } for (UInt i = nb_nodes; i > 0; --i) verttab[i] = verttab[i-1]; verttab[0] = 0; SCOTCH_Num * verttab_tmp = verttab + vnodnbr + 1; SCOTCH_Num * edgetab_tmp = edgetab + verttab[vnodnbr]; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != mesh.getSpatialDimension()) continue; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); const Vector<UInt> & connectivity = mesh.getConnectivity(type); for (UInt el = 0; el < nb_element; ++el) { *verttab_tmp = *(verttab_tmp - 1) + nb_nodes_per_element; verttab_tmp++; UInt * conn = connectivity.values + el * nb_nodes_per_element; for (UInt i = 0; i < nb_nodes_per_element; ++i) { *(edgetab_tmp++) = *(conn++) + vnodbas; } } } SCOTCH_Mesh * meshptr = new SCOTCH_Mesh; SCOTCH_meshInit(meshptr); SCOTCH_meshBuild(meshptr, velmbas, vnodbas, velmnbr, vnodnbr, verttab, vendtab, velotab, vnlotab, vlbltab, edgenbr, edgetab); /// Check the mesh AKANTU_DEBUG_ASSERT(SCOTCH_meshCheck(meshptr) == 0, "Scotch mesh is not consistent"); #ifndef AKANTU_NDEBUG if (AKANTU_DEBUG_TEST(dblDump)) { /// save initial graph FILE *fmesh = fopen("ScotchMesh.msh", "w"); SCOTCH_meshSave(meshptr, fmesh); fclose(fmesh); /// write geometry file std::ofstream fgeominit; fgeominit.open("GeomMeshFile.xyz"); fgeominit << spatial_dimension << std::endl << nb_nodes << std::endl; const Vector<Real> & nodes = mesh.getNodes(); Real * nodes_val = nodes.values; for (UInt i = 0; i < nb_nodes; ++i) { fgeominit << i << " "; for (UInt s = 0; s < spatial_dimension; ++s) fgeominit << *(nodes_val++) << " "; fgeominit << std::endl;; } fgeominit.close(); } #endif AKANTU_DEBUG_OUT(); return meshptr; } /* -------------------------------------------------------------------------- */ void MeshPartitionScotch::destroyMesh(SCOTCH_Mesh * meshptr) { AKANTU_DEBUG_IN(); SCOTCH_Num velmbas, vnodbas, vnodnbr, velmnbr, *verttab, *vendtab, *velotab, *vnlotab, *vlbltab, edgenbr, *edgetab, degrptr; SCOTCH_meshData(meshptr, &velmbas, &vnodbas, &velmnbr, &vnodnbr, &verttab, &vendtab, &velotab, &vnlotab, &vlbltab, &edgenbr, &edgetab, °rptr); delete [] verttab; delete [] edgetab; SCOTCH_meshExit(meshptr); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartitionScotch::partitionate(UInt nb_part) { AKANTU_DEBUG_IN(); nb_partitions = nb_part; AKANTU_DEBUG_INFO("Partitioning the mesh " << mesh.getID() << " in " << nb_part << " parts."); Vector<Int> dxadj; Vector<Int> dadjncy; buildDualGraph(dxadj, dadjncy); /// variables that will hold our structures in scotch format SCOTCH_Graph scotch_graph; SCOTCH_Strat scotch_strat; /// description number and arrays for struct mesh for scotch SCOTCH_Num baseval = 0; //base numbering for element and //nodes (0 -> C , 1 -> fortran) SCOTCH_Num vertnbr = dxadj.getSize() - 1; //number of vertexes SCOTCH_Num *parttab; //array of partitions SCOTCH_Num edgenbr = dxadj.values[vertnbr]; //twice the number of "edges" //(an "edge" bounds two nodes) SCOTCH_Num * verttab = dxadj.values; //array of start indices in edgetab SCOTCH_Num * vendtab = NULL; //array of after-last indices in edgetab SCOTCH_Num * velotab = NULL; //integer load associated with //every vertex ( optional ) SCOTCH_Num * edlotab = NULL; //integer load associated with //every edge ( optional ) SCOTCH_Num * edgetab = dadjncy.values; // adjacency array of every vertex SCOTCH_Num * vlbltab = NULL; // vertex label array (optional) /// Allocate space for Scotch arrays parttab = new SCOTCH_Num[vertnbr]; /// Initialize the strategy structure SCOTCH_stratInit (&scotch_strat); /// Initialize the graph structure SCOTCH_graphInit(&scotch_graph); /// Build the graph from the adjacency arrays SCOTCH_graphBuild(&scotch_graph, baseval, vertnbr, verttab, vendtab, velotab, vlbltab, edgenbr, edgetab, edlotab); /// Check the graph AKANTU_DEBUG_ASSERT(SCOTCH_graphCheck(&scotch_graph) == 0, "Graph to partition is not consistent"); #ifndef AKANTU_NDEBUG if (AKANTU_DEBUG_TEST(dblDump)) { /// save initial graph FILE *fgraphinit = fopen("GraphIniFile.grf", "w"); SCOTCH_graphSave(&scotch_graph,fgraphinit); fclose(fgraphinit); /// write geometry file std::ofstream fgeominit; fgeominit.open("GeomIniFile.xyz"); fgeominit << spatial_dimension << std::endl << vertnbr << std::endl; const Vector<Real> & nodes = mesh.getNodes(); const Mesh::ConnectivityTypeList & f_type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator f_it; UInt out_linerized_el = 0; for(f_it = f_type_list.begin(); f_it != f_type_list.end(); ++f_it) { ElementType type = *f_it; if(Mesh::getSpatialDimension(type) != mesh.getSpatialDimension()) continue; UInt nb_element = mesh.getNbElement(*f_it); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); const Vector<UInt> & connectivity = mesh.getConnectivity(type); Real mid[spatial_dimension] ; for (UInt el = 0; el < nb_element; ++el) { memset(mid, 0, spatial_dimension*sizeof(Real)); for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity.values[nb_nodes_per_element * el + n]; for (UInt s = 0; s < spatial_dimension; ++s) mid[s] += ((Real) nodes.values[node * spatial_dimension + s]) / ((Real) nb_nodes_per_element); } fgeominit << out_linerized_el++ << " "; for (UInt s = 0; s < spatial_dimension; ++s) fgeominit << mid[s] << " "; fgeominit << std::endl;; } } fgeominit.close(); } #endif /// Partition the mesh SCOTCH_graphPart(&scotch_graph, nb_part, &scotch_strat, parttab); /// Check the graph AKANTU_DEBUG_ASSERT(SCOTCH_graphCheck(&scotch_graph) == 0, "Partitioned graph is not consistent"); #ifndef AKANTU_NDEBUG if (AKANTU_DEBUG_TEST(dblDump)) { /// save the partitioned graph FILE *fgraph=fopen("GraphFile.grf", "w"); SCOTCH_graphSave(&scotch_graph, fgraph); fclose(fgraph); /// save the partition map std::ofstream fmap; fmap.open("MapFile.map"); fmap << vertnbr << std::endl; for (Int i = 0; i < vertnbr; i++) fmap << i << " " << parttab[i] << std::endl; fmap.close(); } #endif /// free the scotch data structures SCOTCH_stratExit(&scotch_strat); SCOTCH_graphFree(&scotch_graph); SCOTCH_graphExit(&scotch_graph); fillPartitionInformations(mesh, parttab); delete [] parttab; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartitionScotch::reorder() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Reordering the mesh " << mesh.getID()); SCOTCH_Mesh * scotch_mesh = createMesh(); destroyMesh(scotch_mesh); AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/mesh_utils/mesh_partition/mesh_partition_scotch.hh b/mesh_utils/mesh_partition/mesh_partition_scotch.hh index d1ef82812..34c2278f8 100644 --- a/mesh_utils/mesh_partition/mesh_partition_scotch.hh +++ b/mesh_utils/mesh_partition/mesh_partition_scotch.hh @@ -1,90 +1,104 @@ /** * @file mesh_partition_scotch.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Aug 13 10:00:06 2010 * * @brief mesh partitioning based on libScotch * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_PARTITION_SCOTCH_HH__ #define __AKANTU_MESH_PARTITION_SCOTCH_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh_partition.hh" #ifndef AKANTU_SCOTCH_NO_EXTERN extern "C" { #endif #include <scotch.h> #ifndef AKANTU_SCOTCH_NO_EXTERN } #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class MeshPartitionScotch : public MeshPartition { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshPartitionScotch(const Mesh & mesh, UInt spatial_dimension, const MemoryID & memory_id = 0); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void partitionate(UInt nb_part); virtual void reorder(); /// function to print the contain of the class //virtual void printself(std::ostream & stream, int indent = 0) const; private: SCOTCH_Mesh * createMesh(); void destroyMesh(SCOTCH_Mesh * meshptr); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ // #include "mesh_partition_scotch_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const MeshPartitionScotch & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_MESH_PARTITION_SCOTCH_HH__ */ diff --git a/mesh_utils/mesh_utils.cc b/mesh_utils/mesh_utils.cc index d083e2307..f55c88042 100644 --- a/mesh_utils/mesh_utils.cc +++ b/mesh_utils/mesh_utils.cc @@ -1,475 +1,489 @@ /** * @file mesh_utils.cc * @author Guillaume ANCIAUX <anciaux@lsmscluster1.epfl.ch> * @date Wed Aug 18 14:21:00 2010 * * @brief All mesh utils necessary for various tasks * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "mesh_utils.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2Elements(const Mesh & mesh, Vector<UInt> & node_offset, Vector<UInt> & node_to_elem, UInt spatial_dimension) { AKANTU_DEBUG_IN(); if (spatial_dimension == 0) spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes = mesh.getNbNodes(); const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt nb_types = type_list.size(); UInt nb_good_types = 0; UInt nb_nodes_per_element[nb_types]; UInt nb_nodes_per_element_p1[nb_types]; UInt * conn_val[nb_types]; UInt nb_element[nb_types]; ElementType type_p1; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; nb_nodes_per_element[nb_good_types] = Mesh::getNbNodesPerElement(type); type_p1 = Mesh::getP1ElementType(type); nb_nodes_per_element_p1[nb_good_types] = Mesh::getNbNodesPerElement(type_p1); conn_val[nb_good_types] = mesh.getConnectivity(type).values; nb_element[nb_good_types] = mesh.getConnectivity(type).getSize(); nb_good_types++; } AKANTU_DEBUG_ASSERT(nb_good_types != 0, "Some elements must be found in right dimension to compute facets!"); /// array for the node-element list node_offset.resize(nb_nodes + 1); UInt * node_offset_val = node_offset.values; /// count number of occurrence of each node memset(node_offset_val, 0, (nb_nodes + 1)*sizeof(UInt)); for (UInt t = 0; t < nb_good_types; ++t) { for (UInt el = 0; el < nb_element[t]; ++el) { UInt el_offset = el*nb_nodes_per_element[t]; for (UInt n = 0; n < nb_nodes_per_element_p1[t]; ++n) { node_offset_val[conn_val[t][el_offset + n]]++; } } } /// convert the occurrence array in a csr one for (UInt i = 1; i < nb_nodes; ++i) node_offset_val[i] += node_offset_val[i-1]; for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i] = node_offset_val[i-1]; node_offset_val[0] = 0; /// rearrange element to get the node-element list node_to_elem.resize(node_offset_val[nb_nodes]); UInt * node_to_elem_val = node_to_elem.values; for (UInt t = 0, linearized_el = 0; t < nb_good_types; ++t) for (UInt el = 0; el < nb_element[t]; ++el, ++linearized_el) { UInt el_offset = el*nb_nodes_per_element[t]; for (UInt n = 0; n < nb_nodes_per_element_p1[t]; ++n) node_to_elem_val[node_offset_val[conn_val[t][el_offset + n]]++] = linearized_el; } for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i] = node_offset_val[i-1]; node_offset_val[0] = 0; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2ElementsByElementType(const Mesh & mesh, ElementType type, Vector<UInt> & node_offset, Vector<UInt> & node_to_elem) { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_elements = mesh.getConnectivity(type).getSize(); UInt * conn_val = mesh.getConnectivity(type).values; /// array for the node-element list node_offset.resize(nb_nodes + 1); UInt * node_offset_val = node_offset.values; memset(node_offset_val, 0, (nb_nodes + 1)*sizeof(UInt)); /// count number of occurrence of each node for (UInt el = 0; el < nb_elements; ++el) for (UInt n = 0; n < nb_nodes_per_element; ++n) node_offset_val[conn_val[nb_nodes_per_element*el + n]]++; /// convert the occurrence array in a csr one for (UInt i = 1; i < nb_nodes; ++i) node_offset_val[i] += node_offset_val[i-1]; for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i] = node_offset_val[i-1]; node_offset_val[0] = 0; /// save the element index in the node-element list node_to_elem.resize(node_offset_val[nb_nodes]); UInt * node_to_elem_val = node_to_elem.values; for (UInt el = 0; el < nb_elements; ++el) for (UInt n = 0; n < nb_nodes_per_element; ++n) { node_to_elem_val[node_offset_val[conn_val[nb_nodes_per_element*el + n]]] = el; node_offset_val[conn_val[nb_nodes_per_element*el + n]]++; } /// rearrange node_offset to start with 0 for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i] = node_offset_val[i-1]; node_offset_val[0] = 0; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildFacets(Mesh & mesh, bool boundary_flag, bool internal_flag){ AKANTU_DEBUG_IN(); Vector<UInt> node_offset; Vector<UInt> node_to_elem; buildNode2Elements(mesh,node_offset,node_to_elem); // std::cout << "node offset " << std::endl << node_offset << std::endl; // std::cout << "node to elem " << std::endl << node_to_elem << std::endl; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt nb_types = type_list.size(); UInt nb_good_types = 0; UInt nb_nodes_per_element[nb_types]; UInt nb_nodes_per_facet[nb_types]; UInt nb_facets[nb_types]; UInt ** node_in_facet[nb_types]; Vector<UInt> * connectivity_facets[nb_types]; Vector<UInt> * connectivity_internal_facets[nb_types]; UInt * conn_val[nb_types]; UInt nb_element[nb_types]; ElementType facet_type; Mesh * internal_facets_mesh = NULL; UInt spatial_dimension = mesh.getSpatialDimension(); if (internal_flag) internal_facets_mesh = mesh.getInternalFacetsMeshPointer(); for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) != spatial_dimension) continue; nb_nodes_per_element[nb_good_types] = mesh.getNbNodesPerElement(type); facet_type = mesh.getFacetElementType(type); nb_facets[nb_good_types] = mesh.getNbFacetsPerElement(type); node_in_facet[nb_good_types] = mesh.getFacetLocalConnectivity(type); nb_nodes_per_facet[nb_good_types] = mesh.getNbNodesPerElement(facet_type); if (boundary_flag){ // getting connectivity of boundary facets connectivity_facets[nb_good_types] = mesh.getConnectivityPointer(facet_type); connectivity_facets[nb_good_types]->resize(0); } if (internal_flag){ // getting connectivity of internal facets connectivity_internal_facets[nb_good_types] = internal_facets_mesh->getConnectivityPointer(facet_type); connectivity_internal_facets[nb_good_types]->resize(0); } conn_val[nb_good_types] = mesh.getConnectivity(type).values; nb_element[nb_good_types] = mesh.getConnectivity(type).getSize(); nb_good_types++; } Vector<UInt> counter; /// count number of occurrence of each node for (UInt t = 0,linearized_el = 0; t < nb_good_types; ++t) { for (UInt el = 0; el < nb_element[t]; ++el, ++linearized_el) { UInt el_offset = el*nb_nodes_per_element[t]; for (UInt f = 0; f < nb_facets[t]; ++f) { //build the nodes involved in facet 'f' UInt facet_nodes[nb_nodes_per_facet[t]]; for (UInt n = 0; n < nb_nodes_per_facet[t]; ++n) { UInt node_facet = node_in_facet[t][f][n]; facet_nodes[n] = conn_val[t][el_offset + node_facet]; } //our reference is the first node UInt * first_node_elements = node_to_elem.values+node_offset.values[facet_nodes[0]]; UInt first_node_nelements = node_offset.values[facet_nodes[0]+1]- node_offset.values[facet_nodes[0]]; counter.resize(first_node_nelements); memset(counter.values,0,sizeof(UInt)*first_node_nelements); //loop over the other nodes to search intersecting elements for (UInt n = 1; n < nb_nodes_per_facet[t]; ++n) { UInt * node_elements = node_to_elem.values+node_offset.values[facet_nodes[n]]; UInt node_nelements = node_offset.values[facet_nodes[n]+1]- node_offset.values[facet_nodes[n]]; for (UInt el1 = 0; el1 < first_node_nelements; ++el1) { for (UInt el2 = 0; el2 < node_nelements; ++el2) { if (first_node_elements[el1] == node_elements[el2]) { ++counter.values[el1]; break; } } if (counter.values[el1] == nb_nodes_per_facet[t]) break; } } bool connected_facet = false; //the connected elements are those for which counter is n_facet // UInt connected_element = -1; for (UInt el1 = 0; el1 < counter.getSize(); el1++) { UInt el_index = node_to_elem.values[node_offset.values[facet_nodes[0]]+el1]; if (counter.values[el1] == nb_nodes_per_facet[t]-1 && el_index > linearized_el){ // connected_element = el_index; AKANTU_DEBUG(dblDump,"connecting elements " << linearized_el << " and " << el_index); if (internal_flag) connectivity_internal_facets[t]->push_back(facet_nodes); } if (counter.values[el1] == nb_nodes_per_facet[t]-1 && el_index != linearized_el) connected_facet = true; } if (!connected_facet) { AKANTU_DEBUG(dblDump,"facet " << f << " in element " << linearized_el << " is a boundary"); if (boundary_flag) connectivity_facets[t]->push_back(facet_nodes); } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ // void MeshUtils::buildNormals(Mesh & mesh,UInt spatial_dimension){ // AKANTU_DEBUG_IN(); // const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); // Mesh::ConnectivityTypeList::const_iterator it; // UInt nb_types = type_list.size(); // UInt nb_nodes_per_element[nb_types]; // UInt nb_nodes_per_element_p1[nb_types]; // UInt nb_good_types = 0; // Vector<UInt> * connectivity[nb_types]; // Vector<Real> * normals[nb_types]; // if (spatial_dimension == 0) spatial_dimension = mesh.getSpatialDimension(); // for(it = type_list.begin(); it != type_list.end(); ++it) { // ElementType type = *it; // ElementType type_p1 = mesh.getP1ElementType(type); // if(mesh.getSpatialDimension(type) != spatial_dimension) continue; // nb_nodes_per_element[nb_good_types] = mesh.getNbNodesPerElement(type); // nb_nodes_per_element_p1[nb_good_types] = mesh.getNbNodesPerElement(type_p1); // // getting connectivity // connectivity[nb_good_types] = mesh.getConnectivityPointer(type); // if (!connectivity[nb_good_types]) // AKANTU_DEBUG_ERROR("connectivity is not allocatted : this should probably not have happened"); // //getting array of normals // normals[nb_good_types] = mesh.getNormalsPointer(type); // if(normals[nb_good_types]) // normals[nb_good_types]->resize(0); // else // normals[nb_good_types] = &mesh.createNormals(type); // nb_good_types++; // } // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void MeshUtils::renumberMeshNodes(Mesh & mesh, UInt * local_connectivities, UInt nb_local_element, UInt nb_ghost_element, ElementType type, Vector<UInt> & nodes_numbers) { AKANTU_DEBUG_IN(); nodes_numbers.resize(0); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt * conn = local_connectivities; /// renumber the nodes for (UInt el = 0; el < nb_local_element + nb_ghost_element; ++el) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { Int nn = nodes_numbers.find(*conn); if(nn == -1) { nodes_numbers.push_back(*conn); *conn = nodes_numbers.getSize() - 1; } else { *conn = nn; } *conn++; } } /// copy the renumbered connectivity to the right place Vector<UInt> * local_conn = mesh.getConnectivityPointer(type); local_conn->resize(nb_local_element); memcpy(local_conn->values, local_connectivities, nb_local_element * nb_nodes_per_element * sizeof(UInt)); Vector<UInt> * ghost_conn = mesh.getGhostConnectivityPointer(type); ghost_conn->resize(nb_ghost_element); memcpy(ghost_conn->values, local_connectivities + nb_local_element * nb_nodes_per_element, nb_ghost_element * nb_nodes_per_element * sizeof(UInt)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildSurfaceID(Mesh & mesh) { AKANTU_DEBUG_IN(); Vector<UInt> node_offset; Vector<UInt> node_to_elem; /// Get list of surface elements UInt spatial_dimension = mesh.getSpatialDimension(); buildNode2Elements(mesh, node_offset, node_to_elem, spatial_dimension-1); /// Find which types of elements have been linearized const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt nb_types = type_list.size(); ElementType lin_element_type[nb_types]; UInt nb_lin_types = 0; UInt nb_nodes_per_element[nb_types]; UInt nb_nodes_per_element_p1[nb_types]; UInt * conn_val[nb_types]; UInt nb_element[nb_types]; ElementType type_p1; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; ElementType facet_type = mesh.getFacetElementType(type); lin_element_type[nb_lin_types] = facet_type; nb_nodes_per_element[nb_lin_types] = Mesh::getNbNodesPerElement(facet_type); type_p1 = Mesh::getP1ElementType(facet_type); nb_nodes_per_element_p1[nb_lin_types] = Mesh::getNbNodesPerElement(type_p1); conn_val[nb_lin_types] = mesh.getConnectivity(facet_type).values; nb_element[nb_lin_types] = mesh.getConnectivity(facet_type).getSize(); nb_lin_types++; } for (UInt i = 1; i < nb_lin_types; ++i) nb_element[i] += nb_element[i+1]; for (UInt i = nb_lin_types; i > 0; --i) nb_element[i] = nb_element[i-1]; nb_element[0] = 0; /// Find close surfaces Vector<Int> surface_value_id(1, nb_element[nb_lin_types], -1); Int * surf_val = surface_value_id.values; UInt nb_surfaces = 0; UInt nb_cecked_elements; UInt nb_elements_to_ceck; UInt * elements_to_ceck = new UInt [nb_element[nb_lin_types]]; memset(elements_to_ceck, 0, nb_element[nb_lin_types]*sizeof(UInt)); for (UInt lin_el = 0; lin_el < nb_element[nb_lin_types]; ++lin_el) { if(surf_val[lin_el] != -1) continue; /* Surface id already assigned */ /* First element of new surface */ surf_val[lin_el] = nb_surfaces; nb_cecked_elements = 0; nb_elements_to_ceck = 1; memset(elements_to_ceck, 0, nb_element[nb_lin_types]*sizeof(UInt)); elements_to_ceck[0] = lin_el; // Find others elements belonging to this surface while(nb_cecked_elements < nb_elements_to_ceck) { UInt ceck_lin_el = elements_to_ceck[nb_cecked_elements]; // Transform linearized index of element into ElementType one UInt lin_type_nb = 0; while (ceck_lin_el >= nb_element[lin_type_nb+1]) lin_type_nb++; UInt ceck_el = ceck_lin_el - nb_element[lin_type_nb]; // Get connected elements UInt el_offset = ceck_el*nb_nodes_per_element[lin_type_nb]; for (UInt n = 0; n < nb_nodes_per_element_p1[lin_type_nb]; ++n) { UInt node_id = conn_val[lin_type_nb][el_offset + n]; for (UInt i = node_offset.values[node_id]; i < node_offset.values[node_id+1]; ++i) if(surf_val[node_to_elem.values[i]] == -1) { /* Found new surface element */ surf_val[node_to_elem.values[i]] = nb_surfaces; elements_to_ceck[nb_elements_to_ceck] = node_to_elem.values[i]; nb_elements_to_ceck++; } } nb_cecked_elements++; } nb_surfaces++; } delete [] elements_to_ceck; /// Transform local linearized element index in the global one for (UInt i = 0; i < nb_lin_types; ++i) nb_element[i] = nb_element[i+1] - nb_element[i]; UInt el_offset = 0; for (UInt type_it = 0; type_it < nb_lin_types; ++type_it) { ElementType type = lin_element_type[type_it]; Vector<UInt> * surf_id_type = mesh.getSurfaceIdPointer(type); surf_id_type->resize(nb_element[type_it]); for (UInt el = 0; el < nb_element[type_it]; ++el) surf_id_type->values[el] = surf_val[el+el_offset]; el_offset += nb_element[type_it]; } /// Set nb_surfaces in mesh mesh.nb_surfaces = nb_surfaces; AKANTU_DEBUG_OUT(); } __END_AKANTU__ // LocalWords: ElementType diff --git a/mesh_utils/mesh_utils.hh b/mesh_utils/mesh_utils.hh index 721112367..b7a50f9c0 100644 --- a/mesh_utils/mesh_utils.hh +++ b/mesh_utils/mesh_utils.hh @@ -1,91 +1,105 @@ /** * @file mesh_utils.hh * @author Guillaume ANCIAUX <anciaux@lsmscluster1.epfl.ch> * @date Wed Aug 18 14:03:39 2010 * * @brief All mesh utils necessary for various tasks * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_UTILS_HH__ #define __AKANTU_MESH_UTILS_HH__ #include "aka_common.hh" #include "mesh.hh" __BEGIN_AKANTU__ class MeshUtils { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshUtils(); virtual ~MeshUtils(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// build map from nodes to elements static void buildNode2Elements(const Mesh & mesh, Vector<UInt> & node_offset, Vector<UInt> & node_to_elem, UInt spatial_dimension = 0); /// build map from nodes to elements for a specific element type static void buildNode2ElementsByElementType(const Mesh & mesh, ElementType type, Vector<UInt> & node_offset, Vector<UInt> & node_to_elem); /// build facets elements : boundary and/or internals static void buildFacets(Mesh & mesh, bool boundary_flag=1, bool internal_flag=0); /// build normal to some elements // static void buildNormals(Mesh & mesh, UInt spatial_dimension=0); /// take the local_connectivity array as the array of local and ghost /// connectivity, renumber the nodes and set the connectivity of the mesh static void renumberMeshNodes(Mesh & mesh, UInt * local_connectivities, UInt nb_local_element, UInt nb_ghost_element, ElementType type, Vector<UInt> & old_nodes); /// Detect closed surfaces of the mesh and save the surface id /// of the surface elements in the array surface_id static void buildSurfaceID(Mesh & mesh); /// function to print the contain of the class // virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "mesh_utils_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const MeshUtils & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_MESH_UTILS_HH__ */ diff --git a/mesh_utils/mesh_utils_inline_impl.cc b/mesh_utils/mesh_utils_inline_impl.cc index e370486b6..231d67d8a 100644 --- a/mesh_utils/mesh_utils_inline_impl.cc +++ b/mesh_utils/mesh_utils_inline_impl.cc @@ -1,16 +1,30 @@ /** * @file mesh_utils_inline_impl.cc * @author Guillaume ANCIAUX <anciaux@lsmscluster1.epfl.ch> * @date Wed Aug 18 14:05:36 2010 * * @brief All mesh utils necessary for various tasks * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ diff --git a/model/integration_scheme/central_difference.cc b/model/integration_scheme/central_difference.cc index d10dd59ef..0ab2d6711 100644 --- a/model/integration_scheme/central_difference.cc +++ b/model/integration_scheme/central_difference.cc @@ -1,89 +1,103 @@ /** * @file central_difference.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Aug 2 14:40:51 2010 * * @brief Implementation of the central difference scheme * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "central_difference.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ void CentralDifference::integrationSchemePred(Real delta_t, Vector<Real> & u, Vector<Real> & u_dot, Vector<Real> & u_dot_dot, Vector<bool> & boundary) { AKANTU_DEBUG_IN(); UInt nb_nodes = u.getSize(); UInt nb_degre_of_freedom = u.getNbComponent() * nb_nodes; Real delta_t_2_d2 = delta_t * delta_t / 2.; Real delta_t_d2 = delta_t / 2.; Real * u_val = u.values; Real * u_dot_val = u_dot.values; Real * u_dot_dot_val = u_dot_dot.values; bool * boundary_val = boundary.values; for (UInt d = 0; d < nb_degre_of_freedom; d++) { if(!(*boundary_val)) { /// @f$ u_{n+1} = u_{n} + \Delta t * \dot{u}_n + \frac{\Delta t^2}{2} * \ddot{u}_n @f$ *u_val += delta_t * *u_dot_val + delta_t_2_d2 * *u_dot_dot_val; /// @f$ \dot{u}_{n+1} = \dot{u}_{n} + \frac{\Delta t}{2} * \ddot{u}_{n} @f$ *u_dot_val += delta_t_d2 * *u_dot_dot_val; } u_val++; u_dot_val++; u_dot_dot_val++; boundary_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void CentralDifference::integrationSchemeCorr(Real delta_t, Vector<Real> & u, Vector<Real> & u_dot, Vector<Real> & u_dot_dot, Vector<bool> & boundary) { AKANTU_DEBUG_IN(); UInt nb_nodes = u.getSize(); UInt nb_degre_of_freedom = u.getNbComponent() * nb_nodes; Real delta_t_d2 = delta_t / 2.; // Real * u_val = u.values; Real * u_dot_val = u_dot.values; Real * u_dot_dot_val = u_dot_dot.values; bool * boundary_val = boundary.values; for (UInt d = 0; d < nb_degre_of_freedom; d++) { if(!(*boundary_val)) { /// @f$ \dot{u}_{n+1} = \dot{u}_{n} + \frac{\Delta t}{2} * \ddot{u}_{n+1} @f$ *u_dot_val += delta_t_d2 * *u_dot_dot_val; } // u_val++; u_dot_val++; u_dot_dot_val++; boundary_val++; } AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/integration_scheme/central_difference.hh b/model/integration_scheme/central_difference.hh index 145ec1b74..61a8e7f55 100644 --- a/model/integration_scheme/central_difference.hh +++ b/model/integration_scheme/central_difference.hh @@ -1,62 +1,76 @@ /** * @file central_difference.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Aug 2 14:22:56 2010 * * @brief explicit hyperbolic 2nd order central difference * Newmark-beta with gama = 1/2 and beta = 0 * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "integration_scheme_2nd_order.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_CENTRAL_DIFFERENCE_HH__ #define __AKANTU_CENTRAL_DIFFERENCE_HH__ __BEGIN_AKANTU__ class CentralDifference : public IntegrationScheme2ndOrder { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void integrationSchemePred(Real delta_t, Vector<Real> & u, Vector<Real> & u_dot, Vector<Real> & u_dot_dot, Vector<bool> & boundary); void integrationSchemeCorr(Real delta_t, Vector<Real> & u, Vector<Real> & u_dot, Vector<Real> & u_dot_dot, Vector<bool> & boundary); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; __END_AKANTU__ #endif /* __AKANTU_CENTRAL_DIFFERENCE_HH__ */ diff --git a/model/integration_scheme/integration_scheme_2nd_order.hh b/model/integration_scheme/integration_scheme_2nd_order.hh index 613c90bdd..6331e4a9f 100644 --- a/model/integration_scheme/integration_scheme_2nd_order.hh +++ b/model/integration_scheme/integration_scheme_2nd_order.hh @@ -1,67 +1,81 @@ /** * @file integration_scheme_2nd_order.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Aug 2 12:22:05 2010 * * @brief Interface of the integrator of second order * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_INTEGRATION_SCHEME_2ND_ORDER_HH__ #define __AKANTU_INTEGRATION_SCHEME_2ND_ORDER_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_vector.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class IntegrationScheme2ndOrder { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: virtual ~IntegrationScheme2ndOrder() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void integrationSchemePred(Real delta_t, Vector<Real> & u, Vector<Real> & u_dot, Vector<Real> & u_dot_dot, Vector<bool> & boundary) = 0; virtual void integrationSchemeCorr(Real delta_t, Vector<Real> & u, Vector<Real> & u_dot, Vector<Real> & u_dot_dot, Vector<bool> & boundary) = 0; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; __END_AKANTU__ #include "integration_scheme/newmark-beta.hh" #endif /* __AKANTU_INTEGRATION_SCHEME_2ND_ORDER_HH__ */ diff --git a/model/integration_scheme/newmark-beta.hh b/model/integration_scheme/newmark-beta.hh index 2a962116e..654af5320 100644 --- a/model/integration_scheme/newmark-beta.hh +++ b/model/integration_scheme/newmark-beta.hh @@ -1,112 +1,126 @@ /** * @file newmark-beta.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Sep 30 11:35:15 2010 * * @brief general case of Newmark-@f$\beta@f$ * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_NEWMARK_BETA_HH__ #define __AKANTU_NEWMARK_BETA_HH__ /* -------------------------------------------------------------------------- */ #include "integration_scheme_2nd_order.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /** * @f$\ddot{u}_{n+1} + 2 \xi \omega \dot{u}_{n+1} + \omega^2 u_{n+1} = F_{n+1}@f$ * * @f$ u_{n+1} = \tilde{u_{n+1}} + 2 \beta \frac{\Delta t^2}{2} \ddot{u}_n @f$\n * where @f$ \tilde{u_{n+1}} = u_{n} + \Delta t \dot{u}_n + (1 - 2 \beta) \frac{\Delta t^2}{2} \ddot{u}_n @f$ * * @f$ \dot{u}_{n+1} = \tilde{\dot{u}_{n+1}} + \gamma \frac{\Delta t}{2} * \ddot{u}_{n+1} @f$\n * where @f$ \tilde{\dot{u}_{n+1}} = \dot{u}_{n} + (1 - \gamma) \Delta t \ddot{u}_{n} @f$ * * * @f$\beta = 0@f$, @f$\gamma = \frac{1}{2}@f$ explicit central difference method\n * @f$\beta = \frac{1}{4}@f$, @f$\gamma = \frac{1}{2}@f$ undamped trapezoidal rule (\xi = 0)\n * @f$\gamma > \frac{1}{2}@f$ numerically damped integrator with damping proportional to @f$\gamma - \frac{1}{2}@f$ * * * Stability :\n * Unconditionally stable for @f$\beta \geq \frac{\gamma}{2} \geq \frac{1}{4}@f$\n * Conditional stability:\n * @f$ \omega_{max} \Delta t = \frac{\xi \bar{\gamma} + \left[ \bar{\gamma} + \frac{1}{4} - \beta + \xi^2 \\bar{\gamma}^2 \right]^{\frac{1}{2}}}{\left( \frac{\gamma}{2} - \beta \right)}, \bar{\gamma} \equiv \gamma - \frac{1}{2} \geq 0 @f$ */ class NewmarkBeta : public IntegrationScheme2ndOrder { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: NewmarkBeta(Real beta, Real gamma) : beta(beta), gamma(gamma) {}; ~NewmarkBeta(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void integrationSchemePred(Real delta_t, Vector<Real> & u, Vector<Real> & u_dot, Vector<Real> & u_dot_dot, Vector<bool> & boundary); void integrationSchemeCorr(Real delta_t, Vector<Real> & u, Vector<Real> & u_dot, Vector<Real> & u_dot_dot, Vector<bool> & boundary); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// the @f$\beta@f$ parameter Real beta; /// the @f$\gamma@f$ parameter Real gamma; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "newmark-beta_inline_impl.cc" /** * central difference method (explicit) * undamped stability condition : * @f$ \Delta t = \alpha \Delta t_{crit} = \frac{2}{\omega_{max}} \leq \min_{e} \frac{l_e}{c_e} * */ class CentralDifference : public NewmarkBeta { public: CentralDifference() : NewmarkBeta(0, 0.5) {}; }; //#include "integration_scheme/central_difference.hh" /// undamped trapezoidal rule (implicit) class TrapezoidalRule : public NewmarkBeta { public: TrapezoidalRule() : NewmarkBeta(0.25, 0.5) {}; }; __END_AKANTU__ #endif /* __AKANTU_NEWMARK_BETA_HH__ */ diff --git a/model/integration_scheme/newmark-beta_inline_impl.cc b/model/integration_scheme/newmark-beta_inline_impl.cc index 4a357c5df..59bdb994d 100644 --- a/model/integration_scheme/newmark-beta_inline_impl.cc +++ b/model/integration_scheme/newmark-beta_inline_impl.cc @@ -1,84 +1,98 @@ /** * @file newmark-beta_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Sep 30 11:45:20 2010 * * @brief implementation of the newmark-@f$\beta@f$ integration scheme * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ void NewmarkBeta::integrationSchemePred(Real delta_t, Vector<Real> & u, Vector<Real> & u_dot, Vector<Real> & u_dot_dot, Vector<bool> & boundary) { AKANTU_DEBUG_IN(); UInt nb_nodes = u.getSize(); UInt nb_degre_of_freedom = u.getNbComponent() * nb_nodes; Real delta_t_2_d2 = delta_t * delta_t / 2.; // Real delta_t_d2 = delta_t / 2.; Real * u_val = u.values; Real * u_dot_val = u_dot.values; Real * u_dot_dot_val = u_dot_dot.values; bool * boundary_val = boundary.values; for (UInt d = 0; d < nb_degre_of_freedom; d++) { if(!(*boundary_val)) { /// @f$ \tilde{u_{n+1}} = u_{n} + \Delta t \dot{u}_n + (1 - 2 \beta) \frac{\Delta t^2}{2} \ddot{u}_n @f$ *u_val += delta_t * *u_dot_val + delta_t_2_d2 * (1 - 2 * beta)* *u_dot_dot_val; /// @f$ \tilde{\dot{u}_{n+1}} = \dot{u}_{n} + (1 - \gamma) \Delta t \ddot{u}_{n} @f$ *u_dot_val += (1 - gamma) * delta_t * *u_dot_dot_val; } u_val++; u_dot_val++; u_dot_dot_val++; boundary_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void NewmarkBeta::integrationSchemeCorr(Real delta_t, Vector<Real> & u, Vector<Real> & u_dot, Vector<Real> & u_dot_dot, Vector<bool> & boundary) { AKANTU_DEBUG_IN(); UInt nb_nodes = u.getSize(); UInt nb_degre_of_freedom = u.getNbComponent() * nb_nodes; // Real delta_t_d2 = delta_t / 2.; Real delta_t_2_d2 = delta_t * delta_t / 2.; Real * u_val = u.values; Real * u_dot_val = u_dot.values; Real * u_dot_dot_val = u_dot_dot.values; bool * boundary_val = boundary.values; for (UInt d = 0; d < nb_degre_of_freedom; d++) { if(!(*boundary_val)) { /// @f$ u_{n+1} = \tilde{u_{n+1}} + 2 \beta \frac{\Delta t^2}{2} \ddot{u}_n @f$ *u_val += 2 * beta * delta_t_2_d2 * *u_dot_dot_val; /// @f$ \dot{u}_{n+1} = \tilde{\dot{u}_{n+1}} + \gamma \frac{\Delta t}{2} * \ddot{u}_{n+1} @f$ *u_dot_val += gamma * delta_t * *u_dot_dot_val; } // u_val++; u_dot_val++; u_dot_dot_val++; boundary_val++; } AKANTU_DEBUG_OUT(); } diff --git a/model/model.hh b/model/model.hh index 5c52bc22f..e1f4a449a 100644 --- a/model/model.hh +++ b/model/model.hh @@ -1,98 +1,112 @@ /** * @file model.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jul 22 11:02:42 2010 * * @brief Interface of a model * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MODEL_HH__ #define __AKANTU_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "mesh.hh" #include "fem.hh" #include "mesh_utils.hh" #include "ghost_synchronizer.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class Model : public Memory, public GhostSynchronizer { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: inline Model(Mesh & mesh, UInt spatial_dimension = 0, const ModelID & id = "model", const MemoryID & memory_id = 0); inline virtual ~Model(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void initModel() = 0; /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const = 0; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); AKANTU_GET_MACRO(FEM, *fem, const FEM &); inline FEM & getFEMBoundary(); virtual void synchronizeBoundaries() {}; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id ModelID id; /// the spatial dimension UInt spatial_dimension; /// the main fem object present in all models FEM * fem; /// the fem object present in all models for boundaries FEM * fem_boundary; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "model_inline_impl.cc" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Model & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_MODEL_HH__ */ diff --git a/model/model_inline_impl.cc b/model/model_inline_impl.cc index bae51cea7..3d08eb0c9 100644 --- a/model/model_inline_impl.cc +++ b/model/model_inline_impl.cc @@ -1,50 +1,64 @@ /** * @file model_inline_impl.cc * @author Guillaume ANCIAUX <anciaux@lsmscluster1.epfl.ch> * @date Fri Aug 20 17:18:08 2010 * * @brief inline implementation of the model class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ inline Model::Model(Mesh & mesh, UInt spatial_dimension, const ModelID & id, const MemoryID & memory_id) : Memory(memory_id), id(id) { AKANTU_DEBUG_IN(); this->spatial_dimension = (spatial_dimension == 0) ? mesh.getSpatialDimension() : spatial_dimension; std::stringstream sstr; sstr << id << ":fem"; this->fem = new FEM(mesh, spatial_dimension, sstr.str(), memory_id); this->fem_boundary = NULL; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline Model::~Model() { AKANTU_DEBUG_IN(); delete fem; if(fem_boundary) delete fem_boundary; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline FEM & Model::getFEMBoundary(){ AKANTU_DEBUG_IN(); if (!fem_boundary){ MeshUtils::buildFacets(fem->getMesh()); std::stringstream sstr; sstr << id << ":femboundary"; this->fem_boundary = new FEM(fem->getMesh(), spatial_dimension-1, sstr.str(), memory_id); } AKANTU_DEBUG_OUT(); return *this->fem_boundary; } diff --git a/model/solid_mechanics/contact.cc b/model/solid_mechanics/contact.cc index 3659bdada..513613166 100644 --- a/model/solid_mechanics/contact.cc +++ b/model/solid_mechanics/contact.cc @@ -1,295 +1,309 @@ /** * @file contact.cc * @author David Kammer <david.kammer@epfl.ch> * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Oct 8 14:55:42 2010 * * @brief Common part of contact classes * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "contact.hh" #include "contact_search.hh" #include "aka_common.hh" #include "contact_3d_explicit.hh" #include "contact_search_3d_explicit.hh" #include "contact_2d_explicit.hh" #include "contact_search_2d_explicit.hh" #include "contact_rigid_no_friction.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Contact::Contact(const SolidMechanicsModel & model, const ContactType & type, const ContactID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), model(model), friction_coefficient(0.), master_surfaces(NULL), surface_to_nodes(NULL), surface_to_nodes_offset(NULL), type(type) { AKANTU_DEBUG_IN(); for (UInt i = 0; i < _max_element_type; ++i) { node_to_elements_offset[i] = NULL; node_to_elements[i] = NULL; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Contact::~Contact() { AKANTU_DEBUG_IN(); delete contact_search; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::initContact(bool add_surfaces_flag) { AKANTU_DEBUG_IN(); Mesh & mesh = model.getFEM().getMesh(); const UInt nb_nodes = mesh.getNbNodes(); /// Build surfaces if not done yet if(mesh.getNbSurfaces() == 0) { /* initialise nb_surfaces to zero in mesh_io */ MeshUtils::buildFacets(mesh,1,0); MeshUtils::buildSurfaceID(mesh); } /// Detect facet types const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt nb_types = type_list.size(); UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; UInt spatial_dimension = mesh.getSpatialDimension(); for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) != spatial_dimension) continue; facet_type[nb_facet_types] = mesh.getFacetElementType(type); nb_facet_types++; } const UInt nb_surfaces = mesh.getNbSurfaces(); UInt * surf_nodes_id = new UInt [nb_nodes*nb_surfaces]; memset(surf_nodes_id, 0, nb_nodes*nb_surfaces*sizeof(Int)); /// Fill class members node_to_elements_offset and node_to_element for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) { ElementType type = facet_type[el_type]; const UInt *surf_id_val = mesh.getSurfaceId(type).values; std::stringstream sstr_name_1; sstr_name_1 << id << ":node_to_elements_offset:" << type; this->node_to_elements_offset[type] = &(alloc<UInt>(sstr_name_1.str(),0,1)); std::stringstream sstr_name_2; sstr_name_2 << id << ":node_to_elements:" << type; this->node_to_elements[type] = &(alloc<UInt>(sstr_name_2.str(),0,1)); MeshUtils::buildNode2ElementsByElementType(mesh, type, *(node_to_elements_offset[type]), *(node_to_elements[type])); UInt * node_off_val = node_to_elements_offset[type]->values; UInt * node_elem_val = node_to_elements[type]->values; for (UInt n = 0; n < nb_nodes; ++n) if(node_off_val[n] != node_off_val[n+1]) for (UInt c_el = node_off_val[n]; c_el < node_off_val[n+1]; ++c_el) { UInt surf_id = surf_id_val[node_elem_val[c_el]]; surf_nodes_id[surf_id*nb_nodes + n] = 1; } } /// Count nodes per surfaces this->surface_to_nodes_offset.resize(nb_surfaces+1); UInt * surf_nodes_off_val = surface_to_nodes_offset.values; memset(surf_nodes_off_val, 0, (nb_surfaces + 1)*sizeof(UInt)); for (UInt i = 0; i < nb_surfaces; ++i) for (UInt n = 0; n < nb_nodes; ++n) if(surf_nodes_id[i*nb_nodes+n] == 1) surf_nodes_off_val[i]++; /// convert the occurrence array in a csr one for (UInt i = 1; i < nb_surfaces; ++i) surf_nodes_off_val[i] += surf_nodes_off_val[i-1]; for (UInt i = nb_surfaces; i > 0; --i) surf_nodes_off_val[i] = surf_nodes_off_val[i-1]; surf_nodes_off_val[0] = 0; // std::stringstream stn_name; stn_name << id << ":surface_to_nodes"; // this->surface_to_nodes = alloc<UInt>(stn_name.str(),surf_nodes_off_val[nb_surfaces],1); /// Fill surface_to_nodes (save node index) surface_to_nodes.resize(surf_nodes_off_val[nb_surfaces]); UInt * surf_nodes_val = surface_to_nodes.values; for (UInt i = 0; i < nb_surfaces; ++i) for (UInt n = 0; n < nb_nodes; ++n) if(surf_nodes_id[i*nb_nodes+n] == 1) { surf_nodes_val[surf_nodes_off_val[i]] = n; surf_nodes_off_val[i]++; } /// rearrange surface_to_nodes_offset to start with 0 for (UInt i = nb_surfaces; i > 0; --i) surf_nodes_off_val[i] = surf_nodes_off_val[i-1]; surf_nodes_off_val[0] = 0; delete [] surf_nodes_id; if(add_surfaces_flag) { for (UInt i = 0; i < mesh.getNbSurfaces(); ++i) { addMasterSurface(i); std::cout << "Master surface " << i << " has been added automatically" << std::endl; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::initSearch() { AKANTU_DEBUG_IN(); contact_search->initSearch(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::initNeighborStructure() { AKANTU_DEBUG_IN(); contact_search->initNeighborStructure(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::initNeighborStructure(const Surface & master_surface) { AKANTU_DEBUG_IN(); contact_search->initNeighborStructure(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::checkAndUpdate() { AKANTU_DEBUG_IN(); std::vector<Surface>::iterator it; for (it = master_surfaces.begin(); it != master_surfaces.end(); ++it) { if(contact_search->checkIfUpdateStructureNeeded(*it)) { contact_search->updateStructure(*it); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::updateContact() { AKANTU_DEBUG_IN(); std::vector<Surface>::iterator it; for (it = master_surfaces.begin(); it != master_surfaces.end(); ++it) { contact_search->updateStructure(*it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::addMasterSurface(const Surface & master_surface) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(std::find(master_surfaces.begin(), master_surfaces.end(), master_surface) == master_surfaces.end(), "Master surface already registered in the master surface list"); master_surfaces.push_back(master_surface); contact_search->addMasterSurface(master_surface); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::removeMasterSurface(const Surface & master_surface) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(std::find(master_surfaces.begin(), master_surfaces.end(), master_surface) != master_surfaces.end(), "Master surface not registered in the master surface list"); std::remove(master_surfaces.begin(), master_surfaces.end(), master_surface); contact_search->removeMasterSurface(master_surface); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Contact * Contact::newContact(const SolidMechanicsModel & model, const ContactType & contact_type, const ContactSearchType & contact_search_type, const ContactNeighborStructureType & contact_neighbor_structure_type, const ContactID & id, const MemoryID & memory_id) { AKANTU_DEBUG_IN(); Contact * tmp_contact = NULL; ContactSearch * tmp_search = NULL; switch(contact_type) { case _ct_2d_expli: { tmp_contact = new Contact2dExplicit(model, contact_type, id, memory_id); break; } case _ct_3d_expli: { tmp_contact = new Contact3dExplicit(model, contact_type, id, memory_id); break; } case _ct_rigid_no_fric: { tmp_contact = new ContactRigidNoFriction(model, contact_type, id, memory_id); break; } case _ct_not_defined: { AKANTU_DEBUG_ERROR("Not a valid contact type : " << contact_type); break; } } std::stringstream sstr; sstr << id << ":contact_search"; switch(contact_search_type) { case _cst_2d_expli: { tmp_search = new ContactSearch2dExplicit(*tmp_contact, contact_neighbor_structure_type, contact_search_type, sstr.str()); break; } case _cst_3d_expli: { tmp_search = new ContactSearch3dExplicit(*tmp_contact, contact_neighbor_structure_type, contact_search_type, sstr.str()); break; } case _cst_not_defined: { AKANTU_DEBUG_ERROR("Not a valid contact search type : " << contact_search_type); break; } } AKANTU_DEBUG_OUT(); return tmp_contact; } __END_AKANTU__ diff --git a/model/solid_mechanics/contact.hh b/model/solid_mechanics/contact.hh index df997fbd9..02fd5e76b 100644 --- a/model/solid_mechanics/contact.hh +++ b/model/solid_mechanics/contact.hh @@ -1,171 +1,185 @@ /** * @file contact.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author David Kammer <david.kammer@epfl.ch> * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @date Mon Sep 27 09:47:27 2010 * * @brief Interface for contact classes * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_CONTACT_HH__ #define __AKANTU_CONTACT_HH__ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" //#include "contact_search.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class ContactSearch; class PenetrationList; } __BEGIN_AKANTU__ class Contact : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ protected: Contact(const SolidMechanicsModel & model, const ContactType & type, const ContactID & id = "contact", const MemoryID & memory_id = 0); public: virtual ~Contact(); static Contact * newContact(const SolidMechanicsModel & model, const ContactType & contact_type, const ContactSearchType & contact_search_type, const ContactNeighborStructureType & contact_neighbor_structure_type, const ContactID & id = "contact", const MemoryID & memory_id = 0); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// update the internal structures virtual void initContact(bool add_surfaces_flag = true); /// initiate the contact search structure virtual void initSearch(); /// initialize all neighbor structures virtual void initNeighborStructure(); /// initialize one neighbor structure virtual void initNeighborStructure(const Surface & master_surface); /// check if the neighbor structure need an update virtual void checkAndUpdate(); /// update the internal structures virtual void updateContact(); /// solve the contact virtual void solveContact() = 0; /// add a new master surface void addMasterSurface(const Surface & master_surface); /// remove a master surface void removeMasterSurface(const Surface & master_surface); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(ID, id, const ContactID &); AKANTU_GET_MACRO(Model, model, const SolidMechanicsModel &); AKANTU_GET_MACRO(FrictionCoefficient, friction_coefficient, const Real &); AKANTU_GET_MACRO(ContactSearch, * contact_search, const ContactSearch &); AKANTU_GET_MACRO(SurfaceToNodesOffset, surface_to_nodes_offset, const Vector<UInt> &); AKANTU_GET_MACRO(SurfaceToNodes, surface_to_nodes, const Vector<UInt> &); AKANTU_GET_MACRO(MasterSurfaces, master_surfaces, const std::vector<Surface> &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(NodeToElementsOffset, node_to_elements_offset, const Vector<UInt> &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(NodeToElements, node_to_elements, const Vector<UInt> &); AKANTU_GET_MACRO(Type, type, const ContactType &); void setContactSearch(ContactSearch & contact_search) { this->contact_search = &contact_search; } /// Set friction coefficient (default value = 0) AKANTU_SET_MACRO(FrictionCoefficient, friction_coefficient, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the contact class ContactID id; /// associated model const SolidMechanicsModel & model; /// friction coefficient Real friction_coefficient; /// contact search object ContactSearch * contact_search; /// list of master surfaces std::vector<Surface> master_surfaces; /// type of contact object ContactType type; private: /// offset of nodes per surface Vector<UInt> surface_to_nodes_offset; /// list of surface nodes @warning Node can occur multiple time Vector<UInt> surface_to_nodes; /// offset of surface elements per surface node ByElementTypeUInt node_to_elements_offset; /// list of surface elements id (elements can occur multiple times) ByElementTypeUInt node_to_elements; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "contact_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const Contact & _this) // { // _this.printself(stream); // return stream; //} __END_AKANTU__ #endif /* __AKANTU_CONTACT_HH__ */ diff --git a/model/solid_mechanics/contact/contact_2d_explicit.cc b/model/solid_mechanics/contact/contact_2d_explicit.cc index e317a9923..592ab2c8f 100755 --- a/model/solid_mechanics/contact/contact_2d_explicit.cc +++ b/model/solid_mechanics/contact/contact_2d_explicit.cc @@ -1,371 +1,385 @@ /** * @file contact_2d_explicit.cc * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @date Tue Oct 5 16:23:56 2010 * * @brief Contact class for explicit contact in 2d based on DCR algorithm * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "contact_2d_explicit.hh" #include "contact_search.hh" #include "aka_vector.hh" #define PROJ_TOL 1.E-8 __BEGIN_AKANTU__ Contact2dExplicit::Contact2dExplicit(const SolidMechanicsModel & model, const ContactType & type, const ContactID & id, const MemoryID & memory_id) : Contact(model, type, id, memory_id), coefficient_of_restitution(0.) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model.getFEM().getMesh().getSpatialDimension(); if(spatial_dimension != 2) AKANTU_DEBUG_ERROR("Wrong ContactType for contact in 2d!"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Contact2dExplicit::~Contact2dExplicit() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } // void Contact2dExplicit::defineSurfaces() { // AKANTU_DEBUG_IN(); // Mesh & mesh = model.fem->getMesh(); // // const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); // // UInt nb_types = type_list.size(); // /// Declare vectors // // Vector<UInt> node_offset; // // Vector<UInt> node_to_elem // ; // UInt * facet_conn_val = NULL; // UInt nb_facet_elements; // /// Consider only linear facet elements // // for(it = type_list.begin(); it != type_list.end(); ++it) { // ElementType facet_type; // // if(type == _line_1) { // nb_facet_elements = mesh.getNbElement(facet_type); // facet_conn_val = mesh.getConnectivity(facet_type).values; // // buildNode2ElementsByElementType(mesh, facet_type, node_offset, node_to_elem); // /// Ricominciamo usando le funzioni di più alto livello in mesh // const UInt nb_surfaces = getNbSurfaces(facet_type); // nb_facet_elements = mesh.getNbElement(facet_type); // const Vector<UInt> * elem_to_surf_val = getSurfaceValues(facet_type).values; // for (UInt i = 0; i < nb_surfaces; ++i) // addMasterSurface(i); // /// OK ora riordinare le superfici con i rispettivi nodi ed elementi (in linea) // surf_to_node_offset.resize(nb_surfaces+1); // for (UInt i = 0; i < nb_facet_elements; ++i) // surf_to_elem_offset.val[elem_to_surf_val[i]]++; // /// rearrange surf_to_elem_offset // for (UInt i = 1; i < nb_surfaces; ++i) surf_to_elem_offset.values[i] += surf_to_elem_offset.values[i-1]; // for (UInt i = nb_surfaces; i > 0; --i) surf_to_elem_offset.values[i] = surf_to_elem_offset[i-1]; // surf_to_elem_offset.values[0] = 0; // for (UInt i = 0; i < nb_facet_elements; ++i) // surf_to_elem[elem_to_surf_val[]] // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void Contact2dExplicit::solveContact() { AKANTU_DEBUG_IN(); /// Loop over master surfaces std::vector<Surface>::iterator it; std::vector<Surface> master_surfaces = getMasterSurfaces(); for (it = master_surfaces.begin(); it != master_surfaces.end(); ++it) { /// Get penetration list (find node to segment penetration) PenetrationList pen_list; contact_search->findPenetration(*it, pen_list); if(pen_list.penetrating_nodes.getSize() > 0) { Vector<Real> vel_norm(0, 2); Vector<Real> vel_fric(0, 2); Vector<UInt> nodes_index(0, 2); /// Remove node to segment penetrations projectNodesOnSegments(pen_list, nodes_index); /// Compute normal velocities of impacting nodes according to the normal linear momenta computeNormalVelocities(pen_list, nodes_index, vel_norm); /// Compute friction velocities computeFrictionVelocities(pen_list, nodes_index, vel_norm, vel_fric); /// Update post-impact velocities updatePostImpactVelocities(pen_list, nodes_index, vel_norm, vel_fric); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact2dExplicit::projectNodesOnSegments(PenetrationList & pen_list, Vector<UInt> & nodes_index) { AKANTU_DEBUG_IN(); UInt dim = 2; const SolidMechanicsModel & model = getModel(); Real * inc_val = model.getIncrement().values; Real * disp_val = model.getDisplacement().values; Real * pos_val = model.getCurrentPosition().values; Real * delta = new Real[dim*pen_list.penetrating_nodes.getSize()]; ElementType el_type = _segment_2; UInt * conn_val = model.getFEM().getMesh().getConnectivity(el_type).values; UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); nodes_index.resize(3*pen_list.penetrating_nodes.getSize()); UInt * index = nodes_index.values; for (UInt n = 0; n < pen_list.penetrating_nodes.getSize(); ++n) { const UInt i_node = pen_list.penetrating_nodes.values[n]; for (UInt el = pen_list.penetrated_facets_offset[el_type]->values[n]; el < pen_list.penetrated_facets_offset[el_type]->values[n+1]; ++el) { /// Project node on segment according to its projection Real proj = pen_list.projected_positions[el_type]->values[n]; index[n*3] = conn_val[elem_nodes*pen_list.penetrated_facets[el_type]->values[n]]; index[n*3+1] = conn_val[elem_nodes*pen_list.penetrated_facets[el_type]->values[n]+1]; index[n*3+2] = i_node; if(proj > PROJ_TOL && proj < 1.-PROJ_TOL) { delta[2*n] = -pen_list.gaps[el_type]->values[n]*pen_list.facets_normals[el_type]->values[dim*el]; delta[2*n+1] = -pen_list.gaps[el_type]->values[n]*pen_list.facets_normals[el_type]->values[dim*el+1]; } else if(proj <= PROJ_TOL) { delta[2*n] = pos_val[dim*index[n*3]]-pos_val[dim*i_node]; delta[2*n+1] = pos_val[dim*index[n*3]+1]-pos_val[dim*i_node+1]; if(proj < -PROJ_TOL) { Real modulus = sqrt(delta[2*n]*delta[2*n]+delta[2*n+1]*delta[2*n+1]); pen_list.facets_normals[el_type]->values[dim*el] = delta[2*n]/modulus; pen_list.facets_normals[el_type]->values[dim*el+1] = delta[2*n+1]/modulus; } proj = 0.; } else { /* proj >= 1.- PROJ_TOL */ delta[2*n] = pos_val[dim*index[n*3+1]]-pos_val[dim*i_node]; delta[2*n+1] = pos_val[dim*index[n*3+1]+1]-pos_val[dim*i_node+1]; if(proj > 1.+PROJ_TOL) { Real modulus = sqrt(delta[2*n]*delta[2*n]+delta[2*n+1]*delta[2*n+1]); pen_list.facets_normals[el_type]->values[dim*el] = delta[2*n]/modulus; pen_list.facets_normals[el_type]->values[dim*el] = delta[2*n+1]/modulus; } proj = 1.; } } } /// Update displacement and increment of the projected nodes for (UInt n = 0; n < pen_list.penetrating_nodes.getSize(); ++n) { UInt i_node = pen_list.penetrating_nodes.values[n]; pos_val[dim*index[n*3+2]] +=delta[2*n]; pos_val[dim*index[n*3+2]+1] += delta[2*n+1]; disp_val[dim*index[n*3+2]] += delta[2*n]; disp_val[dim*index[n*3+2]+1] += delta[2*n+1]; inc_val[dim*index[n*3+2]] += delta[2*n]; inc_val[dim*index[n*3+2]+1] +=delta[2*n+1]; } delete [] delta; AKANTU_DEBUG_OUT(); } void Contact2dExplicit::computeNormalVelocities(PenetrationList & pen_list, Vector<UInt> & nodes_index, Vector<Real> & vel_norm) { AKANTU_DEBUG_IN(); const UInt dim = 2; const SolidMechanicsModel & model = getModel(); const ElementType el_type = _segment_2; UInt * conn_val = model.getFEM().getMesh().getConnectivity(el_type).values; const UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); Real * vel_val = model.getVelocity().values; Real * mass_val = model.getMass().values; Real * pos_val = model.getCurrentPosition().values; vel_norm.resize(6*pen_list.penetrating_nodes.getSize()); Real * v_n = vel_norm.values; UInt * index = nodes_index.values; Real dg[6]; /// Loop over projected nodes for (UInt n = 0; n < pen_list.penetrating_nodes.getSize(); ++n) { // for (UInt el = pen_list.penetrated_facets_offset[el_type]->values[n]; el < pen_list.penetrated_facets_offset[el_type]->values[n+1]; ++el) { Real proj = pen_list.projected_positions[el_type]->values[n]; /// Fill gap derivative if (proj < PROJ_TOL) { dg[0] = pen_list.facets_normals[el_type]->values[2*n+0]; dg[1] = pen_list.facets_normals[el_type]->values[2*n+1]; dg[2] = 0.; dg[3] = 0.; dg[4] = -pen_list.facets_normals[el_type]->values[2*n+0]; dg[5] = -pen_list.facets_normals[el_type]->values[2*n+1]; } else if (proj > 1.-PROJ_TOL) { dg[0] = 0.; dg[1] = 0.; dg[2] = pen_list.facets_normals[el_type]->values[2*n+0]; dg[3] = pen_list.facets_normals[el_type]->values[2*n+1]; dg[4] = -pen_list.facets_normals[el_type]->values[2*n+0]; dg[5] = -pen_list.facets_normals[el_type]->values[2*n+1]; } else { dg[0] = pos_val[index[n*3+2]*dim+1]-pos_val[index[n*3+1]*dim+1]; dg[1] = pos_val[index[n*3+1]*dim]-pos_val[index[n*3+2]*dim]; dg[2] = pos_val[index[n*3]*dim+1]-pos_val[index[n*3+2]*dim+1]; dg[3] = pos_val[index[n*3+2]*dim]-pos_val[index[n*3]*dim]; dg[4] = pos_val[index[n*3+1]*dim+1]-pos_val[index[n*3]*dim+1]; dg[5] = pos_val[index[n*3]*dim]-pos_val[index[n*3+1]*dim]; } /// Compute normal velocities exchanged during impact Real temp1 = 0., temp2 = 0.; for (UInt i=0; i<3; ++i) for (UInt j = 0; j < dim; ++j) { temp1 += dg[i*dim+j]*vel_val[dim*index[3*n+i]+j]; temp2 += dg[i*dim+j]*dg[i*dim+j]/mass_val[index[3*n+i]]; } temp1 /= temp2; for (UInt i=0; i<3; ++i) for (UInt j = 0; j < dim; ++j) v_n[n*6+i*dim+j] = temp1*dg[i*dim+j]/mass_val[index[3*n+i]]; // } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact2dExplicit::computeFrictionVelocities(PenetrationList & pen_list, Vector<UInt> & nodes_index, Vector<Real> & vel_norm, Vector<Real> & vel_fric) { AKANTU_DEBUG_IN(); vel_fric.resize(6*pen_list.penetrating_nodes.getSize()); if (getFrictionCoefficient() == 0) { memset(vel_fric.values, 0, (6*pen_list.penetrating_nodes.getSize())*sizeof(Real)); return; } const ElementType el_type = _segment_2; const SolidMechanicsModel & model = getModel(); UInt * conn_val = model.getFEM().getMesh().getConnectivity(el_type).values; const UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); const UInt dim = 2; Real * vel_val = model.getVelocity().values; Real * mass_val = model.getMass().values; Real * v_n = vel_norm.values; Real * v_f = vel_fric.values; UInt * index = nodes_index.values; /// Loop over projected nodes for (UInt n = 0; n < pen_list.penetrating_nodes.getSize(); ++n) { // for (UInt el = pen_list.penetrated_facets_offset[el_type]->values[n]; el < pen_list.penetrated_facets_offset[el_type]->values[n+1]; ++el) { const Real h[3] = {1.-pen_list.projected_positions[el_type]->values[n], pen_list.projected_positions[el_type]->values[n], -1.}; Real temp[3] = {0., 0., 0.}; for (UInt i=0; i<3; ++i) { temp[0] += h[i]*vel_val[dim*index[i+3*n]]; temp[1] += h[i]*vel_val[dim*index[i+3*n]+1]; temp[2] += h[i]*h[i]/mass_val[index[i+3*n]]; } /// Compute non-fixed components of velocities for (UInt i=0; i<2; ++i) for (UInt j=0; j<3; ++j) v_f[n*6+j*dim+i] = temp[i]*h[j]/(temp[2]*mass_val[index[3*n+j]]); /// Compute slide components of velocities for (UInt i=0; i<6; ++i) v_f[n*6+i] = v_f[n*6+i] - v_n[n*6+i]; /// Compute final friction velocities */ memset(temp, 0, 3*sizeof(Real)); for (UInt i=0; i<3; ++i) for (UInt j = 0; j < dim; ++j) { temp[0] += v_n[n*6+i*dim+j]*v_n[n*6+i*dim+j]/mass_val[index[3*n+i]]; temp[1] += v_f[n*6+i*dim+j]*v_f[n*6+i*dim+j]/mass_val[index[3*n+i]]; } Real mu = sqrt(temp[0]/temp[1])*getFrictionCoefficient(); if (mu < 1.) for (UInt i=0; i<6; ++i) v_f[i] *= mu; // } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact2dExplicit::updatePostImpactVelocities(PenetrationList & pen_list, Vector<UInt> & nodes_index, Vector<Real> & vel_norm, Vector<Real> & vel_fric) { AKANTU_DEBUG_IN(); const UInt dim = 2; Real * v = model.getVelocity().values; Real * v_n = vel_norm.values; Real * v_f = vel_fric.values; UInt * index = nodes_index.values; /// Loop over projected nodes for (UInt n = 0; n < pen_list.penetrating_nodes.getSize(); ++n) for (UInt i = 0; i < 3; ++i) for (UInt j = 0; j < dim; ++j) v[dim*index[3*n+i]+j] -= ((1.+coefficient_of_restitution)*v_n[n*6+dim*i+j] + v_f[n*6+dim*i+j]); AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/contact/contact_2d_explicit.hh b/model/solid_mechanics/contact/contact_2d_explicit.hh index 9bf578c6d..547eaaeb7 100644 --- a/model/solid_mechanics/contact/contact_2d_explicit.hh +++ b/model/solid_mechanics/contact/contact_2d_explicit.hh @@ -1,84 +1,98 @@ /** * @file contact_2d_explicit.hh * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @date Tue Oct 12 09:24:20 2010 * * @brief Interface for 2d explicit contact class * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_CONTACT_2D_EXPLICIT_HH__ #define __AKANTU_CONTACT_2D_EXPLICIT_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "contact.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ class Contact2dExplicit : public Contact{ /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Contact2dExplicit(const SolidMechanicsModel & model, const ContactType & type, const ContactID & id = "contact", const MemoryID & memory_id = 0); virtual ~Contact2dExplicit(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void solveContact(); private: /// Project back nodes on penetrated segments void projectNodesOnSegments(PenetrationList & pen_list, Vector<UInt> & nodes_index); /// Decompose velocities prior impact to compute normal velocities void computeNormalVelocities(PenetrationList & pen_list, Vector<UInt> & nodes_index, Vector<Real> & vel_norm); /// Decompose velocities prior impact to compute friction velocities void computeFrictionVelocities(PenetrationList & pen_list, Vector<UInt> & nodes_index, Vector<Real> & vel_norm, Vector<Real> & vel_fric); /// Update velocities adding normal and friction components void updatePostImpactVelocities(PenetrationList & pen_list,Vector<UInt> & nodes_index, Vector<Real> & vel_norm, Vector<Real> & vel_fric); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// Set coefficient of restitution (default value = 0) AKANTU_SET_MACRO(CoefficientOfRestitution, coefficient_of_restitution, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// Coefficient of restitution used to compute post impact velocities Real coefficient_of_restitution; }; __END_AKANTU__ #endif /* __AKANTU_CONTACT_2D_EXPLICIT_HH__ */ diff --git a/model/solid_mechanics/contact/contact_3d_explicit.cc b/model/solid_mechanics/contact/contact_3d_explicit.cc index b9166e032..48a0c099a 100644 --- a/model/solid_mechanics/contact/contact_3d_explicit.cc +++ b/model/solid_mechanics/contact/contact_3d_explicit.cc @@ -1,53 +1,68 @@ /** * @file contact_3d_explicit.cc * @author David Kammer <david.kammer@epfl.ch> * @date Tue Oct 26 17:15:08 2010 * - * @brief Specialization of the contact structure for 3d contact in explicit time scheme + * @brief Specialization of the contact structure for 3d contact in explicit + * time scheme * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "contact_3d_explicit.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Contact3dExplicit::Contact3dExplicit(const SolidMechanicsModel & model, const ContactType & type, const ContactID & id, const MemoryID & memory_id) : Contact(model, type, id, memory_id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } Contact3dExplicit::~Contact3dExplicit() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact3dExplicit::solveContact() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/model/solid_mechanics/contact/contact_3d_explicit.hh b/model/solid_mechanics/contact/contact_3d_explicit.hh index 8d687678d..f21c6cde9 100644 --- a/model/solid_mechanics/contact/contact_3d_explicit.hh +++ b/model/solid_mechanics/contact/contact_3d_explicit.hh @@ -1,80 +1,94 @@ /** * @file contact_3d_explicit.hh * @author David Kammer <david.kammer@epfl.ch> * @date Tue Oct 26 18:13:05 2010 * * @brief Structure that solves contact for 3 dimensions within an explicit time scheme * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_CONTACT_3D_EXPLICIT_HH__ #define __AKANTU_CONTACT_3D_EXPLICIT_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "contact.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class Contact3dExplicit : public Contact { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Contact3dExplicit(const SolidMechanicsModel & model, const ContactType & type, const ContactID & id = "contact", const MemoryID & memory_id = 0); virtual ~Contact3dExplicit(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// solve the contact void solveContact(); /// function to print the contain of the class //virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "contact_3d_explicit_inline_impl.cc" /// standard output stream operator //inline std::ostream & operator <<(std::ostream & stream, const Contact3dExplicit & _this) //{ // _this.printself(stream); // return stream; //} __END_AKANTU__ #endif /*__AKANTU_CONTACT_3D_EXPLICIT_HH__ */ diff --git a/model/solid_mechanics/contact/contact_rigid_no_friction.cc b/model/solid_mechanics/contact/contact_rigid_no_friction.cc index 7b78087d4..8e3f6e960 100644 --- a/model/solid_mechanics/contact/contact_rigid_no_friction.cc +++ b/model/solid_mechanics/contact/contact_rigid_no_friction.cc @@ -1,201 +1,216 @@ /** * @file contact_rigid_no_friction.cc * @author David Kammer <david.kammer@epfl.ch> * @date Tue Oct 26 17:15:08 2010 * - * @brief Specialization of the contact structure for 3d contact in explicit time scheme + * @brief Specialization of the contact structure for 3d contact in explicit + * time scheme * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "contact_rigid_no_friction.hh" #include "contact_search.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ ContactRigidNoFriction::ContactRigidNoFriction(const SolidMechanicsModel & model, const ContactType & type, const ContactID & id, const MemoryID & memory_id) : Contact(model, type, id, memory_id), spatial_dimension(model.getSpatialDimension()), mesh(model.getFEM().getMesh()) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactRigidNoFriction::~ContactRigidNoFriction() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigidNoFriction::solveContact() { AKANTU_DEBUG_IN(); for(UInt master=0; master < master_surfaces.size(); ++master) { PenetrationList * penet_list = new PenetrationList(); contact_search->findPenetration(master_surfaces.at(master), *penet_list); solvePenetrationClosestProjection(*penet_list); delete penet_list; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /*void ContactRigidNoFriction::solvePenetration(const PenetrationList & penet_list) { AKANTU_DEBUG_IN(); const UInt dim = ; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; /// find existing surface element types UInt nb_types = type_list.size(); UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { ElementType current_facet_type = mesh.getFacetElementType(type); facet_type[nb_facet_types++] = current_facet_type; } } Real * current_position = model.getCurrentPosition().values; Real * displacement = model.getDisplacement().values; Real * increment = model.getIncrement().values; UInt * penetrating_nodes = penet_list.penetrating_nodes.values; for (UInt n=0; n < penet_list.penetrating_nodes.getSize(); ++n) { UInt current_node = penetrating_nodes[n]; // count number of elements penetrated by this node UInt nb_penetrated_facets = 0; ElementType penetrated_type; for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) { ElementType type = facet_type[el_type]; UInt offset_min = penet_list.penetrated_facets_offset[type].get(n); UInt offset_max = penet_list.penetrated_facets_offset[type].get(n+1); nb_penetrated_facets += offset_max - offset_min; penetrated_type = type; } // easy case: node penetrated only one facet if(nb_penetrated_facets == 1) { Real * facets_normals = penet_list.facets_normals[penetrated_type].values; Real * gaps = penet_list.gaps[penetrated_type].values; Real * projected_positions = penet_list.projected_positions[penetrated_type].values; UInt offset_min = penet_list.penetrated_facets_offset[penetrated_type].get(n); for(UInt i=0; i < dim; ++i) { current_position[current_node*dim + i] = projected_positions[offset_min*dim + i]; Real displacement_correction = gaps[offset_min*dim + i] * normals[offset_min*dim + i]; displacement[current_node*dim + i] = displacement[current_node*dim + i] - displacement_correction; increment [current_node*dim + i] = increment [current_node*dim + i] - displacement_correction; } } // if more penetrated facets, find the one from which the impactor node is coming else { } } }*/ /* -------------------------------------------------------------------------- */ void ContactRigidNoFriction::solvePenetrationClosestProjection(const PenetrationList & penet_list) { AKANTU_DEBUG_IN(); const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; /// find existing surface element types UInt nb_types = type_list.size(); UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { ElementType current_facet_type = mesh.getFacetElementType(type); facet_type[nb_facet_types++] = current_facet_type; } } for (UInt n=0; n < penet_list.penetrating_nodes.getSize(); ++n) { // find facet for which the gap is the smallest Real min_gap = std::numeric_limits<Real>::max(); ElementType penetrated_type; UInt penetrated_facet_offset; for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) { ElementType type = facet_type[el_type]; Real * gaps = penet_list.gaps[type]->values; UInt offset_min = penet_list.penetrated_facets_offset[type]->get(n); UInt offset_max = penet_list.penetrated_facets_offset[type]->get(n+1); for (UInt f = offset_min; f < offset_max; ++f) { if(gaps[f] < min_gap) { min_gap = gaps[f]; penetrated_type = type; penetrated_facet_offset = f; } } } // correct the position of the impactor projectImpactor(penet_list, n, penetrated_type, penetrated_facet_offset); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigidNoFriction::projectImpactor(const PenetrationList & penet_list, const UInt impactor_index, const ElementType facet_type, const UInt facet_offset) { AKANTU_DEBUG_IN(); const UInt dim = model.getSpatialDimension(); const bool increment_flag = model.getIncrementFlag(); UInt * penetrating_nodes = penet_list.penetrating_nodes.values; Real * facets_normals = penet_list.facets_normals[facet_type]->values; Real * gaps = penet_list.gaps[facet_type]->values; Real * projected_positions = penet_list.projected_positions[facet_type]->values; Real * current_position = model.getCurrentPosition().values; Real * displacement = model.getDisplacement().values; Real * increment = NULL; if(increment_flag) increment = model.getIncrement().values; UInt impactor_node = penetrating_nodes[impactor_index]; for(UInt i=0; i < dim; ++i) { current_position[impactor_node*dim + i] = projected_positions[facet_offset*dim + i]; Real displacement_correction = gaps[facet_offset] * facets_normals[facet_offset*dim + i]; displacement[impactor_node*dim + i] = displacement[impactor_node*dim + i] - displacement_correction; if(increment_flag) increment [impactor_node*dim + i] = increment [impactor_node*dim + i] - displacement_correction; } AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/contact/contact_rigid_no_friction.hh b/model/solid_mechanics/contact/contact_rigid_no_friction.hh index 6b3d4146d..6b98ae562 100644 --- a/model/solid_mechanics/contact/contact_rigid_no_friction.hh +++ b/model/solid_mechanics/contact/contact_rigid_no_friction.hh @@ -1,98 +1,113 @@ /** * @file contact_rigid_no_friction.hh * @author David Kammer <david.kammer@epfl.ch> * @date Mon Jan 17 14:10:05 2011 * - * @brief Structure that solves contact for for a rigid master surface without friction within an explicit time scheme + * @brief Structure that solves contact for for a rigid master surface without + * friction within an explicit time scheme * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_CONTACT_RIGID_NO_FRICTION_HH__ #define __AKANTU_CONTACT_RIGID_NO_FRICTION_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "contact.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class ContactRigidNoFriction : public Contact { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ContactRigidNoFriction(const SolidMechanicsModel & model, const ContactType & type, const ContactID & id = "contact", const MemoryID & memory_id = 0); virtual ~ContactRigidNoFriction(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// solve the contact void solveContact(); /// function to print the contain of the class //virtual void printself(std::ostream & stream, int indent = 0) const; private: /// solve penetration of penetrating nodes //void solvePenetration(const PenetrationList & penet_list); /// solve penetration to the closest facet void solvePenetrationClosestProjection(const PenetrationList & penet_list); /// projects the impactor to the projected position void projectImpactor(const PenetrationList & penet_list, const UInt impactor_index, const ElementType facet_type, const UInt facet_offset); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// spatial dimension of mesh UInt spatial_dimension; /// the mesh const Mesh & mesh; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "contact_rigid_no_friction_inline_impl.cc" /// standard output stream operator //inline std::ostream & operator <<(std::ostream & stream, const ContactRigidNoFriction & _this) //{ // _this.printself(stream); // return stream; //} __END_AKANTU__ #endif /*__AKANTU_CONTACT_RIGID_NO_FRICTION_HH__ */ diff --git a/model/solid_mechanics/contact/contact_search_2d_explicit.cc b/model/solid_mechanics/contact/contact_search_2d_explicit.cc index 339c35584..f4d8e6b03 100755 --- a/model/solid_mechanics/contact/contact_search_2d_explicit.cc +++ b/model/solid_mechanics/contact/contact_search_2d_explicit.cc @@ -1,407 +1,421 @@ /** * @file contact_search_2d_explicit.cc * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @date Wed Nov 3 15:06:52 2010 * * @brief Contact * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "contact_search_2d_explicit.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "aka_memory.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ ContactSearch2dExplicit::ContactSearch2dExplicit(Contact & contact, const ContactNeighborStructureType & neighbors_structure_type, const ContactSearchType & type, const ContactSearchID & id) : ContactSearch(contact, neighbors_structure_type, type, id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactSearch2dExplicit::~ContactSearch2dExplicit() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch2dExplicit::findPenetration(const Surface & master_surface, PenetrationList & pen_list) { AKANTU_DEBUG_IN(); //const ContactNeighborStructureType & neighbor_type = getContactNeighborStructureType(); const ContactNeighborStructure & structure = getContactNeighborStructure(master_surface); const NeighborList & neigh_list = const_cast<ContactNeighborStructure&>(structure).getNeighborList(); // Real * inc_val = contact.getModel().getIncrement().values; // Real * disp_val = contact.getModel().getDisplacement().values; // Real * vel_val = contact.getModel().getVelocity().values; const Contact & contact = getContact(); Real * pos_val = contact.getModel().getCurrentPosition().values; //contact.getModel().updateCurrentPosition(); /// compute current_position = initial_position + displacement temp // Real * coord = contact.getModel().getFEM().getMesh().getNodes().values; // Real * disp = contact.getModel().getDisplacement().values; // Real * pos_val = new Real[contact.getModel().getFEM().getMesh().getNodes().getSize()]; // for (UInt n = 0; n < contact.getModel().getFEM().getMesh().getNodes().getSize(); ++n) // pos_val[n] = coord[n] + disp[n]; Mesh & mesh = contact.getModel().getFEM().getMesh(); ElementType el_type = _segment_2; /* Only linear element at the moment */ const ContactSearchID & id = getID(); /// Alloc space for Penetration class members std::stringstream sstr_pfo; sstr_pfo << id << ":penetrated_facets_offset:" << el_type; pen_list.penetrated_facets_offset[el_type] = new Vector<UInt>(0, 1, sstr_pfo.str()); std::stringstream sstr_pf; sstr_pf << id << ":penetrated_facet:" << el_type; pen_list.penetrated_facets[el_type] = new Vector<UInt>(0 ,1, sstr_pf.str()); std::stringstream sstr_fn; sstr_fn << id << ":facet_normals:" << el_type; pen_list.facets_normals[el_type] = new Vector<Real>(0, 2, sstr_fn.str()); std::stringstream sstr_g; sstr_g << id << ":gaps:" << el_type; pen_list.gaps[el_type] = new Vector<Real>(0, 1, sstr_g.str()); std::stringstream sstr_pp; sstr_pp << id << ":projected_positions:" << el_type; pen_list.projected_positions[el_type] = new Vector<Real>(0, 1, sstr_pp.str()); //pen_list.nb_nodes = 0; UInt * facets_off_val = neigh_list.facets_offset[el_type]->values; UInt * facets_val = neigh_list.facets[el_type]->values; UInt * node_to_el_off_val = contact.getNodeToElementsOffset(el_type).values; UInt * node_to_el_val = contact.getNodeToElements(el_type).values; UInt * conn_val = mesh.getConnectivity(el_type).values; UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); /// Loop over the impactor nodes to detect possible penetrations for (UInt i = 0; i < neigh_list.impactor_nodes.getSize(); ++i) { UInt i_node = neigh_list.impactor_nodes.values[i]; Real *x3 = &pos_val[i_node*2]; /// Loop over elements nearby the impactor node for (UInt i_el = facets_off_val[i]; i_el < facets_off_val[i+1]; ++i_el) { UInt facet = facets_val[i_el]; Real * x1 = &pos_val[2*conn_val[facet*elem_nodes]]; Real * x2 = &pos_val[2*conn_val[facet*elem_nodes+1]]; Real vec_surf[2]; Real vec_normal[2]; Real vec_dist[2]; Real length = Math::distance_2d(x1, x2); Math::vector_2d(x1, x2, vec_surf); Math::vector_2d(x1, x3, vec_dist); Math::normal2(vec_surf, vec_normal); /* Projection normalized over length*/ Real projection = Math::vectorDot2(vec_surf, vec_dist)/(length*length); Real gap = Math::vectorDot2(vec_dist, vec_normal); bool find_proj = false; /// Penetration has occurred if(gap < -PEN_TOL) { InterType test_pen = Detect_Intersection(conn_val[facet*elem_nodes], conn_val[facet*elem_nodes+1], i_node, vec_surf, vec_dist, gap); /// Node has intersected segment if(test_pen != _no) { Real proj = Math::vectorDot2(vec_surf, vec_dist)/(length*length); UInt c_facet = facet; /// Projection on neighbor facet which shares to node1 if(test_pen == _node_1 || (test_pen==_yes && proj < 0.-PROJ_TOL)) { // Find index of neighbor facet for (UInt i = node_to_el_off_val[conn_val[facet*elem_nodes]]; i < node_to_el_off_val[conn_val[facet*elem_nodes]+1]; ++i) if(node_to_el_val[i] != facet /* && on same surface? */) { c_facet = node_to_el_val[i]; break; } if(c_facet != facet) { find_proj = checkProjectionAdjacentFacet(pen_list, facet, c_facet, i_node, proj, el_type); if(find_proj == true) break; } if (proj < 0.-PROJ_TOL && test_pen == _node_1) break; } /// Projection on neighbor facet which shares to node2 if(test_pen == _node_2 || (test_pen==_yes && proj > 1.+PROJ_TOL)) { // Find index of neighbor facet for (UInt i = node_to_el_off_val[conn_val[facet*elem_nodes]]; i < node_to_el_off_val[conn_val[facet*elem_nodes]+1]; ++i) if(node_to_el_val[i] != facet /* && on same surface? */) { c_facet = node_to_el_val[i]; break; } if(c_facet != facet) { find_proj = checkProjectionAdjacentFacet(pen_list, facet, c_facet, i_node, proj, el_type); if(find_proj == true) break; } if (proj > 0.+PROJ_TOL && test_pen == _node_2) break; } /// Save data for projection on this facet -> Check if projection outside in solve? pen_list.penetrated_facets_offset[el_type]->push_back(pen_list.penetrating_nodes.getSize()); pen_list.penetrating_nodes.push_back(i_node); pen_list.penetrated_facets[el_type]->push_back(facet); pen_list.facets_normals[el_type]->push_back(vec_normal); /* Correct ? */ pen_list.gaps[el_type]->push_back(gap); pen_list.projected_positions[el_type]->push_back(proj); //pen_list.penetrating_nodes.getSize()++; } } } } pen_list.penetrated_facets_offset[el_type]->push_back(pen_list.penetrating_nodes.getSize()); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ InterType ContactSearch2dExplicit::Detect_Intersection(UInt node1, UInt node2, UInt node3, Real *vec_surf, Real *vec_dist, Real gap) { AKANTU_DEBUG_IN(); const Real eps = 1.e-12, /* Tolerance to set discriminant equal to zero */ eps2 = 1e6, /* */ eps3 = 1e-6; /* Tolerance for space intersection "l" outside segment (tolerance for projection) */ // eps4=1e-2; /* Upper tolerance for time: penetration may occurred in previous time_step but had been not detected */ const Real eps4 = 1.0001*PEN_TOL/(-gap-PEN_TOL); Real a[2], b[2], c[2], d[2], den, delta, t[2]={-1.,-1.}, l[2]={-1.,-1.}, k, j; Real * inc_val = getContact().getModel().getIncrement().values; /* Initialize vectors of Equation to solve : 0 = a + b*l +c*t + d*t*l */ for(UInt i=0; i<2; i++) { a[i] = -vec_dist[i]; b[i] = vec_surf[i]; c[i] = inc_val[2*node3+i]-inc_val[2*node1+i]; d[i] = inc_val[2*node1+i]-inc_val[2*node2+i]; } /* Compute therm of quadratic equation: t²+k*t+j=0 */ k = (a[1]*d[0]+c[1]*b[0]-c[0]*b[1]-d[1]*a[0])/(c[1]*d[0]-d[1]*c[0]); j = (a[1]*b[0]-b[1]*a[0])/(c[1]*d[0]-d[1]*c[0]); if(isnan(k)!=true && isnan(j)!=true) { if(k < 1.e12 && j < 1.e12) { /* Equation quadratic */ /* If quadratic therm smaller than eps*other therm exclude them */ /* Compute discriminant */ delta = k*k-4.*j; /* Compute solution of quadratic equation */ do { /* Ceck if disc<0 */ if(delta < 0.) { if(delta < -eps) return _no; else // delta close to the machine precision -> only one solution /* delta = 0. */ t[0] = -k/2.; break; } /* Discriminant bigger-equal than zero */ t[0] = (-k-getSign(k)*sqrt(delta))/2.; t[1] = (-k+getSign(k)*sqrt(delta))/2.; if(abs(t[1]) < 2.*eps) t[1] = j/t[0]; } while(0); /* Ceck solution */ for(UInt i=0; i<2; i++) if(t[i]>= 0.-eps3 && t[i]<=1.+eps4) { // Within time step l[i] = -(a[0]+c[0]*t[i])/(b[0]+t[i]*d[0]); if(l[i]>= 0.-eps3 && l[i]<= 1.+eps3) { if(/*t[i]<1.-eps &&*/ l[i]>0.+1.e-3 && l[i]<1.-1.e-3) return _yes; else if(l[i]<0.5) { /* Node 3 close at the beginning to node 1*/ return _node_1; } else { /* Node 3 close at the beginning to node 2 */ return _node_2; } } } return _no; } else { /* New Equation: t²+k*t+j=0 -> k*t+j=0*/ t[0]=-(a[1]*b[0]-b[1]*a[0])/(a[1]*d[0]+c[1]*b[0]-c[0]*b[1]-d[1]*a[0]); if(t[0]>= 0.-eps3 && t[0]<=1.+eps4) { // Within time step l[0] = -(a[0]+c[0]*t[0])/(b[0]+t[0]*d[0]); if(l[0]>= 0.-eps3 && l[0]<= 1.+eps3) { if(/*t[i]<1.-eps &&*/ l[0]>0.+1.e-3 && l[0]<1.-1.e-3) return _yes; else if(l[0]<0.5) /* Node 3 close at the beginning to node 1*/ return _node_1; else /* Node 3 close at the beginning to node 2 */ return _node_2; } } return _no; } } else if(abs(c[1]/d[0])>eps2 && abs(c[0]/d[1])>eps2) { /* neglect array d */ den = b[0]*c[1]-b[1]*c[0]; t[0] = (a[0]*b[1]-b[0]*a[1])/den; if(isnan(t[0])) /* Motion parallel */ return _no; /* ? */ /* Check solution */ if(t[0]>= 0.-eps3 && t[0]<=1.+eps4) { // Possible Intersection Within time step l[0] = -(c[1]*a[0]-c[0]*a[1])/den; if(l[0]>= 0.-eps3 && l[0]<= 1.+eps3) return _yes; } return _no; } else if(abs(d[0]/c[1])>eps2 && abs(d[1]/c[0])>eps2) { /* neglect array c */ t[0] = -(-a[1]*b[0]+b[1]*a[0])/(d[1]*a[0]-d[0]*a[1]); if(isnan(t[0])) return _no; /* ? */ /* Ceck solution */ if(t[0]>= 0.-eps3 && t[0]<=1.+eps4) { // Possible Intersection Within time step l[0] = -a[0]/(b[0]+t[0]*d[0]); if(l[0]>= 0.-eps3 && l[0]<= 1.+eps3) return _yes; } return _no; } /* Neglect array c and d*/ return _no; /* undefined (either no motion or parallel motion)*/ AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool ContactSearch2dExplicit::checkProjectionAdjacentFacet(PenetrationList & pen_list, UInt facet, UInt c_facet, UInt i_node, Real old_proj, ElementType el_type) { AKANTU_DEBUG_IN(); UInt * conn_val = contact.getModel().getFEM().getMesh().getConnectivity(el_type).values; UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); UInt node1 = conn_val[c_facet*elem_nodes]; UInt node2 = conn_val[c_facet*elem_nodes+1]; Real * pos_val = contact.getModel().getCurrentPosition().values; Real * x1 = &pos_val[2*node1]; Real * x2 = &pos_val[2*node2]; Real * x3 = &pos_val[2*i_node]; Real vec_surf[2]; Real vec_normal[2]; Real vec_dist[2]; Real length = Math::distance_2d(x1, x2); Math::vector_2d(x1, x2, vec_surf); Math::vector_2d(x1, x3, vec_dist); Math::normal2(vec_surf, vec_normal); Real gap = Math::vectorDot2(vec_dist, vec_normal); if(gap < 0.-PEN_TOL) { Real proj = Math::vectorDot2(vec_surf, vec_dist)/(length*length); if(proj >= 0. && proj <= 1.) { /* Project on c_facet or node */ /// Save data on penetration list if(old_proj < 0. || old_proj > 1.) { /* (project on adjacent segment) */ pen_list.penetrated_facets_offset[el_type]->push_back(pen_list.penetrating_nodes.getSize()); pen_list.penetrating_nodes.push_back(i_node); pen_list.penetrated_facets[el_type]->push_back(c_facet); pen_list.facets_normals[el_type]->push_back(vec_normal); /* Correct ? */ pen_list.gaps[el_type]->push_back(gap); pen_list.projected_positions[el_type]->push_back(proj); //pen_list.penetrating_nodes.getSize()++; return true; } InterType test_pen = Detect_Intersection(node1, node2, i_node, vec_surf, vec_dist, gap); if(test_pen == _no) return false; /* project on node (compute new normal) */ Real new_normal[2] = {0.,0.}; if(old_proj < 0.5) { Real * x4 = &pos_val[2*conn_val[elem_nodes*facet+1]]; Math::vector_2d(x1, x4, vec_surf); Math::normal2(vec_surf, vec_normal); // new_normal[0] = -x3[0]+x2[0]; // new_normal[1] = -x3[1]+x2[1]; pen_list.projected_positions[el_type]->push_back(0.); gap = Math::distance_2d(x3, x2); } else { Real * x4 = &pos_val[2*conn_val[elem_nodes*facet]]; Math::vector_2d(x4, x2, vec_surf); Math::normal2(vec_surf, vec_normal); // new_normal[0] = -x3[0]+x1[0]; // new_normal[1] = -x3[1]+x1[1]; pen_list.projected_positions[el_type]->push_back(1.); gap = Math::distance_2d(x3, x1); } // Real new_gap = sqrt(new_normal[0]*new_normal[0]+new_normal[1]*new_normal[1]); pen_list.penetrated_facets_offset[el_type]->push_back(pen_list.penetrating_nodes.getSize()); pen_list.penetrating_nodes.push_back(i_node); pen_list.penetrated_facets[el_type]->push_back(facet); pen_list.facets_normals[el_type]->push_back(vec_normal); pen_list.gaps[el_type]->push_back(gap); //pen_list.penetrating_nodes.getSize()++; return true; } } return false; AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/contact/contact_search_2d_explicit.hh b/model/solid_mechanics/contact/contact_search_2d_explicit.hh index 13fa33f6c..a425b28bc 100644 --- a/model/solid_mechanics/contact/contact_search_2d_explicit.hh +++ b/model/solid_mechanics/contact/contact_search_2d_explicit.hh @@ -1,103 +1,117 @@ /** * @file contact_search_2d_explicit.hh * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @date Wed Nov 3 15:09:36 2010 * * @brief contact search class for contact in 2d (only line1 elements) * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_CONTACT_SEARCH_2D_EXPLICIT_HH__ #define __AKANTU_CONTACT_SEARCH_2D_EXPLICIT_HH__ #define PEN_TOL 1.E-10 #define PROJ_TOL 1.E-06 /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "contact_search.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ enum InterType { _not_def = 0, _no = 1, _yes = 2, _node_1 = 3, _node_2 = 4, _seg_1 = 5, _seg_2 = 6, }; /* -------------------------------------------------------------------------- */ class ContactSearch2dExplicit : public ContactSearch { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - + ContactSearch2dExplicit(Contact & contact, const ContactNeighborStructureType & neighbors_structure_type, const ContactSearchType & type, const ContactSearchID & id = "search_contact_2d"); virtual ~ContactSearch2dExplicit(); - + /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void findPenetration(const Surface & master_surface, PenetrationList & penetration_list); private: template <typename T> inline Int getSign(T v); // inline Real F_LINE(UInt node1, UInt node2, UInt node3); InterType Detect_Intersection(UInt node1, UInt node2, UInt node3, Real *vec_surf, Real *vec_dist, Real gap); bool checkProjectionAdjacentFacet(PenetrationList & pen_list, UInt facet, UInt c_facet, UInt i_node, Real old_proj, ElementType el_type); - + /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - + /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "contact_search_2d_explicit_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const ContactSearch2dExplicit & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_CONTACT_SEARCH_2D_EXPLICIT_HH__ */ diff --git a/model/solid_mechanics/contact/contact_search_2d_explicit_inline_impl.cc b/model/solid_mechanics/contact/contact_search_2d_explicit_inline_impl.cc index 6936f9524..f42ef7627 100644 --- a/model/solid_mechanics/contact/contact_search_2d_explicit_inline_impl.cc +++ b/model/solid_mechanics/contact/contact_search_2d_explicit_inline_impl.cc @@ -1,29 +1,43 @@ /** * @file contact_search_2d_explicit_inline_impl.cc * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @date Fri Nov 5 11:01:52 2010 * * @brief Inline functions declaration of class ContactSearch2dExplicit * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ // inline void ContactSearch2d::vector2(const Real * x, const Real * y, Real *vec) { // vec[0] = y[0]-x[0]; // vec[1] = y[1]-x[1]; // } /* -------------------------------------------------------------------------- */ template <class T> inline Int ContactSearch2dExplicit::getSign(T v) { return (v > 0) - (v < 0); } /* -------------------------------------------------------------------------- */ // inline Real ContactSearch2dExplicit::F_LINE(UInt node1, UInt node2, UInt node3) { // return (pos_val[node3*2]*(pos_val[node1*2+1]-pos_val[node2*2+1])-pos_val[node3*2+1]*(pos_val[node1*2]-pos_val[node2*2])+pos_val[node1*2]*pos_val[node2*2+1]-pos_val[node2*2]*pos_val[node1*2+1]) // } diff --git a/model/solid_mechanics/contact/contact_search_3d_explicit.cc b/model/solid_mechanics/contact/contact_search_3d_explicit.cc index 3f27c06c1..70544fcc4 100644 --- a/model/solid_mechanics/contact/contact_search_3d_explicit.cc +++ b/model/solid_mechanics/contact/contact_search_3d_explicit.cc @@ -1,597 +1,612 @@ /** * @file contact_search_3d_explicit.cc * @author David Kammer <david.kammer@epfl.ch> * @date Tue Oct 26 18:49:04 2010 * - * @brief Specialization of the contact search structure for 3D within an explicit time scheme + * @brief Specialization of the contact search structure for 3D within an + * explicit time scheme * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "regular_grid_neighbor_structure.hh" #include "contact_search_3d_explicit.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ ContactSearch3dExplicit::ContactSearch3dExplicit(Contact & contact, const ContactNeighborStructureType & neighbors_structure_type, const ContactSearchType & type, const ContactSearchID & id) : ContactSearch(contact, neighbors_structure_type, type, id), spatial_dimension(contact.getModel().getSpatialDimension()), mesh(contact.getModel().getFEM().getMesh()) { AKANTU_DEBUG_IN(); - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch3dExplicit::findPenetration(const Surface & master_surface, PenetrationList & penetration_list) { AKANTU_DEBUG_IN(); /// get the NodesNeighborList for the given master surface std::map<Surface, ContactNeighborStructure *>::iterator it_surface; for (it_surface = neighbors_structure.begin(); it_surface != neighbors_structure.end(); ++it_surface) { if(it_surface->first == master_surface) { break; } } - AKANTU_DEBUG_ASSERT(it_surface != neighbors_structure.end(), + AKANTU_DEBUG_ASSERT(it_surface != neighbors_structure.end(), "Master surface not found in this search object " << id); const NodesNeighborList & neighbor_list = dynamic_cast<const NodesNeighborList&>(it_surface->second->getNeighborList()); UInt nb_impactor_nodes = neighbor_list.impactor_nodes.getSize(); - + Vector<UInt> * closest_master_nodes = new Vector<UInt>(nb_impactor_nodes, 1); Vector<bool> * has_closest_master_node = new Vector<bool>(nb_impactor_nodes, 1, false); findClosestMasterNodes(master_surface, closest_master_nodes, has_closest_master_node); UInt * closest_master_nodes_val = closest_master_nodes->values; bool * has_closest_master_node_val = has_closest_master_node->values; /// get list of impactor and master nodes from neighbor list - UInt * impactor_nodes_val = neighbor_list.impactor_nodes.values; - + UInt * impactor_nodes_val = neighbor_list.impactor_nodes.values; + //const Mesh & mesh = contact.getModel().getFEM().getMesh(); const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; /// find existing surface element types UInt nb_types = type_list.size(); UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; - + for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { ElementType current_facet_type = mesh.getFacetElementType(type); facet_type[nb_facet_types++] = current_facet_type; /// initialization of penetration list - std::stringstream sstr_facets_offset; + std::stringstream sstr_facets_offset; sstr_facets_offset << id << ":penetrated_facets_offset:" << current_facet_type; penetration_list.penetrated_facets_offset[current_facet_type] = new Vector<UInt>(0, 1, sstr_facets_offset.str()); - + std::stringstream sstr_facets; sstr_facets << id << ":penetrated_facets:" << current_facet_type; penetration_list.penetrated_facets[current_facet_type] = new Vector<UInt>(0, 1, sstr_facets.str()); - + std::stringstream sstr_normals; sstr_normals << id << ":facets_normals:" << current_facet_type; penetration_list.facets_normals[current_facet_type] = new Vector<Real>(0, spatial_dimension, sstr_normals.str()); - + std::stringstream sstr_gaps; sstr_gaps << id << ":gaps:" << current_facet_type; penetration_list.gaps[current_facet_type] = new Vector<Real>(0, 1, sstr_gaps.str()); - + std::stringstream sstr_projected_positions; sstr_projected_positions << id << ":projected_positions:" << current_facet_type; penetration_list.projected_positions[current_facet_type] = new Vector<Real>(0, spatial_dimension, sstr_projected_positions.str()); } } - + for(UInt in = 0; in < nb_impactor_nodes; ++in) { if (!has_closest_master_node_val[in]) continue; UInt current_impactor_node = impactor_nodes_val[in]; UInt closest_master_node = closest_master_nodes_val[in]; std::vector<Element> surface_elements; Vector<bool> * are_inside = new Vector<bool>(0, 1); Vector<bool> * are_in_projection_area = new Vector<bool>(0, 1); Element considered_element; for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) { ElementType type = facet_type[el_type]; - + UInt * surface_id_val = mesh.getSurfaceId(type).values; - + const Vector<UInt> & node_to_elements_offset = contact.getNodeToElementsOffset(type); const Vector<UInt> & node_to_elements = contact.getNodeToElements(type); UInt * node_to_elements_offset_val = node_to_elements_offset.values; UInt * node_to_elements_val = node_to_elements.values; UInt min_element_offset = node_to_elements_offset_val[closest_master_node]; UInt max_element_offset = node_to_elements_offset_val[closest_master_node + 1]; - + considered_element.type = type; for(UInt el = min_element_offset; el < max_element_offset; ++el) { UInt surface_element = node_to_elements_val[el]; if(surface_id_val[surface_element] == master_surface) { bool is_inside; bool is_in_projection_area; - checkPenetrationSituation(current_impactor_node, - surface_element, + checkPenetrationSituation(current_impactor_node, + surface_element, type, is_inside, is_in_projection_area); - + considered_element.element = surface_element; - + surface_elements.push_back(considered_element); are_inside->push_back(is_inside); are_in_projection_area->push_back(is_in_projection_area); } } } UInt nb_penetrated_elements = 0; UInt nb_elements_type[_max_element_type]; memset(nb_elements_type, 0, sizeof(UInt) * _max_element_type); - + bool * are_inside_val = are_inside->values; bool * are_in_projection_area_val = are_in_projection_area->values; bool is_outside = false; UInt nb_surface_elements = static_cast<UInt>(surface_elements.size()); // add all elements for which impactor is inside and in projection area for(UInt el = 0; el < nb_surface_elements; ++el) { if(are_inside_val[el] && are_in_projection_area_val[el]) { - + ElementType current_type = surface_elements.at(el).type; UInt current_element = surface_elements.at(el).element; penetration_list.penetrated_facets[current_type]->push_back(current_element); - + Real normal[3]; - Real projected_position[3]; + Real projected_position[3]; Real gap; computeComponentsOfProjection(current_impactor_node, current_element, current_type, normal, gap, projected_position); penetration_list.facets_normals[current_type]->push_back(normal); penetration_list.projected_positions[current_type]->push_back(projected_position); penetration_list.gaps[current_type]->push_back(gap); - + nb_penetrated_elements++; nb_elements_type[current_type]++; } } if(nb_penetrated_elements > 0) { for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { penetration_list.penetrating_nodes.push_back(current_impactor_node); ElementType current_facet_type = mesh.getFacetElementType(type); penetration_list.penetrated_facets_offset[current_facet_type]->push_back(nb_elements_type[current_facet_type]); - } + } } } - + // if there was no element which is inside and in projection area // check if node is not definitly outside else { for(UInt el = 0; el < nb_surface_elements && !is_outside; ++el) { if(!are_inside_val[el] && are_in_projection_area_val[el]) { is_outside = true; } } - + // it is not definitly outside take all elements to which it is at least inside if(!is_outside) { bool found_inside_node = false; for(UInt el = 0; el < nb_surface_elements; ++el) { if(are_inside_val[el] && !are_in_projection_area_val[el]) { - + ElementType current_type = surface_elements.at(el).type; UInt current_element = surface_elements.at(el).element; penetration_list.penetrated_facets[current_type]->push_back(current_element); - + Real normal[3]; - Real projected_position[3]; + Real projected_position[3]; Real gap; computeComponentsOfProjection(current_impactor_node, current_element, current_type, normal, gap, projected_position); - + penetration_list.facets_normals[current_type]->push_back(normal); penetration_list.projected_positions[current_type]->push_back(projected_position); penetration_list.gaps[current_type]->push_back(gap); - + nb_penetrated_elements++; nb_elements_type[current_type]++; found_inside_node = true; } } if(found_inside_node) { for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { penetration_list.penetrating_nodes.push_back(current_impactor_node); ElementType current_facet_type = mesh.getFacetElementType(type); penetration_list.penetrated_facets_offset[current_facet_type]->push_back(nb_elements_type[current_facet_type]); - } + } } - } + } } } - + delete are_in_projection_area; delete are_inside; } // make the offset table a real offset table for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { ElementType current_facet_type = mesh.getFacetElementType(type); - + UInt tmp_nb_facets = penetration_list.penetrated_facets_offset[current_facet_type]->getSize(); penetration_list.penetrated_facets_offset[current_facet_type]->resize(tmp_nb_facets+1); - + Vector<UInt> & tmp_penetrated_facets_offset = *(penetration_list.penetrated_facets_offset[current_facet_type]); UInt * tmp_penetrated_facets_offset_val = tmp_penetrated_facets_offset.values; - + for (UInt i = 1; i < tmp_nb_facets; ++i) tmp_penetrated_facets_offset_val[i] += tmp_penetrated_facets_offset_val[i - 1]; for (UInt i = tmp_nb_facets; i > 0; --i) tmp_penetrated_facets_offset_val[i] = tmp_penetrated_facets_offset_val[i - 1]; tmp_penetrated_facets_offset_val[0] = 0; - } + } } - + delete closest_master_nodes; delete has_closest_master_node; - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void ContactSearch3dExplicit::findClosestMasterNodes(const Surface & master_surface, +void ContactSearch3dExplicit::findClosestMasterNodes(const Surface & master_surface, Vector<UInt> * closest_master_nodes, Vector<bool> * has_closest_master_node) { AKANTU_DEBUG_IN(); bool * has_closest_master_node_val = has_closest_master_node->values; UInt * closest_master_nodes_val = closest_master_nodes->values; /// get the NodesNeighborList for the given master surface std::map<Surface, ContactNeighborStructure *>::iterator it; for (it = neighbors_structure.begin(); it != neighbors_structure.end(); ++it) { if(it->first == master_surface) { break; } } AKANTU_DEBUG_ASSERT(it != neighbors_structure.end(), "Master surface not found in this search object " << id); const NodesNeighborList & neighbor_list = dynamic_cast<const NodesNeighborList&>(it->second->getNeighborList()); - + /// get list of impactor and master nodes from neighbor list UInt * impactor_nodes_val = neighbor_list.impactor_nodes.values; UInt * master_nodes_offset_val = neighbor_list.master_nodes_offset.values; UInt * master_nodes_val = neighbor_list.master_nodes.values; /// loop over all impactor nodes and find for each the closest master node UInt nb_impactor_nodes = neighbor_list.impactor_nodes.getSize(); for(UInt imp = 0; imp < nb_impactor_nodes; ++imp) { UInt current_impactor_node = impactor_nodes_val[imp]; UInt min_offset = master_nodes_offset_val[imp]; UInt max_offset = master_nodes_offset_val[imp + 1]; // if there is no master node go to next impactor node if (min_offset == max_offset) continue; Real min_square_distance = std::numeric_limits<Real>::max(); UInt closest_master_node = (UInt)-1; // for finding error for(UInt mn = min_offset; mn < max_offset; ++mn) { UInt current_master_node = master_nodes_val[mn]; Real square_distance = computeSquareDistanceBetweenNodes(current_impactor_node, current_master_node); if(min_square_distance > square_distance) { min_square_distance = square_distance; closest_master_node = current_master_node; } } AKANTU_DEBUG_ASSERT(closest_master_node != ((UInt)-1), "could not find a closest master node for impactor node: " << current_impactor_node); has_closest_master_node_val[imp] = true; closest_master_nodes_val[imp] = closest_master_node; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch3dExplicit::computeComponentsOfProjection(const UInt impactor_node, const UInt surface_element, const ElementType type, Real * normal, Real & gap, Real * projected_position) { AKANTU_DEBUG_IN(); switch(type) { case _segment_2: { computeComponentsOfProjectionSegment2(impactor_node, surface_element, normal, gap, projected_position); break; } case _triangle_3: { computeComponentsOfProjectionTriangle3(impactor_node, surface_element, normal, gap, projected_position); break; } case _not_defined: { AKANTU_DEBUG_ERROR("Not a valid surface element type : " << type); break; } } - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void ContactSearch3dExplicit::checkPenetrationSituation(const UInt impactor_node, - const UInt surface_element, +void ContactSearch3dExplicit::checkPenetrationSituation(const UInt impactor_node, + const UInt surface_element, const ElementType type, bool & is_inside, bool & is_in_projection_area) { AKANTU_DEBUG_IN(); switch(type) { case _segment_2: { checkPenetrationSituationSegment2(impactor_node, surface_element, is_inside, is_in_projection_area); break; } case _triangle_3: { checkPenetrationSituationTriangle3(impactor_node, surface_element, is_inside, is_in_projection_area); break; } case _not_defined: { AKANTU_DEBUG_ERROR("Not a valid surface element type : " << type); break; } } - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch3dExplicit::computeComponentsOfProjectionSegment2(const UInt impactor_node, const UInt surface_element, Real * normal, Real & gap, Real * projected_position) { AKANTU_DEBUG_IN(); - + const UInt dim = spatial_dimension; const ElementType type = _segment_2; const UInt nb_nodes_element = Mesh::getNbNodesPerElement(type); - + Real * current_position = contact.getModel().getCurrentPosition().values; UInt * connectivity = mesh.getConnectivity(type).values; UInt node_1 = surface_element * nb_nodes_element; Real * position_node_1 = &(current_position[connectivity[node_1 + 0] * spatial_dimension]); Real * position_node_2 = &(current_position[connectivity[node_1 + 1] * spatial_dimension]); Real * position_impactor_node = &(current_position[impactor_node * spatial_dimension]); /// compute the normal of the face Real vector_1[2]; - Math::vector_2d(position_node_1, position_node_2, vector_1); /// @todo: check if correct order of nodes !! + Math::vector_2d(position_node_1, position_node_2, vector_1); /// @todo: check if correct order of nodes !! Math::normal2(vector_1, normal); /// compute the gap between impactor and face /// gap positive if impactor outside of surface Real vector_node_1_impactor[2]; Math::vector_2d(position_node_1, position_impactor_node, vector_node_1_impactor); gap = Math::vectorDot2(vector_node_1_impactor, normal); /// compute the projected position of the impactor node onto the face for(UInt i=0; i < dim; ++i) { projected_position[i] = position_impactor_node[i] - gap * normal[i]; } - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch3dExplicit::computeComponentsOfProjectionTriangle3(const UInt impactor_node, const UInt surface_element, Real * normal, Real & gap, Real * projected_position) { AKANTU_DEBUG_IN(); - + const UInt dim = spatial_dimension; const ElementType type = _triangle_3; const UInt nb_nodes_element = Mesh::getNbNodesPerElement(type); - + Real * current_position = contact.getModel().getCurrentPosition().values; UInt * connectivity = mesh.getConnectivity(type).values; UInt node_1 = surface_element * nb_nodes_element; Real * position_node_1 = &(current_position[connectivity[node_1 + 0] * spatial_dimension]); Real * position_node_2 = &(current_position[connectivity[node_1 + 1] * spatial_dimension]); Real * position_node_3 = &(current_position[connectivity[node_1 + 2] * spatial_dimension]); Real * position_impactor_node = &(current_position[impactor_node * spatial_dimension]); /// compute the normal of the face Real vector_1[3]; Real vector_2[3]; - Math::vector_3d(position_node_1, position_node_2, vector_1); /// @todo: check if correct order of nodes !! + Math::vector_3d(position_node_1, position_node_2, vector_1); /// @todo: check if correct order of nodes !! Math::vector_3d(position_node_1, position_node_3, vector_2); Math::normal3(vector_1, vector_2, normal); /// compute the gap between impactor and face /// gap positive if impactor outside of surface Real vector_node_1_impactor[3]; Math::vector_3d(position_node_1, position_impactor_node, vector_node_1_impactor); gap = Math::vectorDot3(vector_node_1_impactor, normal); /// compute the projected position of the impactor node onto the face for(UInt i=0; i < dim; ++i) { projected_position[i] = position_impactor_node[i] - gap * normal[i]; } - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void ContactSearch3dExplicit::checkPenetrationSituationSegment2(const UInt impactor_node, - const UInt surface_element, - bool & is_inside, +void ContactSearch3dExplicit::checkPenetrationSituationSegment2(const UInt impactor_node, + const UInt surface_element, + bool & is_inside, bool & is_in_projection_area) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(spatial_dimension == 2, "wrong spatial dimension (=" << spatial_dimension << ") for checkPenetrationSituationSegment2"); const UInt dim = spatial_dimension; const ElementType type = _segment_2; const UInt nb_nodes_element = Mesh::getNbNodesPerElement(type); const Real tolerance = std::numeric_limits<Real>::epsilon(); - + Real * current_position = contact.getModel().getCurrentPosition().values; UInt * connectivity = mesh.getConnectivity(type).values; - Real gap; + Real gap; Real normal[2]; Real projected_position[2]; computeComponentsOfProjectionSegment2(impactor_node, surface_element, normal, gap, projected_position); - + // ------------------------------------------------------- /// Find if impactor node is inside or outside of the face // ------------------------------------------------------- if(gap < -tolerance) - is_inside = true; + is_inside = true; else is_inside = false; // ---------------------------------------------------- /// Find if impactor node is in projection area of face // ---------------------------------------------------- UInt node_1 = surface_element * nb_nodes_element; Real * position_node_1 = &(current_position[connectivity[node_1 + 0] * spatial_dimension]); Real * position_node_2 = &(current_position[connectivity[node_1 + 1] * spatial_dimension]); Real tmp_vector_1_imp[2]; Real tmp_vector_1_2[2]; - + // find vectors from master node 1 to impactor and master node 2 Math::vector_2d(position_node_1, position_node_2, tmp_vector_1_2); Math::vector_2d(position_node_1, projected_position, tmp_vector_1_imp); Real length_difference = Math::norm2(tmp_vector_1_imp) - Math::norm2(tmp_vector_1_2); // the projection is outside if the test area is larger than the area of the triangle if(length_difference > tolerance) - is_in_projection_area = false; + is_in_projection_area = false; else is_in_projection_area = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void ContactSearch3dExplicit::checkPenetrationSituationTriangle3(const UInt impactor_node, - const UInt surface_element, - bool & is_inside, +void ContactSearch3dExplicit::checkPenetrationSituationTriangle3(const UInt impactor_node, + const UInt surface_element, + bool & is_inside, bool & is_in_projection_area) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(spatial_dimension == 3, "wrong spatial dimension (=" << spatial_dimension << ") for checkPenetrationSituationTriangle3"); const UInt dim = spatial_dimension; const ElementType type = _triangle_3; const UInt nb_nodes_element = Mesh::getNbNodesPerElement(type); const Real tolerance = std::numeric_limits<Real>::epsilon(); - + Real * current_position = contact.getModel().getCurrentPosition().values; UInt * connectivity = mesh.getConnectivity(type).values; - Real gap; + Real gap; Real normal[3]; Real projected_position[3]; computeComponentsOfProjectionTriangle3(impactor_node, surface_element, normal, gap, projected_position); - + // ------------------------------------------------------- /// Find if impactor node is inside or outside of the face // ------------------------------------------------------- if(gap < -tolerance) - is_inside = true; + is_inside = true; else is_inside = false; // ---------------------------------------------------- /// Find if impactor node is in projection area of face // ---------------------------------------------------- UInt node_1 = surface_element * nb_nodes_element; Real * position_node_1 = &(current_position[connectivity[node_1 + 0] * spatial_dimension]); Real * position_node_2 = &(current_position[connectivity[node_1 + 1] * spatial_dimension]); Real * position_node_3 = &(current_position[connectivity[node_1 + 2] * spatial_dimension]); Real triangle_area; Real test_area = 0.0; Real tmp_vector_1[3]; Real tmp_vector_2[3]; Real tmp_vector_3[3]; - + // find area of triangle Math::vector_3d(position_node_1, position_node_2, tmp_vector_1); Math::vector_3d(position_node_1, position_node_3, tmp_vector_2); Math::vectorProduct3(tmp_vector_1, tmp_vector_2, tmp_vector_3); triangle_area = 0.5 * Math::norm3(tmp_vector_3); // compute areas of projected position and two nodes of master triangle UInt nb_sub_areas = nb_nodes_element; UInt node_order[4]; node_order[0] = 0; node_order[1] = 1; node_order[2] = 2; node_order[3] = 0; for(UInt i=0; i < nb_sub_areas; ++i) { position_node_1 = &(current_position[connectivity[node_1 + node_order[i ]] * spatial_dimension]); position_node_2 = &(current_position[connectivity[node_1 + node_order[i+1]] * spatial_dimension]); Math::vector_3d(projected_position, position_node_1, tmp_vector_1); Math::vector_3d(projected_position, position_node_2, tmp_vector_2); Math::vectorProduct3(tmp_vector_1, tmp_vector_2, tmp_vector_3); test_area += 0.5 * Math::norm3(tmp_vector_3); } // the projection is outside if the test area is larger than the area of the triangle if((test_area - triangle_area) > tolerance) - is_in_projection_area = false; + is_in_projection_area = false; else is_in_projection_area = true; AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/contact/contact_search_3d_explicit.hh b/model/solid_mechanics/contact/contact_search_3d_explicit.hh index 6d7f1fb95..107844895 100644 --- a/model/solid_mechanics/contact/contact_search_3d_explicit.hh +++ b/model/solid_mechanics/contact/contact_search_3d_explicit.hh @@ -1,138 +1,153 @@ /** * @file contact_search_3d_explicit.hh * @author David Kammer <david.kammer@epfl.ch> * @date Tue Oct 26 18:43:27 2010 * - * @brief Structure that finds contact for 3 dimensions within an explicit time scheme + * @brief Structure that finds contact for 3 dimensions within an explicit time + * scheme * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_CONTACT_SEARCH_3D_EXPLICIT_HH__ #define __AKANTU_CONTACT_SEARCH_3D_EXPLICIT_HH__ /* -------------------------------------------------------------------------- */ #include "contact_search.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class ContactSearch3dExplicit : public ContactSearch { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ContactSearch3dExplicit(Contact & contact, const ContactNeighborStructureType & neighbors_structure_type, const ContactSearchType & type, const ContactSearchID & id = "search_contact"); //virtual ~ContactSearch3dExplicit(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// build the penetration list void findPenetration(const Surface & master_surface, PenetrationList & penetration_list); /// function to print the contain of the class //virtual void printself(std::ostream & stream, int indent = 0) const; private: /// find the closest master node void findClosestMasterNodes(const Surface & master_surface, Vector<UInt> * closest_master_nodes, Vector<bool> * has_closest_master_node); /// compute the square of the distance between two nodes inline Real computeSquareDistanceBetweenNodes(const UInt node_1, const UInt node_2); /// test if impactor node is inside and in the projection area void checkPenetrationSituation(const UInt impactor_node, const UInt surface_element, const ElementType type, bool & is_inside, bool & is_in_projection_area); /// test if impactor node is inside and in the projection area for segment_2 void checkPenetrationSituationSegment2(const UInt impactor_node, const UInt surface_element, bool & is_inside, bool & is_in_projection_area); /// test if impactor node is inside and in the projection area for triangle_3 void checkPenetrationSituationTriangle3(const UInt impactor_node, const UInt surface_element, bool & is_inside, bool & is_in_projection_area); /// compute the normal, the gap and the projected position for impactor void computeComponentsOfProjection(const UInt impactor_node, const UInt surface_element, const ElementType type, Real * normal, Real & gap, Real * projected_position); /// compute the normal, the gap and the projected position for impactor for segment_2 void computeComponentsOfProjectionSegment2(const UInt impactor_node, const UInt surface_element, Real * normal, Real & gap, Real * projected_position); /// compute the normal, the gap and the projected position for impactor for triangle_3 void computeComponentsOfProjectionTriangle3(const UInt impactor_node, const UInt surface_element, Real * normal, Real & gap, Real * projected_position); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// spatial dimension of mesh UInt spatial_dimension; /// the mesh const Mesh & mesh; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "contact_search_3d_explicit_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const ContactSearch3dExplicit & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_CONTACT_SEARCH_3D_EXPLICIT_HH__ */ diff --git a/model/solid_mechanics/contact/contact_search_3d_explicit_inline_impl.cc b/model/solid_mechanics/contact/contact_search_3d_explicit_inline_impl.cc index 8389b2c55..e4bd3f64e 100644 --- a/model/solid_mechanics/contact/contact_search_3d_explicit_inline_impl.cc +++ b/model/solid_mechanics/contact/contact_search_3d_explicit_inline_impl.cc @@ -1,33 +1,47 @@ /** * @file contact_search_3d_explicit_inline_impl.cc * @author David Kammer <david.kammer@epfl.ch> * @date Thu Nov 25 15:22:31 2010 * * @brief Implementation of inline functions of the explicit 3d contact search algorithm * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ inline Real ContactSearch3dExplicit::computeSquareDistanceBetweenNodes(const UInt node_1, const UInt node_2) { AKANTU_DEBUG_IN(); Real square_distance = 0.0; /// get the spatial dimension and current position of nodes //UInt spatial_dimension = contact.getModel().getSpatialDimension(); Real * current_position = contact.getModel().getCurrentPosition().values; /// compute the square distance between the nodes for(UInt dim = 0; dim < spatial_dimension; ++dim) { Real tmp_value = current_position[node_1 * spatial_dimension + dim] - current_position[node_2 * spatial_dimension + dim]; square_distance += tmp_value * tmp_value; } AKANTU_DEBUG_OUT(); return square_distance; } diff --git a/model/solid_mechanics/contact/grid_2d_neighbor_structure.cc b/model/solid_mechanics/contact/grid_2d_neighbor_structure.cc index 63067d9bb..a5ef9c45b 100644 --- a/model/solid_mechanics/contact/grid_2d_neighbor_structure.cc +++ b/model/solid_mechanics/contact/grid_2d_neighbor_structure.cc @@ -1,610 +1,624 @@ /** * @file grid_2d_neighbor_structure.cc * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @date Tue Dec 7 13:04:58 2010 * * @brief * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "contact_search.hh" #include "solid_mechanics_model.hh" #include "grid_2d_neighbor_structure.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Grid2dNeighborStructure::Grid2dNeighborStructure(const ContactSearch & contact_search, const Surface & master_surface, const ContactNeighborStructureType & type, const ContactNeighborStructureID & id) : ContactNeighborStructure(contact_search, master_surface, type, id), mesh(contact_search.getContact().getModel().getFEM().getMesh()) { AKANTU_DEBUG_IN(); UInt spatial_dimension = contact_search.getContact().getModel().getFEM().getMesh().getSpatialDimension(); if(spatial_dimension != 2) AKANTU_DEBUG_ERROR("Wrong ContactType for contact in 2d!"); /// make sure that the increments are computed const_cast<SolidMechanicsModel &>(contact_search.getContact().getModel()).setIncrementFlagOn(); /// set increment to zero max_increment[0] = 0.; max_increment[1] = 0.; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Grid2dNeighborStructure::~Grid2dNeighborStructure() { AKANTU_DEBUG_IN(); delete neighbor_list; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Grid2dNeighborStructure::initNeighborStructure() { AKANTU_DEBUG_IN(); neighbor_list = new NeighborList(); createGrid(true); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool Grid2dNeighborStructure::check() { AKANTU_DEBUG_IN(); UInt nb_surfaces = mesh.getNbSurfaces(); Real * inc_val = contact_search.getContact().getModel().getIncrement().values; Real max[2] = {0. ,0.}; UInt * surf_nodes_off = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surf_nodes = contact_search.getContact().getSurfaceToNodes().values; for (UInt s = 0; s < nb_surfaces; ++s) for (UInt n = surf_nodes_off[s]; n < surf_nodes_off[n+1]; ++n) { UInt i_node = surf_nodes[n]; for (UInt i = 0; i < 2; ++i) max[i] = std::max(max[i], fabs(inc_val[2*i_node+i])); } for (UInt i = 0; i < 2; ++i) { max_increment[i] += max[i]; if(max_increment[i] > spacing) return true; } return false; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Grid2dNeighborStructure::update() { AKANTU_DEBUG_IN(); delete[] this->neighbor_list; neighbor_list = new NeighborList(); createGrid(false); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Grid2dNeighborStructure::createGrid(bool initial_position) { AKANTU_DEBUG_IN(); Real * coord; if (initial_position) coord = mesh.getNodes().values; else coord = contact_search.getContact().getModel().getCurrentPosition().values; UInt nb_surfaces = mesh.getNbSurfaces(); /// get the size of the grid spacing = getMinSize(coord); /// get bounds of master surface Real * x_bounds = new Real[2*nb_surfaces]; Real * y_bounds = new Real[2*nb_surfaces]; getBounds(coord, x_bounds, y_bounds); /// find intersections between mastersurface and the other ones Real x_intersection[2]; Real y_intersection[2]; bool intersection = getBoundsIntersection(x_bounds, y_bounds, x_intersection, y_intersection); /// if every slave surfaces to far away from master surface neighbor list is empty if(intersection == false) return; /// adjust intersection space x_intersection[0] -= 1.49999*spacing; x_intersection[1] += 1.49999*spacing; y_intersection[0] -= 1.49999*spacing; y_intersection[1] += 1.49999*spacing; x_intersection[0] = std::max(x_intersection[0], x_bounds[2*master_surface]); x_intersection[1] = std::min(x_intersection[0+1], x_bounds[2*master_surface+1]); y_intersection[0] = std::max(y_intersection[0], y_bounds[2*master_surface]); y_intersection[1] = std::min(y_intersection[0+1], y_bounds[2*master_surface+1]); /// define grid dimension UInt nb_cells[3]; nb_cells[0] = std::ceil(fabs(x_intersection[1]-x_intersection[0])/spacing); nb_cells[1] = std::ceil(fabs(y_intersection[1]-y_intersection[0])/spacing); nb_cells[2] = nb_cells[0]*nb_cells[1]; Real origin[2]; origin[0] = x_intersection[0] - (nb_cells[0]*spacing-fabs(x_intersection[1]-x_intersection[0]))/2.; origin[1] = y_intersection[0] - (nb_cells[1]*spacing-fabs(y_intersection[1]-y_intersection[0]))/2.; /// fill grid cells with master segments Vector<UInt> cell_to_segments(0, 1); UInt * cell_to_segments_offset = new UInt[nb_cells[2]+1]; memset(cell_to_segments_offset, 0, (nb_cells[2]+1)*sizeof(UInt)); traceSegments(coord, origin, nb_cells, cell_to_segments_offset, cell_to_segments); /// loop over slave nodes to find out impactor ones UInt * surf_nodes_off = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surf_nodes = contact_search.getContact().getSurfaceToNodes().values; UInt * impactors = neighbor_list->impactor_nodes.values; UInt * cell_seg_val = cell_to_segments.values; ElementType el_type = _segment_2; /* Only linear element at the moment */ UInt * conn_val = contact_search.getContact().getModel().getFEM().getMesh().getConnectivity(el_type).values; UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); std::stringstream sstr_fo; sstr_fo << id << ":facets_offset:" << el_type; neighbor_list->facets_offset[el_type] = new Vector<UInt>(0, 1, sstr_fo.str()); std::stringstream sstr_f; sstr_f << id << ":facets:" << el_type; neighbor_list->facets[el_type] = new Vector<UInt>(0, 1, sstr_f.str()); neighbor_list->facets_offset[el_type]->push_back((UInt)0); const Int cell_index[9][2] = {{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1}}; Int nb_x = nb_cells[0]; Int nb_y = nb_cells[1]; Vector<UInt> checked(0,1); /// loop over slave surfaces for (UInt s = 0; s < nb_surfaces; ++s) { if(s == master_surface) continue; /// check is slave surface inside grid if(x_bounds[2*s+1] < origin[0] || y_bounds[2*s+1] < origin[1]) continue; if(x_bounds[2*s] > origin[0]+spacing*nb_cells[0] || y_bounds[2*s] > origin[1]+spacing*nb_cells[1]) continue; /// loop over slave nodes of considered surface for (UInt n = surf_nodes_off[s]; n < surf_nodes_off[s+1]; ++n) { UInt i_node = surf_nodes[n]; Real x_node = (coord[2*i_node] - origin[0])/spacing; Real y_node = (coord[2*i_node+1] - origin[1])/spacing; Int ii = (int)(x_node); Int jj = (int)(y_node); /// is node in one grid cell? if((ii < 0 || jj < 0) || (ii>=nb_x || jj>=nb_y)) continue; Int i_start; /* which cells are to be considered */ if(std::ceil(x_node-ii-0.5)==1 && std::ceil(y_node-jj-0.5)==0) i_start = 3; else { i_start = std::ceil(x_node-ii-0.5) + std::ceil(y_node-jj-0.5); } checked.empty(); bool stored = false; /// look at actual cell and 3 adjacent cells for (Int k = -1; k < 3; ++k) { Int x_index = ii; Int y_index = jj; if ( k >= 0) { x_index += cell_index[i_start*2+k][0]; y_index += cell_index[i_start*2+k][1]; if ((x_index < 0 || y_index < 0) || (x_index>=nb_x || y_index>=nb_y)) continue; /* cell does not exists */ } UInt i_cell = (UInt)(x_index+y_index*nb_x); /// loop over segments related to the considered cell for (UInt el = cell_to_segments_offset[i_cell]; el < cell_to_segments_offset[i_cell+1]; ++el) { UInt i_segment = cell_seg_val[el]; bool i_checked = false; for (UInt l=0; l<checked.getSize(); l++) { if(i_segment == checked.values[l]) { /* Segment already visited */ i_checked = true; break; } } /// check segment-node distance if (i_checked == false) { checked.push_back(i_segment); Real * x1 = &coord[2*conn_val[i_segment*elem_nodes]]; Real * x2 = &coord[2*conn_val[i_segment*elem_nodes+1]]; Real * x3 = &coord[2*i_node]; Real vec_surf[2]; Real vec_dist[2]; Math::vector_2d(x1, x2, vec_surf); Math::vector_2d(x1, x3, vec_dist); Real length = Math::distance_2d(x1, x2); Real proj = Math::vectorDot2(vec_surf, vec_dist)/(length*length); if(proj < 0. || proj >1.) { Real dist; if(proj < 0.) dist = Math::distance_2d(x1, x3); else dist = Math::distance_2d(x2, x3); if(dist < 0.5*spacing) { if (stored == false) { stored = true; neighbor_list->impactor_nodes.push_back(i_node); neighbor_list->facets_offset[el_type]->push_back((UInt)0); } neighbor_list->facets_offset[el_type]->values[neighbor_list->impactor_nodes.getSize()]++; neighbor_list->facets[el_type]->push_back(i_segment); } } else { Real vec_normal[2]; Math::normal2(vec_surf, vec_normal); Real gap = Math::vectorDot2(vec_dist, vec_normal); if(fabs(gap) < 0.5*spacing) { if (stored == false) { stored = true; neighbor_list->impactor_nodes.push_back(i_node); neighbor_list->facets_offset[el_type]->push_back((UInt)0); } neighbor_list->facets_offset[el_type]->values[neighbor_list->impactor_nodes.getSize()]++; neighbor_list->facets[el_type]->push_back(i_segment); } } } } /* end loop segments */ } /* end loop over cells */ } /* end loop over slave nodes */ } /* end loop over surfaces */ /// convert occurence array in a csv one UInt * facet_off = neighbor_list->facets_offset[el_type]->values; for (UInt i = 1; i < neighbor_list->facets_offset[el_type]->getSize(); ++i) facet_off[i] += facet_off[i-1]; /// free temporary vectors delete[] x_bounds; delete[] y_bounds; delete[] cell_to_segments_offset; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real Grid2dNeighborStructure::getMinSize(Real * coord) { AKANTU_DEBUG_IN(); ElementType el_type = _segment_2; /* Only linear element at the moment */ UInt * conn_val = mesh.getConnectivity(el_type).values; UInt nb_elements = mesh.getConnectivity(el_type).getSize(); UInt * surface_id_val = mesh.getSurfaceId(el_type).values; UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); Real min_size = std::numeric_limits<Real>::max(); /// loop over master segments for (UInt el = 0; el < nb_elements; ++el) if (surface_id_val[el] == master_surface) { Real * x1 = &coord[2*conn_val[el*elem_nodes]]; Real * x2 = &coord[2*conn_val[el*elem_nodes+1]]; Real length = (x1[0]-x2[0])*(x1[0]-x2[0])+(x1[1]-x2[1])*(x1[1]-x2[1]); if (length < min_size) min_size = length; } return sqrt(min_size); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Grid2dNeighborStructure::getBounds(Real * coord, Real * x_bounds, Real * y_bounds) { AKANTU_DEBUG_IN(); /// initialize bounds UInt nb_surfaces = mesh.getNbSurfaces(); for (UInt s = 0; s < nb_surfaces; ++s) { x_bounds[s*2] = std::numeric_limits<Real>::max(); x_bounds[s*2+1] = -std::numeric_limits<Real>::max(); y_bounds[s*2] = std::numeric_limits<Real>::max(); y_bounds[s*2+1] = -std::numeric_limits<Real>::max(); } UInt * surf_nodes_off = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surf_nodes = contact_search.getContact().getSurfaceToNodes().values; /// find min and max coordinates of each surface for (UInt s = 0; s < nb_surfaces; ++s) { for (UInt n = surf_nodes_off[s]; n < surf_nodes_off[s+1]; ++n) { UInt i_node = surf_nodes[n]; if(coord[i_node*2] < x_bounds[s*2]) x_bounds[s*2] = coord[i_node*2]; if(coord[i_node*2] > x_bounds[2*s+1]) x_bounds[2*s+1] = coord[i_node*2]; if(coord[i_node*2+1] < y_bounds[2*s]) y_bounds[2*s] = coord[i_node*2+1]; if(coord[i_node*2+1] > y_bounds[2*s+1]) y_bounds[2*s+1] = coord[i_node*2+1]; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool Grid2dNeighborStructure::getBoundsIntersection(Real * x_bounds, Real * y_bounds, Real * x_int, Real * y_int) { AKANTU_DEBUG_IN(); bool find_intersection = false; UInt nb_surfaces = mesh.getNbSurfaces(); x_int[0] = std::numeric_limits<Real>::max(); x_int[1] = -std::numeric_limits<Real>::max(); y_int[0] = std::numeric_limits<Real>::max(); y_int[1] = -std::numeric_limits<Real>::max(); /// enlarge bounds of master surface within a tolerance x_bounds[2*master_surface] -= 1.49999*spacing; x_bounds[2*master_surface+1] += 1.49999*spacing; y_bounds[2*master_surface] -= 1.49999*spacing; y_bounds[2*master_surface+1] += 1.49999*spacing; /// loop over surfaces for (UInt s = 0; s < nb_surfaces; ++s) { if(s == master_surface) continue; Real x_temp[2] = {REAL_INIT_VALUE, REAL_INIT_VALUE}; Real y_temp[2] = {REAL_INIT_VALUE, REAL_INIT_VALUE}; /// find if intersection in x exists if(x_bounds[2*master_surface] > x_bounds[2*s]) { /* starting point of possible intersection */ x_temp[0] = x_bounds[2*master_surface]; /* find ending point of possible intersection */ if(x_bounds[2*s+1] < x_bounds[2*master_surface]) continue; else if(x_bounds[2*s+1] < x_bounds[2*master_surface+1]) x_temp[1] = x_bounds[2*s+1]; else x_temp[1] = x_bounds[2*master_surface+1]; } else { /* starting point of possible intersection */ x_temp[0] = x_bounds[2*s]; /* find ending point of possible intersection */ if(x_bounds[2*master_surface+1] < x_bounds[2*s]) continue; else if(x_bounds[2*master_surface+1] < x_bounds[2*s+1]) x_temp[1] = x_bounds[2*master_surface+1]; else x_temp[1] = x_bounds[2*s+1]; } /// find if intersection in y exists if(y_bounds[2*master_surface] > y_bounds[2*s]) { /* starting point of possible intersection */ y_temp[0] = y_bounds[2*master_surface]; /* find ending point of possible intersection */ if(y_bounds[2*s+1] < y_bounds[2*master_surface]) continue; else if(y_bounds[2*s+1] < y_bounds[2*master_surface+1]) y_temp[1] = y_bounds[2*s+1]; else y_temp[1] = y_bounds[2*master_surface+1]; } else { /* starting point of possible intersection */ y_temp[0] = y_bounds[2*s]; /* find ending point of possible intersection */ if(y_bounds[2*master_surface+1] < y_bounds[2*s]) continue; else if(y_bounds[2*master_surface+1] < y_bounds[2*s+1]) y_temp[1] = y_bounds[2*master_surface+1]; else y_temp[1] = y_bounds[2*s+1]; } /// intersection exists, find its minimum/maximum find_intersection = true; x_int[0] = std::min(x_int[0], x_temp[0]); x_int[1] = std::max(x_int[1], x_temp[1]); y_int[0] = std::min(y_int[0], y_temp[0]); y_int[1] = std::max(y_int[1], y_temp[1]); } return find_intersection; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Grid2dNeighborStructure::traceSegments(Real * coord, Real * origin, UInt * nb_cells, UInt * cell_to_seg_off, Vector<UInt> & cell_to_segments) { AKANTU_DEBUG_IN(); Vector<UInt> temp(0, 2); UInt index[2] = {0, 0}; ElementType el_type = _segment_2; /* Only linear element at the moment */ UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); UInt * surface_id_val = mesh.getSurfaceId(el_type).values; UInt * conn_val = mesh.getConnectivity(el_type).values; UInt nb_segments = mesh.getConnectivity(el_type).getSize(); Int nb_x = nb_cells[0]; Int nb_y = nb_cells[1]; /// Detect cells which are crossed by the segments for (UInt el = 0; el < nb_segments; ++el) if (surface_id_val[el] == master_surface) { /* Compute relative coords and index of the staring and ending cell (in respect to the grid) */ Real x1 = (coord[2*conn_val[elem_nodes*el]] - origin[0])/spacing; Real y1 = (coord[2*conn_val[elem_nodes*el]+1] - origin[1])/spacing; Real x2 = (coord[2*conn_val[elem_nodes*el+1]] - origin[0])/spacing; Real y2 = (coord[2*conn_val[elem_nodes*el+1]+1] - origin[1])/spacing; Int ii = (Int)std::floor(x1); Int jj = (Int)std::floor(y1); Int kk = (Int)std::floor(x2); Int ll = (Int)std::floor(y2); /// check if segment outside grid if((std::max(ii,kk)<0 || std::min(ii,kk)>=nb_x) || (std::max(jj,ll)<0 || std::min(jj,ll)>=nb_y)) continue; /* */ Real dx = fabs(x2-x1); Real dy = fabs(y2-y1); Int n = 0; Int ii_inc, jj_inc; Real error; if(dx == 0.) { ii_inc = 0; error = std::numeric_limits<Real>::max(); } else if(x2 > x1) { ii_inc = 1; n = kk-ii; error = (ii+1-x1)*dy; } else { /* x1 < x2 */ ii_inc = -1; n = ii-kk; error = (x1-ii)*dy; } if(dy == 0.) { jj_inc = 0; error = -std::numeric_limits<Real>::max(); } else if(y2 > y1) { jj_inc = 1; n += ll-jj; error -= (jj+1-y1)*dx; } else { /* y1 < y2 */ jj_inc = -1; n += jj-ll; error -= (y1-jj)*dx; } while(true) { /* check if intersected cell belong to the grid */ if((ii>=0 && ii< nb_x) && (jj>=0 && jj<nb_y)) { /* Increase offset */ index[0] = (UInt)(ii+jj*nb_x); index[1] = el; cell_to_seg_off[index[0]]++; temp.push_back(index); } if(n==0) break; /* Move to the next cell */ if(error > 0) { /* ..move in y-direction */ jj += jj_inc; error -= dx; } else { /* ..move in x-direction */ ii += ii_inc; error += dy; } n--; } } /// convert the occurrence array in a csr one for (UInt i = 1; i < nb_cells[2]; ++i) cell_to_seg_off[i] += cell_to_seg_off[i-1]; for (UInt i = nb_cells[2]; i > 0; --i) cell_to_seg_off[i] = cell_to_seg_off[i-1]; cell_to_seg_off[0] = 0; /// rearrange segments to get the cell-segments list cell_to_segments.resize(cell_to_seg_off[nb_cells[2]]); UInt * cell_val = cell_to_segments.values; UInt * tmp = temp.values; UInt nb_traced = temp.getSize(); for (UInt i = 0; i < nb_traced; i++) { cell_val[cell_to_seg_off[tmp[2*i]]] = tmp[2*i+1]; cell_to_seg_off[tmp[2*i]]++; } /// reconvert occurence array in a csr one for (UInt i = nb_cells[2]; i > 0; --i) cell_to_seg_off[i] = cell_to_seg_off[i-1]; cell_to_seg_off[0] = 0; AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/contact/grid_2d_neighbor_structure.hh b/model/solid_mechanics/contact/grid_2d_neighbor_structure.hh index 9167ac2e6..43f42b005 100644 --- a/model/solid_mechanics/contact/grid_2d_neighbor_structure.hh +++ b/model/solid_mechanics/contact/grid_2d_neighbor_structure.hh @@ -1,117 +1,131 @@ /** * @file grid_2d_neighbor_structure.hh * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @date Tue Dec 7 12:54:48 2010 * * @brief Class which creates the neighbor lists (with a grid) to handle contact in 2d * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_GRID_2D_NEIGHBOR_STRUCTURE_HH__ #define __AKANTU_GRID_2D_NEIGHBOR_STRUCTURE_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_vector.hh" #include "contact_neighbor_structure.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class mesh; } __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ class Grid2dNeighborStructure : public ContactNeighborStructure{ /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Grid2dNeighborStructure(const ContactSearch & contact_search, const Surface & master_surface, const ContactNeighborStructureType & type, const ContactNeighborStructureID & id = "contact_neighbor_structure_id"); virtual ~Grid2dNeighborStructure(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the structure void initNeighborStructure(); /// update the structure void update(); /// check if an update is needed bool check(); /// function to print the contain of the class //virtual void printself(std::ostream & stream, int indent = 0) const; private: /// main routine to create the grid and fill the neighbor list void createGrid(bool initial_position); /// get extrema of each surface void getBounds(Real * coord, Real * x_bounds, Real * y_bounds); /// get intersection space between master surface and slave ones bool getBoundsIntersection(Real *x_bounds, Real * y_bounds, Real * x_int, Real * y_int); /// get minimum mesh size (segment length) Real getMinSize(Real * coord); /// which grid cells are intersected by segment of the master surface void traceSegments(Real * coord, Real * origin, UInt * nb_cells, UInt * cell_to_seg_off, Vector<UInt> & cell_to_segments); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// Mesh Mesh & mesh; /// grid spacing Real spacing; /// maximal displacement for grid update Real max_increment[2]; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "2d_grid_neighbor_structure_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const Grid2dNeighborStructure & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_GRID_2D_NEIGHBOR_STRUCTURE_HH__ */ diff --git a/model/solid_mechanics/contact/regular_grid_neighbor_structure.cc b/model/solid_mechanics/contact/regular_grid_neighbor_structure.cc index 562229ce8..61e40268d 100644 --- a/model/solid_mechanics/contact/regular_grid_neighbor_structure.cc +++ b/model/solid_mechanics/contact/regular_grid_neighbor_structure.cc @@ -1,715 +1,729 @@ /** * @file regular_grid_neighbor_structure.cc * @author David Kammer <david.kammer@epfl.ch> * @date Mon Oct 11 16:03:17 2010 * * @brief Specialization of the contact neighbor structure for regular grid * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ NodesNeighborList::NodesNeighborList() : NeighborList(), master_nodes_offset(Vector<UInt>(0, 1, "master_nodes_offset")), master_nodes (Vector<UInt>(0, 1, "master_nodes")) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> RegularGridNeighborStructure<spatial_dimension>::RegularGridNeighborStructure(const ContactSearch & contact_search, const Surface & master_surface, const ContactNeighborStructureType & type, const ContactNeighborStructureID & id) : ContactNeighborStructure(contact_search, master_surface, type, id), mesh(contact_search.getContact().getModel().getFEM().getMesh()) { AKANTU_DEBUG_IN(); /// chose the neighbor list and initialize it /*if (contact_search.getType() == _cst_3d_expli) { neighbor_list = new NodesNeighborList(); nodes_neighbor_list = true; } else { neighbor_list = new NeighborList(); nodes_neighbor_list = false; } */ this->constructNeighborList(); /// make sure that the increments are computed const_cast<SolidMechanicsModel &>(contact_search.getContact().getModel()).setIncrementFlagOn(); /// arbitrary initial value grid_spacing[0] = 0.05; grid_spacing[1] = 0.05; grid_spacing[2] = 0.05; /// securty factor of max 0.5 is needed for a neighborlist that is always complete security_factor[0] = 0.5; security_factor[1] = 0.5; security_factor[2] = 0.5; /// maximal increment since last update of neighborlist max_increment[0] = 0.0; max_increment[1] = 0.0; max_increment[2] = 0.0; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> RegularGridNeighborStructure<spatial_dimension>::~RegularGridNeighborStructure() { AKANTU_DEBUG_IN(); delete neighbor_list; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void RegularGridNeighborStructure<spatial_dimension>::initNeighborStructure() { AKANTU_DEBUG_IN(); this->setMinimalGridSpacing(); //Real * node_coordinates = mesh.getNodes().values; Real * node_coordinates = contact_search.getContact().getModel().getCurrentPosition().values; this->update(node_coordinates); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void RegularGridNeighborStructure<spatial_dimension>::update() { AKANTU_DEBUG_IN(); this->setMinimalGridSpacing(); // delete neighbor list and reconstruct it delete this->neighbor_list; this->constructNeighborList(); Real * node_current_position = contact_search.getContact().getModel().getCurrentPosition().values; this->update(node_current_position); /// reset max_increment to zero for(UInt i = 0; i < spatial_dimension; ++i) max_increment[i] = 0.0; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void RegularGridNeighborStructure<spatial_dimension>::update(Real * node_position) { AKANTU_DEBUG_IN(); UInt nb_surfaces = mesh.getNbSurfaces(); AKANTU_DEBUG_ASSERT(master_surface < nb_surfaces, "Master surface (" << master_surface << ") out of surface range (number of surfaces: " << nb_surfaces << ") !!"); // ---------------------------- /// find max and min values for each surface // ---------------------------- Real bound_max[nb_surfaces][spatial_dimension]; Real bound_min[nb_surfaces][spatial_dimension]; /// initialize max and min table with extrem values for(UInt surf = 0; surf < nb_surfaces; ++surf) { for(UInt dim = 0; dim < spatial_dimension; ++dim) { bound_max[surf][dim] = - std::numeric_limits<Real>::max(); bound_min[surf][dim] = std::numeric_limits<Real>::max(); } } // get nodes that are on a given surface UInt * surface_to_nodes_offset = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surface_to_nodes = contact_search.getContact().getSurfaceToNodes().values; /// find max and min values of current position for each surface for(UInt surf = 0; surf < nb_surfaces; ++surf) { UInt min_surf_offset = surface_to_nodes_offset[surf]; UInt max_surf_offset = surface_to_nodes_offset[surf + 1]; for(UInt n = min_surf_offset; n < max_surf_offset; ++n) { UInt cur_node = surface_to_nodes[n]; for(UInt dim = 0; dim < spatial_dimension; ++dim) { Real cur_position = node_position[cur_node * spatial_dimension + dim]; bound_max[surf][dim] = std::max(bound_max[surf][dim], cur_position); bound_min[surf][dim] = std::min(bound_min[surf][dim], cur_position); } } } // ---------------------------- /// define grid geometry // ---------------------------- /// define grid geometry around the master surface Real grid_min[spatial_dimension]; Real grid_max[spatial_dimension]; UInt directional_nb_cells[spatial_dimension]; UInt nb_cells = 1; for(UInt dim = 0; dim < spatial_dimension; ++dim) { Real grid_length = bound_max[master_surface][dim] - bound_min[master_surface][dim]; /// get nb of cells needed to cover total length and add a cell to each side (start, end) directional_nb_cells[dim] = static_cast<UInt>(ceil(grid_length / grid_spacing[dim])) + 2; nb_cells *= directional_nb_cells[dim]; Real additional_grid_length = (directional_nb_cells[dim]*grid_spacing[dim] - grid_length) / 2.; /// get minimal and maximal coordinates of the grid grid_min[dim] = bound_min[master_surface][dim] - additional_grid_length; grid_max[dim] = bound_max[master_surface][dim] + additional_grid_length; } // ---------------------------- /// find surfaces being in the grid space // ---------------------------- /// find surfaces being in the grid space UInt nb_grid_surfaces = 0; UInt grid_surfaces[nb_surfaces]; UInt not_grid_space = 0; for(UInt surf = 0; surf < nb_surfaces; ++surf) { for(UInt dim = 0; dim < spatial_dimension; ++dim) { if(bound_max[surf][dim] < grid_min[dim] || bound_min[surf][dim] > grid_max[dim]) not_grid_space = 1; } if(not_grid_space == 0 || surf == master_surface) { grid_surfaces[nb_grid_surfaces++] = surf; } not_grid_space = 0; } /// if number of grid surfaces is equal to 1 we do not need to consider any slave surface /// @todo exit with empty neighbor list // ---------------------------- /// define cell number for all surface nodes // ---------------------------- /// assign cell number to all surface nodes (put -1 if out of grid space) (cell numbers start with zero) Int not_grid_space_node = -1; // should not be same as not_grid_space_surface and be < 0 Int not_grid_space_surface = -2; // should not be same as not_grid_space_node and be < 0 Int directional_cell[spatial_dimension]; UInt nb_surface_nodes = surface_to_nodes_offset[nb_surfaces]; Vector<Int> * cell = new Vector<Int>(nb_surface_nodes, 1, not_grid_space_surface); Int * cell_val = cell->values; /// define the cell number for all surface nodes for(UInt surf = 0; surf < nb_grid_surfaces; ++surf) { UInt current_surface = grid_surfaces[surf]; UInt min_surf_offset = surface_to_nodes_offset[current_surface]; UInt max_surf_offset = surface_to_nodes_offset[current_surface + 1]; for(UInt n = min_surf_offset; n < max_surf_offset; ++n) { UInt cur_node = surface_to_nodes[n]; /// compute cell index for all directions for(UInt dim = 0; dim < spatial_dimension; ++dim) { Real cur_position = node_position[cur_node * spatial_dimension + dim]; directional_cell[dim] = static_cast<UInt>(floor((cur_position - grid_min[dim])/grid_spacing[dim])); } /// test if out of grid space for(UInt dim = 0; dim < spatial_dimension; ++dim) { if(directional_cell[dim] < 0 || directional_cell[dim] >= directional_nb_cells[dim]) { cell_val[n] = not_grid_space_node; } } /// compute global cell index if(cell_val[n] != not_grid_space_node) cell_val[n] = computeCellNb(directional_nb_cells, directional_cell); } } // ---------------------------- /// find all impactor and master nodes for given cell // ---------------------------- /// define offset arrays for nodes per cell which will be computed below UInt * impactor_nodes_cell_offset = new UInt[nb_cells + 1]; memset(impactor_nodes_cell_offset, 0, nb_cells * sizeof(UInt)); UInt * master_nodes_cell_offset = new UInt[nb_cells + 1]; memset(master_nodes_cell_offset, 0, nb_cells * sizeof(UInt)); /// count number of nodes per cell for impactors and master for(UInt surf = 0; surf < nb_grid_surfaces; ++surf) { UInt current_surface = grid_surfaces[surf]; UInt min_surf_offset = surface_to_nodes_offset[current_surface]; UInt max_surf_offset = surface_to_nodes_offset[current_surface + 1]; /// define temporary pointers UInt * nodes_cell_offset; if(current_surface == master_surface) { nodes_cell_offset = master_nodes_cell_offset; } else { nodes_cell_offset = impactor_nodes_cell_offset; } for(UInt n = min_surf_offset; n < max_surf_offset; ++n) { Int cur_cell = cell_val[n]; if(cur_cell != not_grid_space_node) nodes_cell_offset[cur_cell]++; } } /// create two separate offset arrays for impactor nodes and master nodes for (UInt i = 1; i < nb_cells; ++i) { impactor_nodes_cell_offset[i] += impactor_nodes_cell_offset[i - 1]; master_nodes_cell_offset [i] += master_nodes_cell_offset [i - 1]; } for (UInt i = nb_cells; i > 0; --i) { impactor_nodes_cell_offset[i] = impactor_nodes_cell_offset[i - 1]; master_nodes_cell_offset [i] = master_nodes_cell_offset [i - 1]; } impactor_nodes_cell_offset[0] = 0; master_nodes_cell_offset [0] = 0; /// find all impactor and master nodes in a cell UInt * impactor_nodes_cell = new UInt[impactor_nodes_cell_offset[nb_cells]]; UInt * master_nodes_cell = new UInt[master_nodes_cell_offset [nb_cells]]; cell_val = cell->values; for(UInt surf = 0; surf < nb_grid_surfaces; ++surf) { UInt current_surface = grid_surfaces[surf]; UInt min_surf_offset = surface_to_nodes_offset[current_surface]; UInt max_surf_offset = surface_to_nodes_offset[current_surface + 1]; /// define temporary variables UInt * nodes_cell; UInt * nodes_cell_offset; if(current_surface == master_surface) { nodes_cell = master_nodes_cell; nodes_cell_offset = master_nodes_cell_offset; } else { nodes_cell = impactor_nodes_cell; nodes_cell_offset = impactor_nodes_cell_offset; } /// loop over the nodes of surf and create nodes_cell for(UInt n = min_surf_offset; n < max_surf_offset; ++n) { UInt node = surface_to_nodes[n]; Int cur_cell = cell_val[n]; if(cur_cell != not_grid_space_node) nodes_cell[nodes_cell_offset[cur_cell]++] = node; } } for (UInt i = nb_cells; i > 0; --i) { impactor_nodes_cell_offset[i] = impactor_nodes_cell_offset[i - 1]; master_nodes_cell_offset [i] = master_nodes_cell_offset[i - 1]; } impactor_nodes_cell_offset[0] = 0; master_nodes_cell_offset [0] = 0; if(nodes_neighbor_list == true) constructNodesNeighborList(directional_nb_cells, nb_cells, cell, impactor_nodes_cell_offset, impactor_nodes_cell, master_nodes_cell_offset, master_nodes_cell); else constructNeighborList(directional_nb_cells, nb_cells, cell, impactor_nodes_cell_offset, impactor_nodes_cell, master_nodes_cell_offset, master_nodes_cell); delete [] impactor_nodes_cell; delete [] impactor_nodes_cell_offset; delete [] master_nodes_cell; delete [] master_nodes_cell_offset; delete cell; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void RegularGridNeighborStructure<spatial_dimension>::constructNeighborList(UInt directional_nb_cells[spatial_dimension], UInt nb_cells, Vector<Int> * cell, UInt * impactor_nodes_cell_offset, UInt * impactor_nodes_cell, UInt * master_nodes_cell_offset, UInt * master_nodes_cell) { AKANTU_DEBUG_IN(); UInt * surface_to_nodes_offset = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surface_to_nodes = contact_search.getContact().getSurfaceToNodes().values; UInt nb_surfaces = mesh.getNbSurfaces(); UInt nb_surface_nodes = surface_to_nodes_offset[nb_surfaces]; Int * cell_val = cell->values; UInt nb_impactor_nodes = impactor_nodes_cell_offset[nb_cells]; //neighbor_list->impactor_nodes.resize(nb_impactor_nodes); //UInt * impactor_nodes_val = neighbor_list->impactor_nodes.values; /// define maximal number of neighbor cells and include it-self UInt max_nb_neighbor_cells; if(spatial_dimension == 2) { max_nb_neighbor_cells = 9; } else if(spatial_dimension == 3) { max_nb_neighbor_cells = 27; } const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; /// find existing surface element types UInt nb_types = type_list.size(); UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { facet_type[nb_facet_types++] = mesh.getFacetElementType(type); } } /// loop over all existing surface element types for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) { ElementType type = facet_type[el_type]; const Vector<UInt> & node_to_elements_offset = contact_search.getContact().getNodeToElementsOffset(type); const Vector<UInt> & node_to_elements = contact_search.getContact().getNodeToElements(type); UInt * node_to_elements_offset_val = node_to_elements_offset.values; UInt * node_to_elements_val = node_to_elements.values; UInt * surface_id_val = mesh.getSurfaceId(type).values; Vector<bool> * visited_node = new Vector<bool>(nb_impactor_nodes, 1, false); // does it need a delete at the end ? bool * visited_node_val = visited_node->values; UInt neighbor_cells[max_nb_neighbor_cells]; std::stringstream sstr_name_offset; sstr_name_offset << id << ":facets_offset:" << type; neighbor_list->facets_offset[type] = new Vector<UInt>(0, 1, sstr_name_offset.str()); Vector<UInt> & tmp_facets_offset = *(neighbor_list->facets_offset[type]); std::stringstream sstr_name; sstr_name << id << ":facets:" << type; neighbor_list->facets[type] = new Vector<UInt>(0, 1, sstr_name.str());// declare vector that is ?? Vector<UInt> & tmp_facets = *(neighbor_list->facets[type]); for(UInt in = 0; in < nb_impactor_nodes; ++in) { UInt current_impactor_node = impactor_nodes_cell[in]; /// test if nodes has not already been visited if(!visited_node_val[in]) { /// find and store cell numbers of neighbor cells and it-self AKANTU_DEBUG_ASSERT(cell_val[current_impactor_node] >= 0, "Bad cell index. This case normally should not happen !!"); UInt current_cell; for(UInt i = 0; i < nb_surface_nodes; ++i) { if(surface_to_nodes[i] == current_impactor_node) { current_cell = cell_val[i]; break; } } // test if current_cell was initialized //UInt current_cell = cell_val[current_impactor_node]; UInt nb_neighbor_cells = computeNeighborCells(current_cell, neighbor_cells, directional_nb_cells); neighbor_cells[nb_neighbor_cells++] = current_cell; /// define a set in which the found master surface elements are stored std::set<UInt> master_surface_elements; std::set<UInt>::iterator it_set; /// find all master elements that are in the considered region for(UInt cl = 0; cl < nb_neighbor_cells; ++cl) { /// get cell number and offset range UInt considered_cell = neighbor_cells[cl]; UInt min_master_offset = master_nodes_cell_offset[considered_cell]; UInt max_master_offset = master_nodes_cell_offset[considered_cell + 1]; for(UInt mn = min_master_offset; mn < max_master_offset; ++mn) { UInt master_node = master_nodes_cell[mn]; UInt min_element_offset = node_to_elements_offset_val[master_node]; UInt max_element_offset = node_to_elements_offset_val[master_node + 1]; for(UInt el = min_element_offset; el < max_element_offset; ++el) { if(surface_id_val[node_to_elements_val[el]] == master_surface) master_surface_elements.insert(node_to_elements_val[el]); } } } UInt min_impactor_offset = impactor_nodes_cell_offset[current_cell]; UInt max_impactor_offset = impactor_nodes_cell_offset[current_cell + 1]; for(UInt imp = min_impactor_offset; imp < max_impactor_offset; ++imp) { UInt impactor_node = impactor_nodes_cell[imp]; neighbor_list->impactor_nodes.push_back(impactor_node); //impactor_nodes_val[neighbor_list->nb_nodes++] = impactor_node; for(it_set = master_surface_elements.begin(); it_set != master_surface_elements.end(); it_set++) { tmp_facets.push_back(*it_set); } tmp_facets_offset.push_back(master_surface_elements.size()); for(UInt inn = 0; inn < nb_impactor_nodes; ++inn) { if(impactor_nodes_cell[inn] == impactor_node) { visited_node_val[inn] = true; break; } } } } } tmp_facets_offset.resize(tmp_facets_offset.getSize()+1); // increase size off offset table by one UInt * tmp_facets_offset_val = tmp_facets_offset.values; for (UInt i = 1; i < neighbor_list->impactor_nodes.getSize(); ++i) tmp_facets_offset_val[i] += tmp_facets_offset_val[i - 1]; for (UInt i = neighbor_list->impactor_nodes.getSize(); i > 0; --i) tmp_facets_offset_val[i] = tmp_facets_offset_val[i - 1]; tmp_facets_offset_val[0] = 0; delete visited_node; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void RegularGridNeighborStructure<spatial_dimension>::constructNodesNeighborList(UInt directional_nb_cells[spatial_dimension], UInt nb_cells, Vector<Int> * cell, UInt * impactor_nodes_cell_offset, UInt * impactor_nodes_cell, UInt * master_nodes_cell_offset, UInt * master_nodes_cell) { AKANTU_DEBUG_IN(); NodesNeighborList * nodes_neighbor_list = dynamic_cast<NodesNeighborList *>(neighbor_list); UInt * surface_to_nodes_offset = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surface_to_nodes = contact_search.getContact().getSurfaceToNodes().values; UInt nb_surfaces = mesh.getNbSurfaces(); UInt nb_surface_nodes = surface_to_nodes_offset[nb_surfaces]; Int * cell_val = cell->values; UInt nb_impactor_nodes = impactor_nodes_cell_offset[nb_cells]; /// define maximal number of neighbor cells and include it-self UInt max_nb_neighbor_cells; if(spatial_dimension == 2) { max_nb_neighbor_cells = 9; } else if(spatial_dimension == 3) { max_nb_neighbor_cells = 27; } UInt neighbor_cells[max_nb_neighbor_cells]; for(UInt in = 0; in < nb_impactor_nodes; ++in) { UInt current_impactor_node = impactor_nodes_cell[in]; nodes_neighbor_list->impactor_nodes.push_back(current_impactor_node); //nodes_neighbor_list->nb_nodes += 1; /// find and store cell numbers of neighbor cells and it-self UInt current_cell; bool init = false; for(UInt i = 0; i < nb_surface_nodes; ++i) { if(surface_to_nodes[i] == current_impactor_node) { AKANTU_DEBUG_ASSERT(cell_val[i] >= 0, "Bad cell index. This case normally should not happen !!"); current_cell = cell_val[i]; init = true; break; } } AKANTU_DEBUG_ASSERT(init, "Cell number of node is not initialized"); UInt nb_neighbor_cells = computeNeighborCells(current_cell, neighbor_cells, directional_nb_cells); neighbor_cells[nb_neighbor_cells++] = current_cell; UInt tmp_nb_master_nodes = 0; /// find all master elements that are in the considered region for(UInt cl = 0; cl < nb_neighbor_cells; ++cl) { /// get cell number and offset range UInt considered_cell = neighbor_cells[cl]; UInt min_master_offset = master_nodes_cell_offset[considered_cell]; UInt max_master_offset = master_nodes_cell_offset[considered_cell + 1]; for(UInt mn = min_master_offset; mn < max_master_offset; ++mn) { UInt master_node = master_nodes_cell[mn]; nodes_neighbor_list->master_nodes.push_back(master_node); } tmp_nb_master_nodes += max_master_offset - min_master_offset; } nodes_neighbor_list->master_nodes_offset.push_back(tmp_nb_master_nodes); } nodes_neighbor_list->master_nodes_offset.resize(nodes_neighbor_list->master_nodes_offset.getSize()+1); // increase size off offset table by one UInt * master_nodes_offset_val = nodes_neighbor_list->master_nodes_offset.values; for (UInt i = 1; i < nodes_neighbor_list->impactor_nodes.getSize(); ++i) master_nodes_offset_val[i] += master_nodes_offset_val[i - 1]; for (UInt i = nodes_neighbor_list->impactor_nodes.getSize(); i > 0; --i) master_nodes_offset_val[i] = master_nodes_offset_val[i - 1]; master_nodes_offset_val[0] = 0; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> bool RegularGridNeighborStructure<spatial_dimension>::check() { AKANTU_DEBUG_IN(); bool need_update = false; UInt nb_surfaces = mesh.getNbSurfaces(); Real * current_increment = contact_search.getContact().getModel().getIncrement().values; Real max[spatial_dimension]; /// initialize max table with extrem values for(UInt dim = 0; dim < spatial_dimension; ++dim) max[dim] = 0.0; // get the nodes that are on the surfaces UInt * surface_to_nodes_offset = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surface_to_nodes = contact_search.getContact().getSurfaceToNodes().values; /// find maximal increment of surface nodes in all directions for(UInt surf = 0; surf < nb_surfaces; ++surf) { UInt min_surf_offset = surface_to_nodes_offset[surf]; UInt max_surf_offset = surface_to_nodes_offset[surf + 1]; for(UInt n = min_surf_offset; n < max_surf_offset; ++n) { UInt cur_node = surface_to_nodes[n]; for(UInt dim = 0; dim < spatial_dimension; ++dim) { Real cur_increment = current_increment[cur_node * spatial_dimension + dim]; max[dim] = std::max(max[dim], fabs(cur_increment)); } } } /// test if the total increment is larger than a critical distance for(UInt dim = 0; dim < spatial_dimension; ++dim) { max_increment[dim] += max[dim]; if(max_increment[dim] > security_factor[dim] * grid_spacing[dim]) { need_update = true; break; } } AKANTU_DEBUG_OUT(); return need_update; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> void RegularGridNeighborStructure<spatial_dimension>::setMinimalGridSpacing() { AKANTU_DEBUG_IN(); Real min_cell_size[3] = {0.,0.,0.}; Real margin = 1.2; Real * node_current_position = contact_search.getContact().getModel().getCurrentPosition().values; const Mesh::ConnectivityTypeList & type_list = this->mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; /// find existing surface element types UInt nb_types = type_list.size(); UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { facet_type[nb_facet_types++] = mesh.getFacetElementType(type); } } /// loop over all existing surface element types for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) { ElementType type = facet_type[el_type]; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_element = mesh.getNbNodesPerElement(type); UInt * conn = mesh.getConnectivity(type).values; const UInt *surf_id_val = mesh.getSurfaceId(type).values; for(UInt e = 0; e < nb_element; ++e) { if(surf_id_val[e] == master_surface) { Real min_coord[3]; Real max_coord[3]; for(UInt dim = 0; dim < spatial_dimension; ++dim) { min_coord[dim] = std::numeric_limits<Real>::max(); max_coord[dim] = - std::numeric_limits<Real>::max(); } for(UInt n = 0; n < nb_nodes_element; ++n) { UInt node = conn[e*nb_nodes_element + n]; for(UInt dim = 0; dim < spatial_dimension; ++dim) { Real cur_position = node_current_position[node*spatial_dimension + dim]; min_coord[dim] = std::min(min_coord[dim], cur_position); max_coord[dim] = std::max(max_coord[dim], cur_position); } } for(UInt dim = 0; dim < spatial_dimension; ++dim) { min_cell_size[dim] = std::max(min_cell_size[dim], max_coord[dim] - min_coord[dim]); } } } } // find largest grid_spacing in all direction Real max_grid_spacing = 0.; for(UInt dim = 0; dim < spatial_dimension; ++dim) max_grid_spacing = std::max(max_grid_spacing, min_cell_size[dim]); // use the max grid spacing for all direction (multiplied by a margin) for(UInt dim = 0; dim < spatial_dimension; ++dim) this->grid_spacing[dim] = margin * max_grid_spacing; AKANTU_DEBUG_OUT(); } template class RegularGridNeighborStructure<2>; template class RegularGridNeighborStructure<3>; __END_AKANTU__ diff --git a/model/solid_mechanics/contact/regular_grid_neighbor_structure.hh b/model/solid_mechanics/contact/regular_grid_neighbor_structure.hh index 7355afdef..84dd1bb26 100644 --- a/model/solid_mechanics/contact/regular_grid_neighbor_structure.hh +++ b/model/solid_mechanics/contact/regular_grid_neighbor_structure.hh @@ -1,170 +1,184 @@ /** * @file regular_grid_neighbor_structure.hh * @author David Kammer <david.kammer@epfl.ch> * @date Mon Oct 11 10:35:04 2010 * * @brief Structure that handles the neighbor lists by a regular grid * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_REGULAR_GRID_NEIGHBOR_STRUCTURE_HH__ #define __AKANTU_REGULAR_GRID_NEIGHBOR_STRUCTURE_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_vector.hh" #include "contact_neighbor_structure.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class mesh; } __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ class NodesNeighborList : public NeighborList { public: NodesNeighborList(); virtual ~NodesNeighborList() {}; public: /// neighbor master nodes Vector<UInt> master_nodes_offset; Vector<UInt> master_nodes; }; /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> class RegularGridNeighborStructure : public ContactNeighborStructure { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: RegularGridNeighborStructure(const ContactSearch & contact_search, const Surface & master_surface, const ContactNeighborStructureType & type, const ContactNeighborStructureID & id = "contact_neighbor_structure_id"); virtual ~RegularGridNeighborStructure(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the structure void initNeighborStructure(); /// update the structure void update(); /// check if an update is needed bool check(); /// function to print the contain of the class //virtual void printself(std::ostream & stream, int indent = 0) const; private: /// compute neighbor structure void update(Real * node_position); /// construct neighbor list void constructNeighborList(UInt directional_nb_cells[spatial_dimension], UInt nb_cells, Vector<Int> * cell, UInt * impactor_nodes_cell_offset, UInt * impactor_nodes_cell, UInt * master_nodes_cell_offset, UInt * master_nodes_cell); /// construct nodes neighbor list void constructNodesNeighborList(UInt directional_nb_cells[spatial_dimension], UInt nb_cells, Vector<Int> * cell, UInt * impactor_nodes_cell_offset, UInt * impactor_nodes_cell, UInt * master_nodes_cell_offset, UInt * master_nodes_cell); /// compute neighbor cells for a given cell and return number of found neighbor cells inline UInt computeNeighborCells(UInt cell, UInt * neighbors, UInt * directional_nb_cells); /// compute global cell number given the directional cell number inline UInt computeCellNb(UInt * directional_nb_cells, Int * directional_cell); /// initializes the neighbor list inline void constructNeighborList(); /// compute minimal grid size and set it void setMinimalGridSpacing(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// set grid spacing inline void setGridSpacing(Real spacing, UInt component); /// get grid spacing inline Real getGridSpacing(UInt component) const; /// set security factor inline void setSecurityFactor(Real factor, UInt component); /// get security factor inline Real getSecurityFactor(UInt component) const; /// set max increment inline void setMaxIncrement(Real increment, UInt component); /// get max increment inline Real getMaxIncrement(UInt component) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// the mesh const Mesh & mesh; /// type of neighbor list to create bool nodes_neighbor_list; /// grid spacing Real grid_spacing[3]; /// maximal displacement since last grid update Real max_increment[3]; /// security factor for grid update test Real security_factor[3]; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "regular_grid_neighbor_structure_inline_impl.cc" /// standard output stream operator /*inline std::ostream & operator <<(std::ostream & stream, const RegularGridNeighborStructure & _this) { _this.printself(stream); return stream; }*/ __END_AKANTU__ #endif /* __AKANTU_REGULAR_GRID_NEIGHBOR_STRUCTURE_HH__ */ diff --git a/model/solid_mechanics/contact/regular_grid_neighbor_structure_inline_impl.cc b/model/solid_mechanics/contact/regular_grid_neighbor_structure_inline_impl.cc index 3f7c5808a..6008ce401 100644 --- a/model/solid_mechanics/contact/regular_grid_neighbor_structure_inline_impl.cc +++ b/model/solid_mechanics/contact/regular_grid_neighbor_structure_inline_impl.cc @@ -1,198 +1,212 @@ /** * @file regular_grid_neighbor_structure_inline_impl.cc * @author David Kammer <david.kammer@epfl.ch> * @date Mon Oct 11 17:39:51 2010 * * @brief Implementation of inline functions of the regular grid * neighbor structure class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> inline void RegularGridNeighborStructure<spatial_dimension>::setGridSpacing(Real spacing, UInt component) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(component < spatial_dimension, "The component " << component << " is out of range (spatial dimension = " << spatial_dimension << ")"); grid_spacing[component] = spacing; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> inline Real RegularGridNeighborStructure<spatial_dimension>::getGridSpacing(UInt component) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(component < spatial_dimension, "The component " << component << " is out of range (spatial dimension = " << spatial_dimension << ")"); AKANTU_DEBUG_OUT(); return grid_spacing[component]; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> inline void RegularGridNeighborStructure<spatial_dimension>::setSecurityFactor(Real factor, UInt component) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(component < spatial_dimension, "The component " << component << " is out of range (spatial dimension = " << spatial_dimension << ")"); security_factor[component] = factor; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> inline Real RegularGridNeighborStructure<spatial_dimension>::getSecurityFactor(UInt component) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(component < spatial_dimension, "The component " << component << " is out of range (spatial dimension = " << spatial_dimension << ")"); AKANTU_DEBUG_OUT(); return security_factor[component]; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> inline void RegularGridNeighborStructure<spatial_dimension>::setMaxIncrement(Real increment, UInt component) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(component < spatial_dimension, "The component " << component << " is out of range (spatial dimension = " << spatial_dimension << ")"); max_increment[component] = increment; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> inline Real RegularGridNeighborStructure<spatial_dimension>::getMaxIncrement(UInt component) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(component < spatial_dimension, "The component " << component << " is out of range (spatial dimension = " << spatial_dimension << ")"); AKANTU_DEBUG_OUT(); return max_increment[component]; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> inline UInt RegularGridNeighborStructure<spatial_dimension>::computeCellNb(UInt * directional_nb_cells, Int * directional_cell) { AKANTU_DEBUG_IN(); UInt cell_number = directional_cell[spatial_dimension - 1]; for(Int dim = spatial_dimension - 2; dim >= 0; --dim) { cell_number *= directional_nb_cells[dim]; cell_number += directional_cell[dim]; } AKANTU_DEBUG_OUT(); return cell_number; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> inline UInt RegularGridNeighborStructure<spatial_dimension>::computeNeighborCells(UInt cell, UInt * neighbors, UInt * directional_nb_cells) { AKANTU_DEBUG_IN(); UInt nb_neighbors = 0; UInt max_spatial_dimension = 3; // to avoid warnings while compiling UInt directional_cell[max_spatial_dimension]; UInt global_cell_nb = cell; /// find the directional cell number for(Int dir = spatial_dimension - 1; dir >= 0; --dir) { UInt factor = 1; for(UInt i = 0; i < dir; ++i) { factor *= directional_nb_cells[i]; } directional_cell[dir] = std::floor(global_cell_nb / factor); // integer division ! global_cell_nb -= directional_cell[dir] * factor; } /// compute neighbor cells UInt neighbor_thickness = 1; // the number of neighbors for a given direction /// computation for 2D if(spatial_dimension == 2) { for(Int x = directional_cell[0] - neighbor_thickness; x <= directional_cell[0] + neighbor_thickness; ++x) { if(x < 0 || x >= directional_nb_cells[0]) continue; // border cell? for(Int y = directional_cell[1] - neighbor_thickness; y <= directional_cell[1] + neighbor_thickness; ++y) { if(y < 0 || y >= directional_nb_cells[1]) continue; // border cell? if(x == directional_cell[0] && y == directional_cell[1]) continue; // do only return neighbors not itself! Int neighbor_directional_cell[2]; neighbor_directional_cell[0] = x; neighbor_directional_cell[1] = y; /// compute global cell index UInt neighbor_cell = computeCellNb(directional_nb_cells, neighbor_directional_cell); /// add the neighbor cell to the list neighbors[nb_neighbors++] = neighbor_cell; } } } /// computation for 3D else if(spatial_dimension == 3) { for(Int x = directional_cell[0] - neighbor_thickness; x <= directional_cell[0] + neighbor_thickness; ++x) { if(x < 0 || x >= directional_nb_cells[0]) continue; // border cell? for(Int y = directional_cell[1] - neighbor_thickness; y <= directional_cell[1] + neighbor_thickness; ++y) { if(y < 0 || y >= directional_nb_cells[1]) continue; // border cell? for(Int z = directional_cell[2] - neighbor_thickness; z <= directional_cell[2] + neighbor_thickness; ++z) { if(z < 0 || z >= directional_nb_cells[2]) continue; // border cell? if(x == directional_cell[0] && y == directional_cell[1] && z == directional_cell[2]) continue; // do only return neighbors not itself! UInt local_spatial_dimension = 3; // to avoid warnings while compiling Int neighbor_directional_cell[local_spatial_dimension]; neighbor_directional_cell[0] = x; neighbor_directional_cell[1] = y; neighbor_directional_cell[2] = z; /// compute global cell index UInt neighbor_cell = computeCellNb(directional_nb_cells, neighbor_directional_cell); /// add the neighbor cell to the list neighbors[nb_neighbors++] = neighbor_cell; } } } } AKANTU_DEBUG_OUT(); return nb_neighbors; } /* -------------------------------------------------------------------------- */ template<UInt spatial_dimension> inline void RegularGridNeighborStructure<spatial_dimension>::constructNeighborList() { AKANTU_DEBUG_IN(); if (contact_search.getType() == _cst_3d_expli) { neighbor_list = new NodesNeighborList(); nodes_neighbor_list = true; } else { neighbor_list = new NeighborList(); nodes_neighbor_list = false; } AKANTU_DEBUG_OUT(); } diff --git a/model/solid_mechanics/contact_neighbor_structure.cc b/model/solid_mechanics/contact_neighbor_structure.cc index 2b27133ff..1174eff41 100644 --- a/model/solid_mechanics/contact_neighbor_structure.cc +++ b/model/solid_mechanics/contact_neighbor_structure.cc @@ -1,77 +1,91 @@ /** * @file contact_neighbor_structure.cc * @author David Kammer <david.kammer@epfl.ch> * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Oct 8 12:42:26 2010 * * @brief * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "contact_neighbor_structure.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ NeighborList::NeighborList() : impactor_nodes(Vector<UInt>(0, 1, "impactors")) { AKANTU_DEBUG_IN(); for (UInt i = 0; i < _max_element_type; ++i) { facets_offset[i] = NULL; facets [i] = NULL; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ NeighborList::~NeighborList() { AKANTU_DEBUG_IN(); for (UInt i = 0; i < _max_element_type; ++i) { if(facets_offset[i]) delete facets_offset[i]; if(facets [i]) delete facets [i]; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactNeighborStructure::ContactNeighborStructure(const ContactSearch & contact_search, const Surface & master_surface, const ContactNeighborStructureType & type, const ContactNeighborStructureID & id) : id(id), contact_search(contact_search), master_surface(master_surface), type(type) { AKANTU_DEBUG_IN(); neighbor_list = NULL; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactNeighborStructure::~ContactNeighborStructure() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool ContactNeighborStructure::check() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ERROR("Check not implemented for this neighbors structure : " << id); AKANTU_DEBUG_OUT(); return false; } __END_AKANTU__ diff --git a/model/solid_mechanics/contact_neighbor_structure.hh b/model/solid_mechanics/contact_neighbor_structure.hh index 8bbde1ab8..07a15b332 100644 --- a/model/solid_mechanics/contact_neighbor_structure.hh +++ b/model/solid_mechanics/contact_neighbor_structure.hh @@ -1,113 +1,127 @@ /** * @file contact_neighbor_structure.hh * @author David Kammer <david.kammer@epfl.ch> * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Oct 8 12:36:15 2010 * * @brief Interface of the structure handling the neighbor lists * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_CONTACT_NEIGHBOR_STRUCTURE_HH__ #define __AKANTU_CONTACT_NEIGHBOR_STRUCTURE_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_vector.hh" #include "mesh.hh" #include "contact_search.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class NeighborList { public: NeighborList(); virtual ~NeighborList(); public: /// number of impactor nodes //UInt nb_nodes; /// list of nodes of slave surfaces near the master one Vector<UInt> impactor_nodes; /// neighbor facets (sparse storage) ByElementTypeUInt facets_offset; ByElementTypeUInt facets; }; /* -------------------------------------------------------------------------- */ class ContactNeighborStructure { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ContactNeighborStructure(const ContactSearch & contact_search, const Surface & master_surface, const ContactNeighborStructureType & type, const ContactNeighborStructureID & id = "contact_neighbor_structure_id"); virtual ~ContactNeighborStructure(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the structure virtual void initNeighborStructure() = 0; /// update the structure virtual void update() = 0; /// check if an update is needed virtual bool check(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the neighbor list AKANTU_GET_MACRO(NeighborList, *neighbor_list, const NeighborList &); AKANTU_GET_MACRO(ID, id, const ContactNeighborStructureID) AKANTU_GET_MACRO(ContactSearch, contact_search, const ContactSearch &); AKANTU_GET_MACRO(MasterSurface, master_surface, const Surface &); AKANTU_GET_MACRO(Type, type, const ContactNeighborStructureType &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the object ContactNeighborStructureID id; /// associated contact search class const ContactSearch & contact_search; /// associated master surface Surface master_surface; /// neighbor list NeighborList * neighbor_list; /// type of contact neighbor structure object ContactNeighborStructureType type; }; __END_AKANTU__ #endif /* __AKANTU_CONTACT_NEIGHBOR_STRUCTURE_HH__ */ diff --git a/model/solid_mechanics/contact_search.cc b/model/solid_mechanics/contact_search.cc index 42653aa7b..3f1898b16 100644 --- a/model/solid_mechanics/contact_search.cc +++ b/model/solid_mechanics/contact_search.cc @@ -1,241 +1,255 @@ /** * @file contact_search.cc * @author David Kammer <kammer@epfl.ch> * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Oct 8 11:46:34 2010 * * @brief * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "contact_search.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "grid_2d_neighbor_structure.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ PenetrationList::PenetrationList() : penetrating_nodes(Vector<UInt>(0, 1, "penetrating_nodes")) { AKANTU_DEBUG_IN(); for (UInt i = 0; i < _max_element_type; ++i) { penetrated_facets_offset[i] = NULL; penetrated_facets [i] = NULL; facets_normals [i] = NULL; gaps [i] = NULL; projected_positions [i] = NULL; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ PenetrationList::~PenetrationList() { AKANTU_DEBUG_IN(); for (UInt i = 0; i < _max_element_type; ++i) { if(penetrated_facets_offset[i]) delete penetrated_facets_offset[i]; if(penetrated_facets [i]) delete penetrated_facets [i]; if(facets_normals [i]) delete facets_normals [i]; if(gaps [i]) delete gaps [i]; if(projected_positions [i]) delete projected_positions [i]; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactSearch::ContactSearch(Contact & contact, const ContactNeighborStructureType & neighbors_structure_type, const ContactSearchType & type, const ContactSearchID & id) : id(id), contact(contact), neighbors_structure_type(neighbors_structure_type), type(type) { AKANTU_DEBUG_IN(); contact.setContactSearch(*this); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactSearch::~ContactSearch() { AKANTU_DEBUG_IN(); std::map<Surface, ContactNeighborStructure *>::iterator it; for (it = neighbors_structure.begin(); it != neighbors_structure.end(); ++it) { delete it->second; } neighbors_structure.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch::initSearch() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch::initNeighborStructure() { AKANTU_DEBUG_IN(); std::map<Surface, ContactNeighborStructure *>::iterator it; for (it = neighbors_structure.begin(); it != neighbors_structure.end(); ++it) { it->second->initNeighborStructure(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch::initNeighborStructure(const Surface & master_surface) { AKANTU_DEBUG_IN(); std::map<Surface, ContactNeighborStructure *>::iterator it; for (it = neighbors_structure.begin(); it != neighbors_structure.end(); ++it) { if(it->first == master_surface) it->second->initNeighborStructure(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch::addMasterSurface(const Surface & master_surface) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(neighbors_structure.find(master_surface) == neighbors_structure.end(), "Master surface already registered in the search object " << id); ContactNeighborStructure * tmp_neighbors_structure = NULL; std::stringstream sstr; sstr << id << ":contact_neighbor_structure:" << neighbors_structure_type << ":" << master_surface; switch(neighbors_structure_type) { case _cnst_regular_grid : { Mesh & mesh = contact.getModel().getFEM().getMesh(); if (mesh.getSpatialDimension() == 2) { tmp_neighbors_structure = new RegularGridNeighborStructure<2>(*this, master_surface, neighbors_structure_type, sstr.str()); } else if(mesh.getSpatialDimension() == 3) { tmp_neighbors_structure = new RegularGridNeighborStructure<3>(*this, master_surface, neighbors_structure_type, sstr.str()); } else AKANTU_DEBUG_ERROR("RegularGridNeighborStructure does not exist for dimension: " << mesh.getSpatialDimension()); break; } case _cnst_2d_grid : { tmp_neighbors_structure = new Grid2dNeighborStructure(*this, master_surface, neighbors_structure_type, sstr.str()); break; } case _cnst_not_defined : // tmp_neighbors_structure = new ContactNeighborStructureGrid2d(this, master_surface, sstr.str()); AKANTU_DEBUG_ERROR("Not a valid neighbors structure type : " << neighbors_structure_type); break; } neighbors_structure[master_surface] = tmp_neighbors_structure; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch::removeMasterSurface(const Surface & master_surface) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(neighbors_structure.find(master_surface) != neighbors_structure.end(), "Master surface not registered in the search object " << id); delete neighbors_structure[master_surface]; neighbors_structure.erase(neighbors_structure.find(master_surface)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch::updateStructure(const Surface & master_surface) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(neighbors_structure.find(master_surface) != neighbors_structure.end(), "Master surface not registered in the search object " << id); neighbors_structure[master_surface]->update(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool ContactSearch::checkIfUpdateStructureNeeded(const Surface & master_surface) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(neighbors_structure.find(master_surface) != neighbors_structure.end(), "Master surface not registered in the search object " << id); bool check = neighbors_structure[master_surface]->check(); AKANTU_DEBUG_OUT(); return check; } /* -------------------------------------------------------------------------- */ const ContactNeighborStructure & ContactSearch::getContactNeighborStructure(const Surface & master_surface) const { AKANTU_DEBUG_IN(); std::map<Surface, ContactNeighborStructure *>::const_iterator it = neighbors_structure.find(master_surface); AKANTU_DEBUG_ASSERT(it != neighbors_structure.end(), "Master surface not registred in contact search."); AKANTU_DEBUG_OUT(); return *(it->second); } /* -------------------------------------------------------------------------- */ void ContactSearch::computeMaxIncrement(Real * max_increment) { AKANTU_DEBUG_IN(); UInt spatial_dimension = contact.getModel().getFEM().getMesh().getSpatialDimension(); UInt nb_surfaces = contact.getModel().getFEM().getMesh().getNbSurfaces(); Real * current_increment = contact.getModel().getIncrement().values; /// initialize max table with zeros for(UInt dim = 0; dim < spatial_dimension; ++dim) max_increment[dim] = 0.0; // get the nodes that are on the surfaces UInt * surface_to_nodes_offset = contact.getSurfaceToNodesOffset().values; UInt * surface_to_nodes = contact.getSurfaceToNodes().values; /// find maximal increment of surface nodes in all directions for(UInt surf = 0; surf < nb_surfaces; ++surf) { UInt min_surf_offset = surface_to_nodes_offset[surf]; UInt max_surf_offset = surface_to_nodes_offset[surf + 1]; for(UInt n = min_surf_offset; n < max_surf_offset; ++n) { UInt cur_node = surface_to_nodes[n]; for(UInt dim = 0; dim < spatial_dimension; ++dim) { Real cur_increment = current_increment[cur_node * spatial_dimension + dim]; max_increment[dim] = std::max(max_increment[dim], fabs(cur_increment)); } } } AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/contact_search.hh b/model/solid_mechanics/contact_search.hh index d8b873ccb..06ecc6e83 100644 --- a/model/solid_mechanics/contact_search.hh +++ b/model/solid_mechanics/contact_search.hh @@ -1,135 +1,149 @@ /** * @file contact_search.hh * @author David Kammer <david.kammer@epfl.ch> * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Oct 8 10:43:54 2010 * * @brief Interface of the search class for contact * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_CONTACT_SEARCH_HH__ #define __AKANTU_CONTACT_SEARCH_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_vector.hh" #include "contact.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class ContactNeighborStructure; } __BEGIN_AKANTU__ class PenetrationList { public: PenetrationList(); virtual ~PenetrationList(); public: /// nodes who have penetrated the master surface Vector<UInt> penetrating_nodes; /// list of penetrated facets ByElementTypeUInt penetrated_facets_offset; ByElementTypeUInt penetrated_facets; /// normal of the penetrated facets ByElementTypeReal facets_normals; /// gap between the penetrated facets and the node ByElementTypeReal gaps; /// position of the node projected on the penetrated facets ByElementTypeReal projected_positions; }; /* -------------------------------------------------------------------------- */ class ContactSearch : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ContactSearch(Contact & contact, const ContactNeighborStructureType & neighbors_structure_type, const ContactSearchType & type, const ContactSearchID & id = "search_contact"); virtual ~ContactSearch(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the needed structures virtual void initSearch(); /// initialize all neighbor structures virtual void initNeighborStructure(); /// initialize one neighbor structure virtual void initNeighborStructure(const Surface & master_surface); /// build the penetration list virtual void findPenetration(const Surface & master_surface, PenetrationList & penetration_list) = 0; /// update the neighbor structure virtual void updateStructure(const Surface & master_surface); /// check if the neighbor structure need an update virtual bool checkIfUpdateStructureNeeded(const Surface & master_surface); /// add a new master surface void addMasterSurface(const Surface & master_surface); /// remove a master surface void removeMasterSurface(const Surface & master_surface); private: /// compute the maximal increment for all surface nodes in each direction void computeMaxIncrement(Real * max_increment); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(ID, id, const ContactSearchID &); AKANTU_GET_MACRO(Contact, contact, const Contact &); AKANTU_GET_MACRO(Type, type, const ContactSearchType &); const ContactNeighborStructure & getContactNeighborStructure(const Surface & master_surface) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the object ContactSearchID id; /// associated contact class const Contact & contact; /// type of the neighbors structure to create const ContactNeighborStructureType & neighbors_structure_type; /// structure used to handle neighbors lists std::map<Surface, ContactNeighborStructure *> neighbors_structure; /// type of contact search object ContactSearchType type; }; __END_AKANTU__ #endif /* __AKANTU_CONTACT_SEARCH_HH__ */ diff --git a/model/solid_mechanics/material.cc b/model/solid_mechanics/material.cc index 70d7ce79d..4453ae10a 100644 --- a/model/solid_mechanics/material.cc +++ b/model/solid_mechanics/material.cc @@ -1,318 +1,332 @@ /** * @file material.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 11:43:41 2010 * * @brief Implementation of the common part of the material class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Material::Material(SolidMechanicsModel & model, const MaterialID & id) : Memory(model.getMemoryID()), id(id), spatial_dimension(model.getSpatialDimension()), name(""), model(&model), potential_energy_vector(false), is_init(false) { AKANTU_DEBUG_IN(); for(UInt t = _not_defined; t < _max_element_type; ++t) { this->stress [t] = NULL; this->strain [t] = NULL; this->potential_energy [t] = NULL; this->element_filter [t] = NULL; this->ghost_stress [t] = NULL; this->ghost_strain [t] = NULL; this->ghost_potential_energy[t] = NULL; this->ghost_element_filter [t] = NULL; } /// for each connectivity types allocate the element filer array of the material initInternalVector(strain, spatial_dimension*spatial_dimension, "strain", _not_ghost); initInternalVector(ghost_strain, spatial_dimension*spatial_dimension, "strain", _ghost); initInternalVector(stress, spatial_dimension*spatial_dimension, "stress", _not_ghost); initInternalVector(ghost_stress, spatial_dimension*spatial_dimension, "stress", _ghost); const Mesh::ConnectivityTypeList & type_list = model.getFEM().getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; std::stringstream sstr; sstr << id << ":element_filer:"<< *it; element_filter[*it] = &(alloc<UInt> (sstr.str(), 0, 1)); // std::stringstream sstr_stre; sstr_stre << id << ":stress:" << *it; // std::stringstream sstr_stra; sstr_stra << id << ":strain:" << *it; // stress[*it] = &(alloc<Real>(sstr_stre.str(), 0, // spatial_dimension * spatial_dimension)); // strain[*it] = &(alloc<Real>(sstr_stra.str(), 0, // spatial_dimension * spatial_dimension)); } const Mesh::ConnectivityTypeList & ghost_type_list = model.getFEM().getMesh().getConnectivityTypeList(_ghost); for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; std::stringstream sstr; sstr << id << ":ghost_element_filer:"<< *it; ghost_element_filter[*it] = &(alloc<UInt> (sstr.str(), 0, 1)); // std::stringstream sstr_stre; sstr_stre << id << ":ghost_stress:" << *it; // std::stringstream sstr_stra; sstr_stra << id << ":ghost_strain:" << *it; // ghost_stress[*it] = &(alloc<Real>(sstr_stre.str(), 0, // spatial_dimension * spatial_dimension)); // ghost_strain[*it] = &(alloc<Real>(sstr_stra.str(), 0, // spatial_dimension * spatial_dimension)); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Material::~Material() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::setParam(const std::string & key, const std::string & value, __attribute__ ((unused)) const MaterialID & id) { if(key == "name") name = std::string(value); else AKANTU_DEBUG_ERROR("Unknown material property : " << key); } /* -------------------------------------------------------------------------- */ void Material::initMaterial() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::initInternalVector(ByElementTypeReal & vect, UInt nb_component, const std::string & vect_id, GhostType ghost_type) { AKANTU_DEBUG_IN(); for(UInt t = _not_defined; t < _max_element_type; ++t) vect[t] = NULL; std::string ghost_id = ""; if (ghost_type == _ghost) { ghost_id = "ghost_"; } const Mesh::ConnectivityTypeList & type_list = model->getFEM().getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; std::stringstream sstr_damage; sstr_damage << id << ":" << ghost_id << vect_id << ":" << *it; vect[*it] = &(alloc<Real>(sstr_damage.str(), 0, nb_component, REAL_INIT_VALUE)); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::resizeInternalVector(ByElementTypeReal & vect, GhostType ghost_type) { AKANTU_DEBUG_IN(); const Mesh::ConnectivityTypeList & type_list = model->getFEM().getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; Vector<UInt> * elem_filter; if (ghost_type == _not_ghost) { elem_filter = element_filter[*it]; } else if (ghost_type == _ghost) { elem_filter = ghost_element_filter[*it]; } UInt nb_element = elem_filter->getSize(); UInt nb_quadrature_points = FEM::getNbQuadraturePoints(*it); UInt new_size = nb_element*nb_quadrature_points; UInt size = vect[*it]->getSize(); UInt nb_component = vect[*it]->getNbComponent(); vect[*it]->resize(new_size); memset(vect[*it]->values + size * nb_component, 0, (new_size - size) * nb_component * sizeof(Real)); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the residual by assembling @f$\int_{e} \sigma_e \frac{\partial * \varphi}{\partial X} dX @f$ * * @param[in] current_position nodes postition + displacements * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ void Material::updateResidual(Vector<Real> & current_position, GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); Vector<Real> & residual = const_cast<Vector<Real> &>(model->getResidual()); const Mesh::ConnectivityTypeList & type_list = model->getFEM().getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); UInt size_of_shapes_derivatives = FEM::getShapeDerivativesSize(*it); UInt nb_quadrature_points = FEM::getNbQuadraturePoints(*it); Vector<Real> * strain_vect; Vector<Real> * stress_vect; Vector<UInt> * elem_filter; const Vector<Real> * shapes_derivatives; if(ghost_type == _not_ghost) { elem_filter = element_filter[*it]; strain_vect = strain[*it]; stress_vect = stress[*it]; shapes_derivatives = &(model->getFEM().getShapesDerivatives(*it)); } else { elem_filter = ghost_element_filter[*it]; strain_vect = ghost_strain[*it]; stress_vect = ghost_stress[*it]; shapes_derivatives = &(model->getFEM().getGhostShapesDerivatives(*it)); } UInt nb_element = elem_filter->getSize(); /// compute @f$\nabla u@f$ model->getFEM().gradientOnQuadraturePoints(current_position, *strain_vect, spatial_dimension, *it, ghost_type, elem_filter); /// compute @f$\mathbf{\sigma}_q@f$ from @f$\nabla u@f$ computeStress(*it, ghost_type); /// compute @f$\sigma \frac{\partial \varphi}{\partial X}@f$ by @f$\mathbf{B}^t \mathbf{\sigma}_q@f$ Vector<Real> * sigma_dphi_dx = new Vector<Real>(nb_element*nb_quadrature_points, size_of_shapes_derivatives, "sigma_x_dphi_/_dX"); Real * shapesd = shapes_derivatives->values; UInt size_of_shapesd = shapes_derivatives->getNbComponent(); Real * shapesd_val; Real * stress_val = stress_vect->values; Real * sigma_dphi_dx_val = sigma_dphi_dx->values; UInt * elem_filter_val = elem_filter->values; UInt offset_shapesd_val = spatial_dimension * nb_nodes_per_element; UInt offset_stress_val = spatial_dimension * spatial_dimension; UInt offset_sigma_dphi_dx_val = spatial_dimension * nb_nodes_per_element; for (UInt el = 0; el < nb_element; ++el) { shapesd_val = shapesd + elem_filter_val[el]*size_of_shapesd*nb_quadrature_points; for (UInt q = 0; q < nb_quadrature_points; ++q) { Math::matrix_matrixt(nb_nodes_per_element, spatial_dimension, spatial_dimension, shapesd_val, stress_val, sigma_dphi_dx_val); shapesd_val += offset_shapesd_val; stress_val += offset_stress_val; sigma_dphi_dx_val += offset_sigma_dphi_dx_val; } } /** * compute @f$\int \sigma * \frac{\partial \varphi}{\partial X}dX@f$ by @f$ \sum_q \mathbf{B}^t * \mathbf{\sigma}_q \overline w_q J_q@f$ */ Vector<Real> * int_sigma_dphi_dx = new Vector<Real>(0, nb_nodes_per_element * spatial_dimension, "int_sigma_x_dphi_/_dX"); model->getFEM().integrate(*sigma_dphi_dx, *int_sigma_dphi_dx, size_of_shapes_derivatives, *it, ghost_type, elem_filter); delete sigma_dphi_dx; /// assemble model->getFEM().assembleVector(*int_sigma_dphi_dx, residual, residual.getNbComponent(), *it, ghost_type, elem_filter, -1); delete int_sigma_dphi_dx; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::computePotentialEnergyByElement() { AKANTU_DEBUG_IN(); const Mesh::ConnectivityTypeList & type_list = model->getFEM().getMesh().getConnectivityTypeList(_not_ghost); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(model->getFEM().getMesh().getSpatialDimension(*it) != spatial_dimension) continue; if(potential_energy[*it] == NULL) { UInt nb_element = element_filter[*it]->getSize(); UInt nb_quadrature_points = FEM::getNbQuadraturePoints(*it); std::stringstream sstr; sstr << id << ":potential_energy:"<< *it; potential_energy[*it] = &(alloc<Real> (sstr.str(), nb_element * nb_quadrature_points, 1, REAL_INIT_VALUE)); } computePotentialEnergy(*it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real Material::getPotentialEnergy() { AKANTU_DEBUG_IN(); Real epot = 0.; computePotentialEnergyByElement(); /// integrate the potential energy for each type of elements const Mesh::ConnectivityTypeList & type_list = model->getFEM().getMesh().getConnectivityTypeList(_not_ghost); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(model->getFEM().getMesh().getSpatialDimension(*it) != spatial_dimension) continue; epot += model->getFEM().integrate(*potential_energy[*it], *it, _not_ghost, element_filter[*it]); } AKANTU_DEBUG_OUT(); return epot; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/model/solid_mechanics/material.hh b/model/solid_mechanics/material.hh index f19507d81..60e939a00 100644 --- a/model/solid_mechanics/material.hh +++ b/model/solid_mechanics/material.hh @@ -1,233 +1,247 @@ /** * @file material.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Jul 23 09:06:29 2010 * * @brief Mother class for all materials * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_HH__ #define __AKANTU_MATERIAL_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "fem.hh" #include "mesh.hh" //#include "solid_mechanics_model.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class SolidMechanicsModel; } __BEGIN_AKANTU__ class Material : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Material(SolidMechanicsModel & model, const MaterialID & id = ""); virtual ~Material(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// read properties virtual void setParam(const std::string & key, const std::string & value, const MaterialID & id); /// initialize the material computed parameter virtual void initMaterial(); /// compute the residual for this material void updateResidual(Vector<Real> & current_position, GhostType ghost_type = _not_ghost); /// constitutive law virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost) = 0; /// compute the potential energy by element void computePotentialEnergyByElement(); /// compute the potential energy virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost) = 0; /// compute the stable time step for an element of size h virtual Real getStableTimeStep(Real h) = 0; /// add an element to the local mesh filter inline void addElement(ElementType type, UInt element); /// add an element to the local mesh filter for ghost element inline void addGhostElement(ElementType type, UInt element); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const = 0; /* ------------------------------------------------------------------------ */ /* Function for all materials */ /* ------------------------------------------------------------------------ */ protected: /// allocate an internal vector void initInternalVector(ByElementTypeReal & vect, UInt nb_component, const std::string & id, GhostType ghost_type = _not_ghost); /// resize an internal vector void resizeInternalVector(ByElementTypeReal & vect, GhostType ghost_type = _not_ghost); /* ------------------------------------------------------------------------ */ /* Ghost Synchronizer inherited members */ /* ------------------------------------------------------------------------ */ public: inline virtual UInt getNbDataToPack(const Element & element, GhostSynchronizationTag tag); inline virtual UInt getNbDataToUnpack(const Element & element, GhostSynchronizationTag tag); inline virtual void packData(Real ** buffer, const Element & element, GhostSynchronizationTag tag); inline virtual void unpackData(Real ** buffer, const Element & element, GhostSynchronizationTag tag); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(ID, id, const MaterialID &); AKANTU_GET_MACRO(Rho, rho, Real); Real getPotentialEnergy(); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Strain, strain, const Vector<Real> &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Stress, stress, const Vector<Real> &); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(PotentialEnergy, potential_energy, const Vector<Real> &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the material MaterialID id; /// spatial dimension UInt spatial_dimension; /// material name std::string name; /// The model to witch the material belong SolidMechanicsModel * model; /// density : rho Real rho; /// stresses arrays ordered by element types ByElementTypeReal stress; /// strains arrays ordered by element types ByElementTypeReal strain; /// list of element handled by the material ByElementTypeUInt element_filter; /// stresses arrays ordered by element types ByElementTypeReal ghost_stress; /// strains arrays ordered by element types ByElementTypeReal ghost_strain; /// list of element handled by the material ByElementTypeUInt ghost_element_filter; /// is the vector for potential energy initialized bool potential_energy_vector; /// potential energy by element ByElementTypeReal potential_energy; /// potential energy by element ByElementTypeReal ghost_potential_energy; /// boolean to know if the material has been initialized bool is_init; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_inline_impl.cc" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Material & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #include "materials/material_elastic.hh" /* -------------------------------------------------------------------------- */ /* Auto loop */ /* -------------------------------------------------------------------------- */ #define MATERIAL_QUADRATURE_POINT_LOOP_BEGIN \ UInt nb_quadrature_points = FEM::getNbQuadraturePoints(el_type); \ UInt size_strain = spatial_dimension * spatial_dimension; \ \ UInt nb_element; \ Real * strain_val; \ Real * stress_val; \ \ if(ghost_type == _not_ghost) { \ nb_element = element_filter[el_type]->getSize(); \ stress[el_type]->resize(nb_element*nb_quadrature_points); \ strain_val = strain[el_type]->values; \ stress_val = stress[el_type]->values; \ } else { \ nb_element = ghost_element_filter[el_type]->getSize(); \ ghost_stress[el_type]->resize(nb_element*nb_quadrature_points); \ strain_val = ghost_strain[el_type]->values; \ stress_val = ghost_stress[el_type]->values; \ } \ \ if (nb_element == 0) return; \ \ for (UInt el = 0; el < nb_element; ++el) { \ for (UInt q = 0; q < nb_quadrature_points; ++q) { \ #define MATERIAL_QUADRATURE_POINT_LOOP_END \ strain_val += size_strain; \ stress_val += size_strain; \ } \ } \ #endif /* __AKANTU_MATERIAL_HH__ */ diff --git a/model/solid_mechanics/material_inline_impl.cc b/model/solid_mechanics/material_inline_impl.cc index 01509e838..072c9e3e0 100644 --- a/model/solid_mechanics/material_inline_impl.cc +++ b/model/solid_mechanics/material_inline_impl.cc @@ -1,74 +1,88 @@ /** * @file material_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 11:57:43 2010 * * @brief Implementation of the inline functions of the class material * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ inline void Material::addElement(ElementType type, UInt element) { element_filter[type]->push_back(element); UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); for (UInt i = 0; i < nb_quadrature_points; ++i) { strain[type]->push_back(REAL_INIT_VALUE); stress[type]->push_back(REAL_INIT_VALUE); if(potential_energy[type] != NULL) { potential_energy[type]->push_back(REAL_INIT_VALUE); } } } /* -------------------------------------------------------------------------- */ inline void Material::addGhostElement(ElementType type, UInt element) { ghost_element_filter[type]->push_back(element); UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); for (UInt i = 0; i < nb_quadrature_points; ++i) { ghost_strain[type]->push_back(REAL_INIT_VALUE); ghost_stress[type]->push_back(REAL_INIT_VALUE); } // if(potential_energy_vector) // ghost_potential_energy[type]->push_back(REAL_INIT_VALUE); } /* -------------------------------------------------------------------------- */ inline UInt Material::getNbDataToPack(__attribute__ ((unused)) const Element & element, __attribute__ ((unused)) GhostSynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); return 0; } /* -------------------------------------------------------------------------- */ inline UInt Material::getNbDataToUnpack(__attribute__ ((unused)) const Element & element, __attribute__ ((unused)) GhostSynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); return 0; } /* -------------------------------------------------------------------------- */ inline void Material::packData(__attribute__ ((unused)) Real ** buffer, __attribute__ ((unused)) const Element & element, __attribute__ ((unused)) GhostSynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void Material::unpackData(__attribute__ ((unused)) Real ** buffer, __attribute__ ((unused)) const Element & element, __attribute__ ((unused)) GhostSynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } diff --git a/model/solid_mechanics/material_parser.hh b/model/solid_mechanics/material_parser.hh index cebc907ff..ed867b1a8 100644 --- a/model/solid_mechanics/material_parser.hh +++ b/model/solid_mechanics/material_parser.hh @@ -1,71 +1,85 @@ /** * @file material_parser.hh * @author Guillaume ANCIAUX <anciaux@lsmscluster1.epfl.ch> * @date Thu Nov 25 11:43:48 2010 * * @brief * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_PARSER_HH__ #define __AKANTU_MATERIAL_PARSER_HH__ __BEGIN_AKANTU__ class MaterialParser { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialParser() : current_line(0) {}; virtual ~MaterialParser(){ infile.close(); }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// open a file to parse void open(const std::string & filename); /// read the file and return the next material type std::string getNextMaterialType(); /// read properties and instanciate a given material object template <typename Mat> Material * readMaterialObject(SolidMechanicsModel & model, MaterialID & mat_id); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: inline void my_getline(); /// number of the current line UInt current_line; /// material file std::ifstream infile; /// current read line std::string line; }; #include "material_parser_inline_impl.cc" __END_AKANTU__ #endif diff --git a/model/solid_mechanics/material_parser_inline_impl.cc b/model/solid_mechanics/material_parser_inline_impl.cc index 5eed96361..3b1e2e2f9 100644 --- a/model/solid_mechanics/material_parser_inline_impl.cc +++ b/model/solid_mechanics/material_parser_inline_impl.cc @@ -1,93 +1,107 @@ /** * @file material_parser_inline_impl.cc * @author Guillaume ANCIAUX <guillaume.anciaux@epfl.ch> * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Nov 26 08:32:38 2010 * * @brief * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ template <typename Mat> inline Material * MaterialParser::readMaterialObject(SolidMechanicsModel & model,MaterialID & mat_id){ std::string keyword; std::string value; /// instanciate the material object Material * mat = new Mat(model, mat_id); /// read the material properties my_getline(); while(line[0] != ']') { size_t pos = line.find("="); if(pos == std::string::npos) AKANTU_DEBUG_ERROR("Malformed material file : line must be \"key = value\" at line" << current_line); keyword = line.substr(0, pos); trim(keyword); value = line.substr(pos + 1); trim(value); try { mat->setParam(keyword, value, mat_id); } catch (debug::Exception ex) { AKANTU_DEBUG_ERROR("Malformed material file : error in setParam \"" << ex.info() << "\" at line " << current_line); } my_getline(); } return mat; } /* -------------------------------------------------------------------------- */ inline std::string MaterialParser::getNextMaterialType(){ while(infile.good()) { my_getline(); // if empty line continue if(line.empty()) continue; std::stringstream sstr(line); std::string keyword; std::string value; sstr >> keyword; to_lower(keyword); /// if found a material deccription then stop /// and prepare the things for further reading if(keyword == "material") { std::string type; sstr >> type; to_lower(type); std::string obracket; sstr >> obracket; if(obracket != "[") AKANTU_DEBUG_ERROR("Malformed material file : missing [ at line " << current_line); return type; } } return ""; } /* -------------------------------------------------------------------------- */ inline void MaterialParser::my_getline() { std::getline(infile, line); //read the line if (!(infile.flags() & (std::ios::failbit | std::ios::eofbit))) ++current_line; size_t pos = line.find("#"); //remove the comment line = line.substr(0, pos); trim(line); // remove unnecessary spaces } /* -------------------------------------------------------------------------- */ inline void MaterialParser::open(const std::string & filename){ infile.open(filename.c_str()); current_line = 0; if(!infile.good()) { AKANTU_DEBUG_ERROR("Cannot open file " << filename); } } diff --git a/model/solid_mechanics/materials/material_elastic.cc b/model/solid_mechanics/materials/material_elastic.cc index 2d95f1fa6..b3c46c325 100644 --- a/model/solid_mechanics/materials/material_elastic.cc +++ b/model/solid_mechanics/materials/material_elastic.cc @@ -1,121 +1,135 @@ /** * @file material_elastic.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 11:53:52 2010 * * @brief Specialization of the material class for the elastic material * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_elastic.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MaterialElastic::MaterialElastic(SolidMechanicsModel & model, const MaterialID & id) : Material(model, id) { AKANTU_DEBUG_IN(); rho = 0; E = 0; nu = 1./2.; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialElastic::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); lambda = nu * E / ((1 + nu) * (1 - 2*nu)); mu = E / (2 * (1 + nu)); kpa = lambda + 2./3. * mu; is_init = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialElastic::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real F[3*3]; Real sigma[3*3]; MATERIAL_QUADRATURE_POINT_LOOP_BEGIN; memset(F, 0, 3 * 3 * sizeof(Real)); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) F[3*i + j] = strain_val[spatial_dimension * i + j]; for (UInt i = 0; i < spatial_dimension; ++i) F[i*3 + i] -= 1; computeStress(F, sigma); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) stress_val[spatial_dimension*i + j] = sigma[3 * i + j]; MATERIAL_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialElastic::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if(ghost_type != _not_ghost) return; Real * epot = potential_energy[el_type]->values; MATERIAL_QUADRATURE_POINT_LOOP_BEGIN; computePotentialEnergy(strain_val, stress_val, epot); epot++; MATERIAL_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialElastic::setParam(const std::string & key, const std::string & value, const MaterialID & id) { std::stringstream sstr(value); if(key == "rho") { sstr >> rho; } else if(key == "E") { sstr >> E; } else if(key == "nu") { sstr >> nu; } else { Material::setParam(key, value, id); } } /* -------------------------------------------------------------------------- */ void MaterialElastic::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Material<_elastic> [" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + name : " << name << std::endl; stream << space << " + density : " << rho << std::endl; stream << space << " + Young's modulus : " << E << std::endl; stream << space << " + Poisson's ratio : " << nu << std::endl; if(is_init) { stream << space << " + First Lamé coefficient : " << lambda << std::endl; stream << space << " + Second Lamé coefficient : " << mu << std::endl; stream << space << " + Bulk coefficient : " << kpa << std::endl; } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/model/solid_mechanics/materials/material_elastic.hh b/model/solid_mechanics/materials/material_elastic.hh index a81a13d04..b07721e4a 100644 --- a/model/solid_mechanics/materials/material_elastic.hh +++ b/model/solid_mechanics/materials/material_elastic.hh @@ -1,107 +1,121 @@ /** * @file material_elastic.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jul 29 15:00:59 2010 * * @brief Material isotropic elastic * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_ELASTIC_HH__ #define __AKANTU_MATERIAL_ELASTIC_HH__ __BEGIN_AKANTU__ class MaterialElastic : public Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialElastic(SolidMechanicsModel & model, const MaterialID & id = ""); virtual ~MaterialElastic() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); void setParam(const std::string & key, const std::string & value, const MaterialID & id); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// constitutive law for a given quadrature point inline void computeStress(Real * F, Real * sigma); /// compute the potential energy for all elements void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the potential energy for on element inline void computePotentialEnergy(Real * F, Real * sigma, Real * epot); /// compute the celerity of wave in the material inline Real celerity(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the stable time step inline Real getStableTimeStep(Real h); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// the young modulus Real E; /// Poisson coefficient Real nu; /// First Lamé coefficient Real lambda; /// Second Lamé coefficient (shear modulus) Real mu; /// Bulk modulus Real kpa; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_elastic_inline_impl.cc" /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const MaterialElastic & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_MATERIAL_ELASTIC_HH__ */ diff --git a/model/solid_mechanics/materials/material_elastic_inline_impl.cc b/model/solid_mechanics/materials/material_elastic_inline_impl.cc index 381152500..fc7058f6b 100644 --- a/model/solid_mechanics/materials/material_elastic_inline_impl.cc +++ b/model/solid_mechanics/materials/material_elastic_inline_impl.cc @@ -1,49 +1,63 @@ /** * @file material_elastic_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 11:57:43 2010 * * @brief Implementation of the inline functions of the material elastic * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ inline void MaterialElastic::computeStress(Real * F, Real * sigma) { Real trace = F[0] + F[4] + F[8]; /// \F_{11} + \F_{22} + \F_{33} /// \sigma_{ij} = \lamda * \F_{kk} * \delta_{ij} + 2 * \mu * \F_{ij} sigma[0] = lambda * trace + 2*mu*F[0]; sigma[4] = lambda * trace + 2*mu*F[4]; sigma[8] = lambda * trace + 2*mu*F[8]; sigma[1] = sigma[3] = mu * (F[1] + F[3]); sigma[2] = sigma[6] = mu * (F[2] + F[6]); sigma[5] = sigma[7] = mu * (F[5] + F[7]); } /* -------------------------------------------------------------------------- */ inline void MaterialElastic::computePotentialEnergy(Real * F, Real * sigma, Real * epot) { *epot = 0.; for (UInt i = 0, t = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j, ++t) (*epot) += sigma[t] * (F[t] - (i == j)); *epot *= .5; } /* -------------------------------------------------------------------------- */ inline Real MaterialElastic::celerity() { return sqrt(E/rho); } /* -------------------------------------------------------------------------- */ inline Real MaterialElastic::getStableTimeStep(Real h) { return (h/celerity()); } diff --git a/model/solid_mechanics/solid_mechanics_model.cc b/model/solid_mechanics/solid_mechanics_model.cc index 96a891fdf..93bf6909a 100644 --- a/model/solid_mechanics/solid_mechanics_model.cc +++ b/model/solid_mechanics/solid_mechanics_model.cc @@ -1,466 +1,480 @@ /** * @file solid_mechanics_model.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jul 22 14:35:38 2010 * * @brief Implementation of the SolidMechanicsModel class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "aka_math.hh" #include "integration_scheme_2nd_order.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ SolidMechanicsModel::SolidMechanicsModel(Mesh & mesh, UInt spatial_dimension, const ModelID & id, const MemoryID & memory_id) : Model(mesh, spatial_dimension, id, memory_id), time_step(NAN), f_m2a(1.0), integrator(new CentralDifference()), increment_flag(false) { AKANTU_DEBUG_IN(); this->displacement = NULL; this->mass = NULL; this->velocity = NULL; this->acceleration = NULL; this->force = NULL; this->residual = NULL; this->boundary = NULL; this->increment = NULL; for(UInt t = _not_defined; t < _max_element_type; ++t) { this->element_material[t] = NULL; this->ghost_element_material[t] = NULL; } registerTag(_gst_smm_mass, "Mass"); registerTag(_gst_smm_residual, "Explicit Residual"); registerTag(_gst_smm_boundary, "Boundary conditions"); materials.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolidMechanicsModel::~SolidMechanicsModel() { AKANTU_DEBUG_IN(); std::vector<Material *>::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { delete *mat_it; } materials.clear(); delete integrator; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initVectors() { AKANTU_DEBUG_IN(); UInt nb_nodes = fem->getMesh().getNbNodes(); std::stringstream sstr_disp; sstr_disp << id << ":displacement"; std::stringstream sstr_mass; sstr_mass << id << ":mass"; std::stringstream sstr_velo; sstr_velo << id << ":velocity"; std::stringstream sstr_acce; sstr_acce << id << ":acceleration"; std::stringstream sstr_forc; sstr_forc << id << ":force"; std::stringstream sstr_resi; sstr_resi << id << ":residual"; std::stringstream sstr_boun; sstr_boun << id << ":boundary"; displacement = &(alloc<Real>(sstr_disp.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); mass = &(alloc<Real>(sstr_mass.str(), nb_nodes, 1)); // \todo see if it must not be spatial_dimension velocity = &(alloc<Real>(sstr_velo.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); acceleration = &(alloc<Real>(sstr_acce.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); force = &(alloc<Real>(sstr_forc.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); residual = &(alloc<Real>(sstr_resi.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); boundary = &(alloc<bool>(sstr_boun.str(), nb_nodes, spatial_dimension, false)); std::stringstream sstr_curp; sstr_curp << id << ":current_position_tmp"; current_position = &(alloc<Real>(sstr_curp.str(), 0, spatial_dimension, REAL_INIT_VALUE)); const Mesh::ConnectivityTypeList & type_list = fem->getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { UInt nb_element = fem->getMesh().getNbElement(*it); if(!element_material[*it]) { std::stringstream sstr_elma; sstr_elma << id << ":element_material:" << *it; element_material[*it] = &(alloc<UInt>(sstr_elma.str(), nb_element, 1, 0)); } } const Mesh::ConnectivityTypeList & ghost_type_list = fem->getMesh().getConnectivityTypeList(_ghost); for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { UInt nb_element = fem->getMesh().getNbGhostElement(*it); std::stringstream sstr_elma; sstr_elma << id << ":ghost_element_material:" << *it; ghost_element_material[*it] = &(alloc<UInt>(sstr_elma.str(), nb_element, 1, 0)); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initModel() { fem->initShapeFunctions(_not_ghost); fem->initShapeFunctions(_ghost); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateCurrentPosition() { AKANTU_DEBUG_IN(); UInt nb_nodes = fem->getMesh().getNbNodes(); current_position->resize(nb_nodes); //Vector<Real> * current_position = new Vector<Real>(nb_nodes, spatial_dimension, NAN, "position"); Real * current_position_val = current_position->values; Real * position_val = fem->getMesh().getNodes().values; Real * displacement_val = displacement->values; /// compute current_position = initial_position + displacement memcpy(current_position_val, position_val, nb_nodes*spatial_dimension*sizeof(Real)); for (UInt n = 0; n < nb_nodes*spatial_dimension; ++n) { *current_position_val++ += *displacement_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initializeUpdateResidualData() { AKANTU_DEBUG_IN(); UInt nb_nodes = fem->getMesh().getNbNodes(); residual->resize(nb_nodes); /// copy the forces in residual for boundary conditions memcpy(residual->values, force->values, nb_nodes*spatial_dimension*sizeof(Real)); updateCurrentPosition(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateResidual(bool need_initialize) { AKANTU_DEBUG_IN(); if (need_initialize) initializeUpdateResidualData(); /// start synchronization asynchronousSynchronize(_gst_smm_residual); /// call update residual on each local elements std::vector<Material *>::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->updateResidual(*current_position, _not_ghost); } /// finalize communications waitEndSynchronize(_gst_smm_residual); /// call update residual on each ghost elements for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->updateResidual(*current_position, _ghost); } // current_position; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateAcceleration() { AKANTU_DEBUG_IN(); UInt nb_nodes = acceleration->getSize(); UInt nb_degre_of_freedom = acceleration->getNbComponent(); Real * mass_val = mass->values; Real * residual_val = residual->values; Real * accel_val = acceleration->values; bool * boundary_val = boundary->values; for (UInt n = 0; n < nb_nodes; ++n) { for (UInt d = 0; d < nb_degre_of_freedom; d++) { if(!(*boundary_val)) { *accel_val = f_m2a * *residual_val / *mass_val; } residual_val++; accel_val++; boundary_val++; } mass_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::explicitPred() { AKANTU_DEBUG_IN(); if(increment_flag) { memcpy(increment->values, displacement->values, displacement->getSize()*displacement->getNbComponent()*sizeof(Real)); } integrator->integrationSchemePred(time_step, *displacement, *velocity, *acceleration, *boundary); if(increment_flag) { Real * inc_val = increment->values; Real * dis_val = displacement->values; UInt nb_nodes = displacement->getSize(); for (UInt n = 0; n < nb_nodes; ++n) { *inc_val = *dis_val - *inc_val; *inc_val++; *dis_val++; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::explicitCorr() { AKANTU_DEBUG_IN(); integrator->integrationSchemeCorr(time_step, *displacement, *velocity, *acceleration, *boundary); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::synchronizeBoundaries() { AKANTU_DEBUG_IN(); synchronize(_gst_smm_boundary); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::setIncrementFlagOn() { AKANTU_DEBUG_IN(); if(!increment) { UInt nb_nodes = fem->getMesh().getNbNodes(); std::stringstream sstr_inc; sstr_inc << id << ":increment"; increment = &(alloc<Real>(sstr_inc.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); } increment_flag = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getStableTimeStep() { AKANTU_DEBUG_IN(); Material ** mat_val = &(materials.at(0)); Real min_dt = std::numeric_limits<Real>::max(); Real * coord = fem->getMesh().getNodes().values; Real * disp_val = displacement->values; const Mesh::ConnectivityTypeList & type_list = fem->getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(fem->getMesh().getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_nodes_per_element = fem->getMesh().getNbNodesPerElement(*it); UInt nb_element = fem->getMesh().getNbElement(*it); UInt * conn = fem->getMesh().getConnectivity(*it).values; UInt * elem_mat_val = element_material[*it]->values; Real * u = new Real[nb_nodes_per_element*spatial_dimension]; for (UInt el = 0; el < nb_element; ++el) { UInt el_offset = el * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n] * spatial_dimension; memcpy(u + n * spatial_dimension, coord + offset_conn, spatial_dimension * sizeof(Real)); for (UInt i = 0; i < spatial_dimension; ++i) { u[n * spatial_dimension + i] += disp_val[offset_conn + i]; } } Real el_size = fem->getElementInradius(u, *it); Real el_dt = mat_val[elem_mat_val[el]]->getStableTimeStep(el_size); min_dt = min_dt > el_dt ? el_dt : min_dt; } delete [] u; } /// reduction min over all processors allReduce(&min_dt, _so_min); AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getPotentialEnergy() { AKANTU_DEBUG_IN(); Real epot = 0.; /// call update residual on each local elements std::vector<Material *>::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { epot += (*mat_it)->getPotentialEnergy(); } /// reduction sum over all processors allReduce(&epot, _so_sum); AKANTU_DEBUG_OUT(); return epot; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy() { AKANTU_DEBUG_IN(); Real ekin = 0.; UInt nb_nodes = fem->getMesh().getNbNodes(); // Vector<Real> * v_square = new Vector<Real>(nb_nodes, 1, "v_square"); Real * vel_val = velocity->values; Real * mass_val = mass->values; for (UInt n = 0; n < nb_nodes; ++n) { Real v2 = 0; for (UInt i = 0; i < spatial_dimension; ++i) { v2 += *vel_val * *vel_val; vel_val++; } ekin += *mass_val * v2; mass_val++; } // Real * v_s_val = v_square->values; // for (UInt n = 0; n < nb_nodes; ++n) { // *v_s_val = 0; // for (UInt s = 0; s < spatial_dimension; ++s) { // *v_s_val += *vel_val * *vel_val; // vel_val++; // } // v_s_val++; // } // Material ** mat_val = &(materials.at(0)); // const Mesh:: ConnectivityTypeList & type_list = fem->getMesh().getConnectivityTypeList(); // Mesh::ConnectivityTypeList::const_iterator it; // for(it = type_list.begin(); it != type_list.end(); ++it) { // if(fem->getMesh().getSpatialDimension(*it) != spatial_dimension) continue; // UInt nb_quadrature_points = FEM::getNbQuadraturePoints(*it); // UInt nb_element = fem->getMesh().getNbElement(*it); // Vector<Real> * v_square_el = new Vector<Real>(nb_element * nb_quadrature_points, 1, "v_square per element"); // fem->interpolateOnQuadraturePoints(*v_square, *v_square_el, 1, *it); // Real * v_square_el_val = v_square_el->values; // UInt * elem_mat_val = element_material[*it]->values; // for (UInt el = 0; el < nb_element; ++el) { // Real rho = mat_val[elem_mat_val[el]]->getRho(); // for (UInt q = 0; q < nb_quadrature_points; ++q) { // *v_square_el_val *= rho; // v_square_el_val++; // } // } // ekin += fem->integrate(*v_square_el, *it); // delete v_square_el; // } // delete v_square; /// reduction sum over all processors allReduce(&ekin, _so_sum); AKANTU_DEBUG_OUT(); return ekin * .5; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Solid Mechanics Model [" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + spatial dimension : " << spatial_dimension << std::endl; stream << space << " + fem [" << std::endl; fem->printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + nodals information [" << std::endl; displacement->printself(stream, indent + 2); mass ->printself(stream, indent + 2); velocity ->printself(stream, indent + 2); acceleration->printself(stream, indent + 2); force ->printself(stream, indent + 2); residual ->printself(stream, indent + 2); boundary ->printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + connectivity type information [" << std::endl; const Mesh::ConnectivityTypeList & type_list = fem->getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { stream << space << AKANTU_INDENT << AKANTU_INDENT << " + " << *it <<" [" << std::endl; element_material[*it]->printself(stream, indent + 3); stream << space << AKANTU_INDENT << AKANTU_INDENT << "]" << std::endl; } stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/model/solid_mechanics/solid_mechanics_model.hh b/model/solid_mechanics/solid_mechanics_model.hh index 1c2ea94f7..f6fd60f97 100644 --- a/model/solid_mechanics/solid_mechanics_model.hh +++ b/model/solid_mechanics/solid_mechanics_model.hh @@ -1,264 +1,278 @@ /** * @file solid_mechanics_model.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date[creation] Thu Jul 22 11:51:06 2010 * @date[last modification] Thu Oct 14 14:00:06 2010 * * @brief Model of Solid Mechanics * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLID_MECHANICS_MODEL_HH__ #define __AKANTU_SOLID_MECHANICS_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "model.hh" #include "material.hh" #include "material_parser.hh" /* -------------------------------------------------------------------------- */ namespace akantu { // class Material; class IntegrationScheme2ndOrder; class Contact; } __BEGIN_AKANTU__ class SolidMechanicsModel : public Model { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SolidMechanicsModel(UInt spatial_dimension, const ModelID & id = "solid_mechanics_model", const MemoryID & memory_id = 0); SolidMechanicsModel(Mesh & mesh, UInt spatial_dimension = 0, const ModelID & id = "solid_mechanics_model", const MemoryID & memory_id = 0); virtual ~SolidMechanicsModel(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// allocate all vectors void initVectors(); /// read the material files to instantiate all the materials void readMaterials(const std::string & filename); /// read a custom material with a keyword and class as template template <typename M> UInt readCustomMaterial(const std::string & filename, const std::string & keyword); /// read properties part of a material file and create the material template <typename M> Material * readMaterialProperties(std::ifstream & infile, MaterialID mat_id, UInt ¤t_line); /// initialize all internal arrays for materials void initMaterials(); /// initialize the model void initModel(); /// assemble the lumped mass matrix void assembleMassLumped(); /// initialize the array needed by updateResidual (residual, current_position) void initializeUpdateResidualData(); /// update the current position vector void updateCurrentPosition(); /// assemble the residual for the explicit scheme void updateResidual(bool need_initialize = true); /// compute the acceleration from the residual void updateAcceleration(); /// explicit integration predictor void explicitPred(); /// explicit integration corrector void explicitCorr(); /// synchronize the ghost element boundaries values void synchronizeBoundaries(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /// integrate a force on the boundary by providing a stress tensor void computeForcesByStressTensor(const Vector<Real> & stresses, const ElementType & type); /// integrate a force on the boundary by providing a traction vector void computeForcesByTractionVector(const Vector<Real> & tractions, const ElementType & type); /// compute force vector from a function(x,y,z) that describe stresses void computeForcesFromFunction(void (*myf)(double *,double *), BoundaryFunctionType function_type); private: /// assemble the lumped mass matrix for local and ghost elements void assembleMassLumped(GhostType ghost_type); /// assemble the lumped mass matrix for local and ghost elements void assembleMassLumpedRowSum(GhostType ghost_type, const ElementType type); /// assemble the lumped mass matrix for local and ghost elements void assembleMassLumpedDiagonalScaling(GhostType ghost_type, const ElementType type); /* ------------------------------------------------------------------------ */ /* Ghost Synchronizer inherited members */ /* ------------------------------------------------------------------------ */ public: inline virtual UInt getNbDataToPack(const Element & element, GhostSynchronizationTag tag) const; inline virtual UInt getNbDataToUnpack(const Element & element, GhostSynchronizationTag tag) const; inline virtual void packData(Real ** buffer, const Element & element, GhostSynchronizationTag tag) const; inline virtual void unpackData(Real ** buffer, const Element & element, GhostSynchronizationTag tag) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(TimeStep, time_step, Real); AKANTU_SET_MACRO(TimeStep, time_step, Real); AKANTU_GET_MACRO(F_M2A, f_m2a, Real); AKANTU_SET_MACRO(F_M2A, f_m2a, Real); AKANTU_GET_MACRO(Displacement, *displacement, Vector<Real> &); AKANTU_GET_MACRO(CurrentPosition, *current_position, const Vector<Real> &); AKANTU_GET_MACRO(Increment, *increment, const Vector<Real> &); AKANTU_GET_MACRO(Mass, *mass, const Vector<Real> &); AKANTU_GET_MACRO(Velocity, *velocity, Vector<Real> &); AKANTU_GET_MACRO(Acceleration, *acceleration, Vector<Real> &); AKANTU_GET_MACRO(Force, *force, Vector<Real> &); AKANTU_GET_MACRO(Residual, *residual, const Vector<Real> &); AKANTU_GET_MACRO(Boundary, *boundary, Vector<bool> &); AKANTU_GET_MACRO(IncrementFlag, increment_flag, bool); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementMaterial, element_material, Vector<UInt> &); inline Material & getMaterial(UInt mat_index); /// compute the stable time step Real getStableTimeStep(); // void setPotentialEnergyFlagOn(); // void setPotentialEnergyFlagOff(); Real getPotentialEnergy(); Real getKineticEnergy(); AKANTU_SET_MACRO(Contact, contact, Contact *); void setIncrementFlagOn(); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// time step Real time_step; /// conversion coefficient form force/mass to acceleration Real f_m2a; /// displacements array Vector<Real> * displacement; /// lumped mass array Vector<Real> * mass; /// velocities array Vector<Real> * velocity; /// accelerations array Vector<Real> * acceleration; /// forces array Vector<Real> * force; /// residuals array Vector<Real> * residual; /// boundaries array Vector<bool> * boundary; /// array of current position used during update residual Vector<Real> * current_position; /// materials of all elements ByElementTypeUInt element_material; /// materials of all ghost elements ByElementTypeUInt ghost_element_material; /// list of used materials std::vector<Material *> materials; /// integration scheme of second order used IntegrationScheme2ndOrder * integrator; /// increment of displacement Vector<Real> * increment; /// flag defining if the increment must be computed or not bool increment_flag; /// object to resolve the contact Contact * contact; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_inline_impl.cc" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const SolidMechanicsModel & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_SOLID_MECHANICS_MODEL_HH__ */ diff --git a/model/solid_mechanics/solid_mechanics_model_boundary.cc b/model/solid_mechanics/solid_mechanics_model_boundary.cc index 3afa70015..3030a4b5a 100644 --- a/model/solid_mechanics/solid_mechanics_model_boundary.cc +++ b/model/solid_mechanics/solid_mechanics_model_boundary.cc @@ -1,179 +1,193 @@ /** * @file solid_mechanics_model_boundary.cc * @author Guillaume ANCIAUX <anciaux@lsmscluster1.epfl.ch> * @date Fri Nov 19 10:23:03 2010 * * @brief * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /** * @param myf pointer to a function that fills a vector/tensor with respect to passed coordinates * @param function_type flag to specify the take of function: _bft_stress is tensor like and _bft_forces is traction like. */ void SolidMechanicsModel::computeForcesFromFunction(void (*myf)(double *,double *), BoundaryFunctionType function_type){ /** function type is ** _bft_forces : traction function is given ** _bft_stress : stress function is given */ std::stringstream name; name << id << ":solidmechanics:imposed_traction"; Vector<Real> traction_funct(0, spatial_dimension,name.str()); name.clear(); name << id << ":solidmechanics:imposed_stresses"; Vector<Real> stress_funct(0, spatial_dimension*spatial_dimension,name.str()); name.clear(); name << id << ":solidmechanics:quad_coords"; Vector<Real> quad_coords(0,spatial_dimension,"quad_coords"); UInt offset = 0; switch(function_type) { case _bft_stress: offset = spatial_dimension * spatial_dimension; break; case _bft_forces: offset = spatial_dimension; break; } //prepare the loop over element types const Mesh::ConnectivityTypeList & type_list = fem_boundary->getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != fem_boundary->getElementDimension()) continue; UInt nb_quad = FEM::getNbQuadraturePoints(*it); UInt nb_element = fem_boundary->getMesh().getNbElement(*it); fem_boundary->interpolateOnQuadraturePoints(fem_boundary->getMesh().getNodes(), quad_coords, spatial_dimension, (*it)); Real * imposed_val = NULL; switch(function_type) { case _bft_stress: stress_funct.resize(nb_element*nb_quad); imposed_val = stress_funct.values; break; case _bft_forces: traction_funct.resize(nb_element*nb_quad); imposed_val = traction_funct.values; break; } /// sigma/tractions on each quadrature points Real * qcoord = quad_coords.values; for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quad; ++q) { myf(qcoord, imposed_val); imposed_val += offset; qcoord += spatial_dimension; } } switch(function_type) { case _bft_stress: computeForcesByStressTensor(stress_funct,(*it)); break; case _bft_forces: computeForcesByTractionVector(traction_funct,(*it)); break; } } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::computeForcesByStressTensor(const Vector<Real> & stresses, const ElementType & type){ AKANTU_DEBUG_IN(); UInt nb_element = fem_boundary->getMesh().getNbElement(type); UInt nb_quad = FEM::getNbQuadraturePoints(type); // check dimension match AKANTU_DEBUG_ASSERT(Mesh::getSpatialDimension(type) == fem_boundary->getElementDimension(), "element type dimension does not match the dimension of boundaries : " << fem_boundary->getElementDimension() << " != " << Mesh::getSpatialDimension(type)); // check size of the vector AKANTU_DEBUG_ASSERT(stresses.getSize() == nb_quad*nb_element, "the size of the vector should be the total number of quadrature points"); // check number of components AKANTU_DEBUG_ASSERT(stresses.getNbComponent() == spatial_dimension*spatial_dimension, "the number of components should be the dimension of 2-tensors"); std::stringstream name; name << id << ":solidmechanics:" << type << ":traction_boundary"; Vector<Real> funct(nb_element*nb_quad, spatial_dimension,name.str()); const Vector<Real> & normals_on_quad = fem_boundary->getNormalsOnQuadPoints(type); Math::matrix_vector(spatial_dimension,spatial_dimension,stresses,normals_on_quad,funct); computeForcesByTractionVector(funct,type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::computeForcesByTractionVector(const Vector<Real> & tractions, const ElementType & type){ AKANTU_DEBUG_IN(); UInt nb_element = fem_boundary->getMesh().getNbElement(type); UInt nb_nodes_per_element = fem_boundary->getMesh().getNbNodesPerElement(type); UInt nb_quad = FEM::getNbQuadraturePoints(type); // check dimension match AKANTU_DEBUG_ASSERT(Mesh::getSpatialDimension(type) == fem_boundary->getElementDimension(), "element type dimension does not match the dimension of boundaries : " << fem_boundary->getElementDimension() << " != " << Mesh::getSpatialDimension(type)); // check size of the vector AKANTU_DEBUG_ASSERT(tractions.getSize() == nb_quad*nb_element, "the size of the vector should be the total number of quadrature points"); // check number of components AKANTU_DEBUG_ASSERT(tractions.getNbComponent() == spatial_dimension, "the number of components should be the spatial dimension of the problem"); // do a complete copy of the vector Vector<Real> funct(tractions,true); // extend the vector to multiply by the shapes (prepare to assembly) funct.extendComponentsInterlaced(nb_nodes_per_element,spatial_dimension); // multiply by the shapes Real * funct_val = funct.values; Real * shapes_val = (fem_boundary->getShapes(type)).values; for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quad; ++q) { for (UInt n = 0; n < nb_nodes_per_element; ++n,++shapes_val) { for (UInt i = 0; i < spatial_dimension; ++i) { *funct_val++ *= *shapes_val; } } } } // allocate the vector that will contain the integrated values std::stringstream name; name << id << ":solidmechanics:" << type << ":integral_boundary"; Vector<Real> int_funct(nb_element, spatial_dimension*nb_nodes_per_element,name.str()); //do the integration fem_boundary->integrate(funct, int_funct, spatial_dimension*nb_nodes_per_element, type); // assemble the result into force vector fem_boundary->assembleVector(int_funct,const_cast<Vector<Real> &>(getForce()), spatial_dimension, type); AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/solid_mechanics_model_inline_impl.cc b/model/solid_mechanics/solid_mechanics_model_inline_impl.cc index 5bc89d7c0..decc89bf0 100644 --- a/model/solid_mechanics/solid_mechanics_model_inline_impl.cc +++ b/model/solid_mechanics/solid_mechanics_model_inline_impl.cc @@ -1,252 +1,266 @@ /** * @file solid_mechanics_model_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jul 29 12:07:04 2010 * * @brief Implementation of the inline functions of the SolidMechanicsModel class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ inline Material & SolidMechanicsModel::getMaterial(UInt mat_index) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(mat_index < materials.size(), "The model " << id << " has no material no "<< mat_index); AKANTU_DEBUG_OUT(); return *materials[mat_index]; } /* -------------------------------------------------------------------------- */ template <typename M> UInt SolidMechanicsModel::readCustomMaterial(const std::string & filename, const std::string & keyword) { MaterialParser parser; parser.open(filename); std::string key = keyword; to_lower(key); std::string mat_name = parser.getNextMaterialType(); while (mat_name != ""){ if (mat_name == key) break; mat_name = parser.getNextMaterialType(); } if (mat_name != key) AKANTU_DEBUG_ERROR("material " << key << " not found in file " << filename); std::stringstream sstr_mat; sstr_mat << id << ":" << materials.size() << ":" << key; MaterialID mat_id = sstr_mat.str(); Material * mat = parser.readMaterialObject<M>(*this,mat_id); materials.push_back(mat); return materials.size();; } /* -------------------------------------------------------------------------- */ inline UInt SolidMechanicsModel::getNbDataToPack(const Element & element, GhostSynchronizationTag tag) const { AKANTU_DEBUG_IN(); UInt size = 0; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type); #ifdef AKANTU_DEBUG size += spatial_dimension; /// position of the barycenter of the element (only for check) #endif switch(tag) { case _gst_smm_mass: { size += nb_nodes_per_element; // mass vector break; } case _gst_smm_residual: { size += nb_nodes_per_element * spatial_dimension; // displacement UInt mat = element_material[element.type]->values[element.element]; size += materials[mat]->getNbDataToPack(element, tag); break; } case _gst_smm_boundary: { size += nb_nodes_per_element * spatial_dimension * 3; // force, displacement, boundary break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); return size; } /* -------------------------------------------------------------------------- */ inline UInt SolidMechanicsModel::getNbDataToUnpack(const Element & element, GhostSynchronizationTag tag) const { AKANTU_DEBUG_IN(); UInt size = 0; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type); #ifdef AKANTU_DEBUG size += spatial_dimension; /// position of the barycenter of the element (only for check) #endif switch(tag) { case _gst_smm_mass: { size += nb_nodes_per_element; // mass vector break; } case _gst_smm_residual: { size += nb_nodes_per_element * spatial_dimension; // displacement UInt mat = ghost_element_material[element.type]->values[element.element]; size += materials[mat]->getNbDataToPack(element, tag); break; } case _gst_smm_boundary: { size += nb_nodes_per_element * spatial_dimension * 3; // force, displacement, boundary break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); return size; } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::packData(Real ** buffer, const Element & element, GhostSynchronizationTag tag) const { AKANTU_DEBUG_IN(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type); UInt el_offset = element.element * nb_nodes_per_element; UInt * conn = fem->getMesh().getConnectivity(element.type).values; #ifdef AKANTU_DEBUG fem->getMesh().getBarycenter(element.element, element.type, *buffer); (*buffer) += spatial_dimension; #endif switch(tag) { case _gst_smm_mass: { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; (*buffer)[n] = mass->values[offset_conn]; } *buffer += nb_nodes_per_element; break; } case _gst_smm_residual: { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n] * spatial_dimension; memcpy(*buffer, current_position->values + offset_conn, spatial_dimension * sizeof(Real)); *buffer += spatial_dimension; } UInt mat = element_material[element.type]->values[element.element]; materials[mat]->packData(buffer, element, tag); break; } case _gst_smm_boundary: { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n] * spatial_dimension; memcpy(*buffer, force->values + offset_conn, spatial_dimension * sizeof(Real)); *buffer += spatial_dimension; memcpy(*buffer, velocity->values + offset_conn, spatial_dimension * sizeof(Real)); *buffer += spatial_dimension; for (UInt i = 0; i < spatial_dimension; ++i) { (*buffer)[i] = boundary->values[offset_conn + i] ? 1.0 : -1.0; } *buffer += spatial_dimension; } break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::unpackData(Real ** buffer, const Element & element, GhostSynchronizationTag tag) const { AKANTU_DEBUG_IN(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type); UInt el_offset = element.element * nb_nodes_per_element; UInt * conn = fem->getMesh().getGhostConnectivity(element.type).values; #ifdef AKANTU_DEBUG Real barycenter[spatial_dimension]; fem->getMesh().getBarycenter(element.element, element.type, barycenter, _ghost); Real tolerance = 1e-15; for (UInt i = 0; i < spatial_dimension; ++i) { if(!(fabs(barycenter[i] - (*buffer)[i]) <= tolerance)) AKANTU_DEBUG_ERROR("Unpacking an unknown value for the element : " << element << "(barycenter[" << i << "] = " << barycenter[i] << " and (*buffer)[" << i << "] = " << (*buffer)[i] << ")"); } *buffer += spatial_dimension; #endif switch(tag) { case _gst_smm_mass: { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; mass->values[offset_conn] = (*buffer)[n]; } *buffer += nb_nodes_per_element; break; } case _gst_smm_residual: { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n] * spatial_dimension; memcpy(current_position->values + offset_conn, *buffer, spatial_dimension * sizeof(Real)); *buffer += spatial_dimension; } UInt mat = ghost_element_material[element.type]->values[element.element]; materials[mat]->unpackData(buffer, element, tag); break; } case _gst_smm_boundary: { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n] * spatial_dimension; memcpy(force->values + offset_conn, *buffer, spatial_dimension * sizeof(Real)); *buffer += spatial_dimension; memcpy(velocity->values + offset_conn, *buffer, spatial_dimension * sizeof(Real)); *buffer += spatial_dimension; for (UInt i = 0; i < spatial_dimension; ++i) { boundary->values[offset_conn + i] = ((*buffer)[i] > 0) ? true : false; } *buffer += spatial_dimension; } break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); } diff --git a/model/solid_mechanics/solid_mechanics_model_mass.cc b/model/solid_mechanics/solid_mechanics_model_mass.cc index 1fa1f2105..0e8b8f895 100644 --- a/model/solid_mechanics/solid_mechanics_model_mass.cc +++ b/model/solid_mechanics/solid_mechanics_model_mass.cc @@ -1,206 +1,220 @@ /** * @file solid_mechanics_model_mass.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Oct 4 15:21:23 2010 * * @brief function handling mass computation * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "material.hh" //#include "static_communicator.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMassLumped() { AKANTU_DEBUG_IN(); UInt nb_nodes = fem->getMesh().getNbNodes(); memset(mass->values, 0, nb_nodes*sizeof(Real)); assembleMassLumped(_not_ghost); assembleMassLumped(_ghost); /// for not connected nodes put mass to one in order to avoid /// wrong range in paraview Real * mass_values = mass->values; for (UInt i = 0; i < nb_nodes; ++i) { if (fabs(mass_values[i]) < std::numeric_limits<Real>::epsilon() || isnan(mass_values[i])) mass_values[i] = 1; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMassLumped(GhostType ghost_type) { AKANTU_DEBUG_IN(); const Mesh::ConnectivityTypeList & type_list = fem->getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; switch(*it) { case _triangle_6: case _tetrahedron_10: assembleMassLumpedDiagonalScaling(ghost_type, *it); break; default: assembleMassLumpedRowSum(ghost_type, *it); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j dV = \int \rho \varphi_i dV @f$ */ void SolidMechanicsModel::assembleMassLumpedRowSum(GhostType ghost_type, ElementType type) { AKANTU_DEBUG_IN(); Material ** mat_val = &(materials.at(0)); UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); UInt shape_size = FEM::getShapeSize(type); UInt nb_element; const Vector<Real> * shapes; UInt * elem_mat_val; if(ghost_type == _not_ghost) { nb_element = fem->getMesh().getNbElement(type); shapes = &(fem->getShapes(type)); elem_mat_val = element_material[type]->values; } else { nb_element = fem->getMesh().getNbGhostElement(type); shapes = &(fem->getGhostShapes(type)); elem_mat_val = ghost_element_material[type]->values; } if (nb_element == 0) { AKANTU_DEBUG_OUT(); return; } Vector<Real> * rho_phi_i = new Vector<Real>(nb_element * nb_quadrature_points, shape_size, "rho_x_shapes"); Real * rho_phi_i_val = rho_phi_i->values; Real * shapes_val = shapes->values; /// compute @f$ rho * \varphi_i @f$ for each nodes of each element for (UInt el = 0; el < nb_element; ++el) { Real rho = mat_val[elem_mat_val[el]]->getRho(); for (UInt n = 0; n < shape_size * nb_quadrature_points; ++n) { *rho_phi_i_val++ = rho * *shapes_val++; } } Vector<Real> * int_rho_phi_i = new Vector<Real>(0, shape_size, "inte_rho_x_shapes"); fem->integrate(*rho_phi_i, *int_rho_phi_i, shape_size, type, ghost_type); delete rho_phi_i; fem->assembleVector(*int_rho_phi_i, *mass, 1, type, ghost_type); delete int_rho_phi_i; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * @f$ \tilde{M}_{i} = c * M_{ii} = \int_{V_e} \rho dV @f$ */ void SolidMechanicsModel::assembleMassLumpedDiagonalScaling(GhostType ghost_type, ElementType type) { AKANTU_DEBUG_IN(); Material ** mat_val = &(materials.at(0)); UInt nb_nodes_per_element_p1 = Mesh::getNbNodesPerElement(Mesh::getP1ElementType(type)); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); UInt nb_element; UInt * elem_mat_val; Real corner_factor = 0; Real mid_factor = 0; switch(type){ case _triangle_6 : corner_factor = 1./12.; mid_factor = 1./4.; break; case _tetrahedron_10: corner_factor = 1./32.; mid_factor = 7./48.; break; default: corner_factor = 0; mid_factor = 0; } if(ghost_type == _not_ghost) { nb_element = fem->getMesh().getNbElement(type); elem_mat_val = element_material[type]->values; } else { nb_element = fem->getMesh().getNbGhostElement(type); elem_mat_val = ghost_element_material[type]->values; } if (nb_element == 0) { AKANTU_DEBUG_OUT(); return; } Vector<Real> * rho_1 = new Vector<Real>(nb_element * nb_quadrature_points, 1, "rho_x_1"); Real * rho_1_val = rho_1->values; /// compute @f$ rho @f$ for each nodes of each element for (UInt el = 0; el < nb_element; ++el) { Real rho = mat_val[elem_mat_val[el]]->getRho(); /// here rho is constant in an element for (UInt n = 0; n < nb_quadrature_points; ++n) { *rho_1_val++ = rho; } } /// compute @f$ \int \rho dV = \rho V @f$ for each element Vector<Real> * int_rho_1 = new Vector<Real>(nb_element * nb_quadrature_points, 1, "inte_rho_x_1"); fem->integrate(*rho_1, *int_rho_1, 1, type, ghost_type); delete rho_1; /// distribute the mass of the element to the nodes Vector<Real> * mass_per_node = new Vector<Real>(nb_element, nb_nodes_per_element, "mass_per_node"); Real * int_rho_1_val = int_rho_1->values; Real * mass_per_node_val = mass_per_node->values; for (UInt e = 0; e < nb_element; ++e) { Real lmass = *int_rho_1_val * corner_factor; for (UInt n = 0; n < nb_nodes_per_element_p1; ++n) *mass_per_node_val++ = lmass; /// corner points lmass = *int_rho_1_val * mid_factor; for (UInt n = nb_nodes_per_element_p1; n < nb_nodes_per_element; ++n) *mass_per_node_val++ = lmass; /// mid points int_rho_1_val++; } delete int_rho_1; fem->assembleVector(*mass_per_node, *mass, 1, type, ghost_type); delete mass_per_node; AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/solid_mechanics_model_material.cc b/model/solid_mechanics/solid_mechanics_model_material.cc index 9288f07f4..dc5ad98af 100644 --- a/model/solid_mechanics/solid_mechanics_model_material.cc +++ b/model/solid_mechanics/solid_mechanics_model_material.cc @@ -1,85 +1,99 @@ /** * @file solid_mechanics_model_material.cc * @author Guillaume ANCIAUX <anciaux@lsmscluster1.epfl.ch> * @date Thu Nov 25 10:48:53 2010 * - * @brief + * @brief * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "material.hh" #include "aka_math.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::readMaterials(const std::string & filename) { MaterialParser parser; parser.open(filename.c_str()); std::string mat_type = parser.getNextMaterialType(); UInt mat_count = 0; while (mat_type != ""){ std::stringstream sstr_mat; sstr_mat << id << ":" << mat_count++ << ":" << mat_type; Material * material; MaterialID mat_id = sstr_mat.str(); /// read the material properties if(mat_type == "elastic") material = parser.readMaterialObject<MaterialElastic>(*this,mat_id); else AKANTU_DEBUG_ERROR("Malformed material file : unknown material type " << mat_type); materials.push_back(material); mat_type = parser.getNextMaterialType(); } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initMaterials() { AKANTU_DEBUG_ASSERT(materials.size() != 0, "No material to initialize !"); Material ** mat_val = &(materials.at(0)); /// fill the element filters of the materials using the element_material arrays const Mesh::ConnectivityTypeList & type_list = fem->getMesh().getConnectivityTypeList(_not_ghost); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_element = fem->getMesh().getNbElement(*it); UInt * elem_mat_val = element_material[*it]->values; for (UInt el = 0; el < nb_element; ++el) { mat_val[elem_mat_val[el]]->addElement(*it, el); } } /// @todo synchronize element material /// fill the element filters of the materials using the element_material arrays const Mesh::ConnectivityTypeList & ghost_type_list = fem->getMesh().getConnectivityTypeList(_ghost); for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_element = fem->getMesh().getNbGhostElement(*it); UInt * elem_mat_val = ghost_element_material[*it]->values; for (UInt el = 0; el < nb_element; ++el) { mat_val[elem_mat_val[el]]->addGhostElement(*it, el); } } std::vector<Material *>::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { /// init internals properties (*mat_it)->initMaterial(); } } __END_AKANTU__ diff --git a/solver/solver.cc b/solver/solver.cc index bed8d1013..8d86dbd87 100644 --- a/solver/solver.cc +++ b/solver/solver.cc @@ -1,52 +1,66 @@ /** * @file solver.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Nov 17 16:19:27 2010 * * @brief Solver interface class * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "solver.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Solver::Solver(SparseMatrix & matrix, const SolverID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), matrix(&matrix), is_matrix_allocated(false), mesh(NULL) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Solver::Solver(const Mesh & mesh, __attribute__ ((unused)) const SparseMatrixType & sparse_matrix_type, __attribute__ ((unused)) UInt nb_degre_of_freedom, const SolverID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), matrix(NULL), is_matrix_allocated(false), rhs(NULL), mesh(&mesh) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Solver::~Solver() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/solver/solver.hh b/solver/solver.hh index c847a81b7..2b3ac02a6 100644 --- a/solver/solver.hh +++ b/solver/solver.hh @@ -1,113 +1,127 @@ /** * @file solver.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Oct 4 20:27:42 2010 * * @brief interface for solvers * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLVER_HH__ #define __AKANTU_SOLVER_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "aka_vector.hh" #include "sparse_matrix.hh" #include "mesh.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class Solver : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Solver(SparseMatrix & matrix, const SolverID & id = "solver", const MemoryID & memory_id = 0); Solver(const Mesh & mesh, const SparseMatrixType & sparse_matrix_type, UInt nb_degre_of_freedom, const SolverID & id = "solver", const MemoryID & memory_id = 0); virtual ~Solver(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the solver virtual void initialize() = 0; /// solve virtual void solve() = 0; /// assemble local matrices by elements in the global sparse matrix inline void assemble(const Vector<Real> & local_matrix, const Element & element); /// function to print the contain of the class // virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(RHS, *rhs, Vector<Real> &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of thr Solver SolverID id; /// the matrix SparseMatrix * matrix; /// is sparse matrix allocated bool is_matrix_allocated; /// the right hand side Vector<Real> * rhs; /// mesh const Mesh * mesh; /// pointer to the communicator StaticCommunicator * communicator; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "solver_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const Solver & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_SOLVER_HH__ */ diff --git a/solver/solver_inline_impl.cc b/solver/solver_inline_impl.cc index b80cfe87e..1b36ef735 100644 --- a/solver/solver_inline_impl.cc +++ b/solver/solver_inline_impl.cc @@ -1,19 +1,33 @@ /** * @file solver_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Nov 17 16:14:58 2010 * * @brief implementation of inline function of the Solver class * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ inline void Solver::assemble(const Vector<Real> & local_matrix, const Element & element) { AKANTU_DEBUG_ASSERT(matrix != NULL, "The sparse matrix must be first instantiated."); matrix->addToMatrix(local_matrix, element); } diff --git a/solver/solver_mumps.cc b/solver/solver_mumps.cc index 8a4d60f4f..b1528002a 100644 --- a/solver/solver_mumps.cc +++ b/solver/solver_mumps.cc @@ -1,325 +1,339 @@ /** * @file solver_mumps.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Nov 17 17:32:27 2010 * * @brief implem of SolverMumps class * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * * @section DESCRIPTION * * @subsection Ctrl_param Control parameters * * ICNTL(1), * ICNTL(2), * ICNTL(3) : output streams for error, diagnostics, and global messages * * ICNTL(4) : verbose level : 0 no message - 4 all messages * * ICNTL(5) : type of matrix, 0 assembled, 1 elementary * * ICNTL(6) : control the permutation and scaling(default 7) see mumps doc for * more information * * ICNTL(7) : determine the pivot order (default 7) see mumps doc for more * information * * ICNTL(8) : describe the scaling method used * * ICNTL(9) : 1 solve A x = b, 0 solve At x = b * * ICNTL(10) : number of iterative refinement when NRHS = 1 * * ICNTL(11) : > 0 return statistics * * ICNTL(12) : only used for SYM = 2, ordering strategy * * ICNTL(13) : * * ICNTL(14) : percentage of increase of the estimated working space * * ICNTL(15-17) : not used * * ICNTL(18) : only used if ICNTL(5) = 0, 0 matrix centralized, 1 structure on * host and mumps give the mapping, 2 structure on host and distributed matrix * for facto, 3 distributed matrix * * ICNTL(19) : > 0, Shur complement returned * * ICNTL(20) : 0 rhs dense, 1 rhs sparse * * ICNTL(21) : 0 solution in rhs, 1 solution distributed in ISOL_loc and SOL_loc * allocated by user * * ICNTL(22) : 0 in-core, 1 out-of-core * * ICNTL(23) : maximum memory allocatable by mumps pre proc * * ICNTL(24) : controls the detection of "null pivot rows" * * ICNTL(25) : * * ICNTL(26) : * * ICNTL(27) : * * ICNTL(28) : 0 automatic choice, 1 sequential analysis, 2 parallel analysis * * ICNTL(29) : 0 automatic choice, 1 PT-Scotch, 2 ParMetis */ /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_MPI #include <mpi.h> #include "static_communicator_mpi.hh" #endif #include "solver_mumps.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ SolverMumps::SolverMumps(const Mesh & mesh, const SparseMatrixType & sparse_matrix_type, UInt nb_degre_of_freedom, const SolverID & id, const MemoryID & memory_id) : Solver(mesh, sparse_matrix_type, nb_degre_of_freedom, id, memory_id) { AKANTU_DEBUG_IN(); std::stringstream sstr_mat; sstr_mat << id << ":sparse_matrix"; matrix = new SparseMatrix(mesh, sparse_matrix_type, nb_degre_of_freedom, sstr_mat.str(), memory_id); UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_rhs; sstr_rhs << id << ":rhs"; rhs = &(alloc<Real>(sstr_rhs.str(), nb_nodes * nb_degre_of_freedom, 1, REAL_INIT_VALUE)); mumps_data.sym = 2 * (sparse_matrix_type == _symmetric); #ifdef AKANTU_USE_MPI mumps_data.par = 1; StaticCommunicator * comm = StaticCommunicator::getStaticCommunicator(); mumps_data.comm_fortran = MPI_Comm_c2f(dynamic_cast<StaticCommunicatorMPI *>(comm)->getMPICommunicator()); #else mumps_data.par = 0; #endif icntl(1) = 2; icntl(2) = 2; icntl(3) = 2; icntl(4) = 1; if (debug::getDebugLevel() >= 10) icntl(4) = 4; else if (debug::getDebugLevel() >= 5) icntl(4) = 3; else if (debug::getDebugLevel() >= 3) icntl(4) = 2; mumps_data.job = _smj_initialize; //initialize dmumps_c(&mumps_data); mumps_data.n = nb_nodes * nb_degre_of_freedom; strcpy(mumps_data.write_problem, "mumps_matrix.mtx"); // mumps_data.nz = 0; // mumps_data.irn = NULL; // mumps_data.jcn = NULL; // mumps_data.a = NULL; // mumps_data.nz_loc = 0; // mumps_data.irn_loc = NULL; // mumps_data.jcn_loc = NULL; // mumps_data.a_loc = NULL; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolverMumps::SolverMumps(SparseMatrix & matrix, const SolverID & id, const MemoryID & memory_id) : Solver(matrix, id, memory_id) { AKANTU_DEBUG_IN(); // std::stringstream sstr; sstr << id << ":sparse_matrix"; // matrix = new SparseMatrix(mesh, sparse_matrix_type, nb_degre_of_freedom, sstr_mat.str(), memory_id); UInt size = matrix.getSize(); UInt nb_degre_of_freedom = matrix.getNbDegreOfFreedom(); std::stringstream sstr_rhs; sstr_rhs << id << ":rhs"; mumps_data.sym = 2 * (matrix.getSparseMatrixType() == _symmetric); communicator = StaticCommunicator::getStaticCommunicator(); #ifdef AKANTU_USE_MPI mumps_data.par = 1; mumps_data.comm_fortran = MPI_Comm_c2f(dynamic_cast<const StaticCommunicatorMPI *>(communicator)->getMPICommunicator()); #else mumps_data.par = 0; #endif if(communicator->whoAmI() == 0) { rhs = &(alloc<Real>(sstr_rhs.str(), size * nb_degre_of_freedom, 1, REAL_INIT_VALUE)); } else { rhs = NULL; } icntl(1) = 2; icntl(2) = 2; icntl(3) = 2; icntl(4) = 1; if (debug::getDebugLevel() >= 10) icntl(4) = 4; else if (debug::getDebugLevel() >= 5) icntl(4) = 3; else if (debug::getDebugLevel() >= 3) icntl(4) = 2; mumps_data.job = _smj_initialize; //initialize dmumps_c(&mumps_data); mumps_data.n = size * nb_degre_of_freedom; strcpy(mumps_data.write_problem, "mumps_matrix.mtx"); // mumps_data.nz = 0; // mumps_data.irn = NULL; // mumps_data.jcn = NULL; // mumps_data.a = NULL; // mumps_data.nz_loc = 0; // mumps_data.irn_loc = NULL; // mumps_data.jcn_loc = NULL; // mumps_data.a_loc = NULL; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolverMumps::~SolverMumps() { AKANTU_DEBUG_IN(); delete matrix; mumps_data.job = _smj_destroy; // destroy dmumps_c(&mumps_data); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolverMumps::initialize() { AKANTU_DEBUG_IN(); // matrix->buildProfile(); icntl(5) = 0; // Assembled matrix #ifdef AKANTU_USE_MPI mumps_data.nz_loc = matrix->getNbNonZero(); mumps_data.irn_loc = matrix->getIRN().values; mumps_data.jcn_loc = matrix->getJCN().values; icntl(18) = 3; //fully distributed icntl(28) = 0; //parallel analysis // #ifdef AKANTU_USE_PTSCOTCH // icntl(18) = 3; //fully distributed // icntl(28) = 2; //parallel analysis // #else // AKANTU_USE_PTSCOTCH // icntl(18) = 2; // distributed, sequential analysis // icntl(28) = 1; //sequential analysis // if (communicator->whoAmI() == 0) { // Int * nb_non_zero_loc = new Int[communicator->getNbProc()]; // nb_non_zero_loc[0] = matrix->getNbNonZero(); // communicator->gather(nb_non_zero_loc, 1, 0); // UInt nb_non_zero = 0; // for (Int i = 0; i < communicator->getNbProc(); ++i) { // nb_non_zero += nb_non_zero_loc[i]; // } // Int * irn = new Int[nb_non_zero]; // Int * jcn = new Int[nb_non_zero]; // memcpy(irn, matrix->getIRN().values, *nb_non_zero_loc * sizeof(int)); // memcpy(jcn, matrix->getJCN().values, *nb_non_zero_loc * sizeof(int)); // communicator->gatherv(irn, nb_non_zero_loc, 0); // communicator->gatherv(jcn, nb_non_zero_loc, 0); // mumps_data.nz = nb_non_zero; // mumps_data.irn = irn; // mumps_data.jcn = jcn; // } else { // Int nb_non_zero_loc = matrix->getNbNonZero(); // communicator->gather(&nb_non_zero_loc, 1, 0); // communicator->gatherv(matrix->getIRN().values, &nb_non_zero_loc, 0); // communicator->gatherv(matrix->getJCN().values, &nb_non_zero_loc, 0); // } // #endif // AKANTU_USE_PTSCOTCH #else //AKANTU_USE_MPI mumps_data.nz = matrix->getNbNonZero(); mumps_data.irn = matrix->getIRN().values; mumps_data.jcn = matrix->getJCN().values; icntl(18) = 0; //centralized icntl(28) = 0; //sequential analysis #endif //AKANTU_USE_MPI mumps_data.job = _smj_analyze; //analyse dmumps_c(&mumps_data); #ifdef AKANTU_USE_MPI #ifdef AKANTU_USE_PTSCOTCH delete [] mumps_data.irn; delete [] mumps_data.jcn; #endif #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolverMumps::solve() { AKANTU_DEBUG_IN(); #ifdef AKANTU_USE_MPI mumps_data.a_loc = matrix->getA().values; #else mumps_data.a = matrix->getA().values; #endif if(communicator->whoAmI() == 0) { mumps_data.rhs = rhs->values; } icntl(20) = 0; icntl(21) = 0; // mumps_data.nrhs = 1; // mumps_data.lrhs = mumps_data.n; mumps_data.job = _smj_factorize_solve; //solve dmumps_c(&mumps_data); /// @todo spread the rhs vector form host to slaves AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/solver/solver_mumps.hh b/solver/solver_mumps.hh index c9a13b53c..928b5720e 100644 --- a/solver/solver_mumps.hh +++ b/solver/solver_mumps.hh @@ -1,110 +1,124 @@ /** * @file solver_mumps.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Nov 17 17:28:56 2010 * * @brief Solver class implementation for the mumps solver * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLVER_MUMPS_HH__ #define __AKANTU_SOLVER_MUMPS_HH__ #include <dmumps_c.h> #include "solver.hh" __BEGIN_AKANTU__ class SolverMumps : public Solver { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SolverMumps(const Mesh & mesh, const SparseMatrixType & sparse_matrix_type, UInt nb_degre_of_freedom, const SolverID & id = "solver_mumps", const MemoryID & memory_id = 0); SolverMumps(SparseMatrix & sparse_matrix, const SolverID & id = "solver_mumps", const MemoryID & memory_id = 0); virtual ~SolverMumps(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// build the profile and do the analysis part void initialize(); /// factorize and solve the system void solve(); /// function to print the contain of the class // virtual void printself(std::ostream & stream, int indent = 0) const; private: inline Int & icntl(UInt i) { return mumps_data.icntl[i - 1]; } /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// mumps data DMUMPS_STRUC_C mumps_data; /* ------------------------------------------------------------------------ */ /* Local types */ /* ------------------------------------------------------------------------ */ private: enum SolverMumpsJob { _smj_initialize = -1, _smj_analyze = 1, _smj_factorize = 2, _smj_solve = 3, _smj_analyze_factorize = 4, _smj_factorize_solve = 5, _smj_complete = 6, // analyze, factorize, solve _smj_destroy = -2 }; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "solver_mumps_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const SolverMumps & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_SOLVER_MUMPS_HH__ */ diff --git a/solver/sparse_matrix.cc b/solver/sparse_matrix.cc index b3be12767..23bcd397d 100644 --- a/solver/sparse_matrix.cc +++ b/solver/sparse_matrix.cc @@ -1,227 +1,241 @@ /** * @file sparse_matrix.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Oct 26 18:25:07 2010 * * @brief implementation of the SparseMatrix class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <fstream> /* -------------------------------------------------------------------------- */ #include "sparse_matrix.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ SparseMatrix::SparseMatrix(const Mesh & mesh, const SparseMatrixType & sparse_matrix_type, UInt nb_degre_of_freedom, const SparseMatrixID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), sparse_matrix_type(sparse_matrix_type), nb_degre_of_freedom(nb_degre_of_freedom), mesh(&mesh), nb_non_zero(0), irn(0,1,"irn"), jcn(0,1,"jcn"), a(0,1,"A"), irn_jcn_to_k(NULL) { AKANTU_DEBUG_IN(); size = mesh.getNbNodes(); for(UInt t = _not_defined; t < _max_element_type; ++t) { this->element_to_sparse_profile[t] = NULL; } StaticCommunicator * comm = StaticCommunicator::getStaticCommunicator(); nb_proc = comm->getNbProc(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseMatrix::SparseMatrix(UInt size, const SparseMatrixType & sparse_matrix_type, UInt nb_degre_of_freedom, const SparseMatrixID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), sparse_matrix_type(sparse_matrix_type), nb_degre_of_freedom(nb_degre_of_freedom), mesh(NULL), size(size), nb_non_zero(0), irn(0,1,"irn"), jcn(0,1,"jcn"), a(0,1,"A"), irn_jcn_to_k(NULL) { AKANTU_DEBUG_IN(); for(UInt t = _not_defined; t < _max_element_type; ++t) { this->element_to_sparse_profile[t] = NULL; } StaticCommunicator * comm = StaticCommunicator::getStaticCommunicator(); nb_proc = comm->getNbProc(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseMatrix::~SparseMatrix() { AKANTU_DEBUG_IN(); if (irn_jcn_to_k) delete irn_jcn_to_k; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrix::buildProfile() { AKANTU_DEBUG_IN(); if(irn_jcn_to_k) delete irn_jcn_to_k; irn_jcn_to_k = new std::map<std::pair<UInt, UInt>, UInt>; // std::map<std::pair<UInt, UInt>, UInt> irn_jcn_to_k; std::map<std::pair<UInt, UInt>, UInt>::iterator irn_jcn_to_k_it; nb_non_zero = 0; irn.resize(0); jcn.resize(0); const Mesh::ConnectivityTypeList & type_list = mesh->getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if (Mesh::getSpatialDimension(*it) != mesh->getSpatialDimension()) continue; UInt nb_element = mesh->getNbElement(*it); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); if (element_to_sparse_profile[*it] == NULL) { std::stringstream sstr; UInt nb_values_per_elem = nb_degre_of_freedom * nb_nodes_per_element; if (sparse_matrix_type == _symmetric) { nb_values_per_elem = (nb_values_per_elem * (nb_values_per_elem + 1)) / 2; } else { nb_values_per_elem *= nb_values_per_elem; } sstr << id << ":" << "element_to_sparse_profile:" << *it; element_to_sparse_profile[*it] = &(alloc<UInt>(sstr.str(), nb_element, nb_values_per_elem)); std::cout << "COUNT " << nb_values_per_elem << std::endl; } UInt * global_nodes_ids_val = NULL; if(nb_proc > 1) global_nodes_ids_val = mesh->getGlobalNodesIds().values; UInt * elem_to_sparse_val = element_to_sparse_profile[*it]->values; UInt * conn_val = mesh->getConnectivity(*it).values; for (UInt e = 0; e < nb_element; ++e) { // loop on element UInt count = 0; for (UInt j = 0; j < nb_nodes_per_element; ++j) { // loop on local column UInt n_j = (nb_proc == 1) ? conn_val[j] : global_nodes_ids_val[conn_val[j]]; UInt c_jcn = n_j * nb_degre_of_freedom; for (UInt d_j = 0; d_j < nb_degre_of_freedom; ++d_j, ++c_jcn) { // loop on degre of freedom UInt i_end = (sparse_matrix_type == _symmetric) ? j + 1 : nb_nodes_per_element; for (UInt i = 0; i < i_end; ++i) { // loop on rows UInt n_i = (nb_proc == 1) ? conn_val[i] : global_nodes_ids_val[conn_val[i]]; UInt c_irn = n_i * nb_degre_of_freedom; UInt d_i_end = (sparse_matrix_type == _symmetric && i == j) ? d_j + 1 : nb_degre_of_freedom; for (UInt d_i = 0; d_i < d_i_end; ++d_i, ++c_irn) { // loop on degre of freedom std::pair<UInt, UInt> jcn_irn; if ((sparse_matrix_type == _symmetric) && c_irn < c_jcn) jcn_irn = std::make_pair(c_jcn, c_irn); else jcn_irn = std::make_pair(c_irn, c_jcn); irn_jcn_to_k_it = irn_jcn_to_k->find(jcn_irn); if (irn_jcn_to_k_it == irn_jcn_to_k->end()) { std::cout << c_irn << " " << c_jcn << " -> " << jcn_irn.first << " " << jcn_irn.second << " new (" << nb_non_zero << ")" << std::endl; *elem_to_sparse_val++ = nb_non_zero; count++; (*irn_jcn_to_k)[jcn_irn] = nb_non_zero; irn.push_back(c_irn + 1); jcn.push_back(c_jcn + 1); nb_non_zero++; } else { std::cout << c_irn << " " << c_jcn << " -> " << jcn_irn.first << " " << jcn_irn.second << " old (" << irn_jcn_to_k_it->second << ")" << std::endl; *elem_to_sparse_val++ = irn_jcn_to_k_it->second; count++; } } } } } conn_val += nb_nodes_per_element; std::cout << "COUNT " << e << " " << count << std::endl; } } a.resize(nb_non_zero); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrix::saveProfile(const std::string & filename) { AKANTU_DEBUG_IN(); std::ofstream outfile; outfile.open(filename.c_str()); outfile << "%%MatrixMarket matrix coordinate pattern"; if(sparse_matrix_type == _symmetric) outfile << " symmetric"; else outfile << " general"; outfile << std::endl; UInt m = size * nb_degre_of_freedom; outfile << m << " " << m << " " << nb_non_zero << std::endl; for (UInt i = 0; i < nb_non_zero; ++i) { outfile << irn.values[i]+1 << " " << jcn.values[i]+1 << " 1" << std::endl; } outfile.close(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrix::saveMatrix(const std::string & filename) { AKANTU_DEBUG_IN(); std::ofstream outfile; outfile.open(filename.c_str()); outfile << "%%MatrixMarket matrix coordinate real"; if(sparse_matrix_type == _symmetric) outfile << " symmetric"; else outfile << " general"; outfile << std::endl; UInt m = size * nb_degre_of_freedom; outfile << m << " " << m << " " << nb_non_zero << std::endl; for (UInt i = 0; i < nb_non_zero; ++i) { outfile << irn.values[i]+1 << " " << jcn.values[i]+1 << " " << a.values[i] << std::endl; } outfile.close(); AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/solver/sparse_matrix.hh b/solver/sparse_matrix.hh index 320e0bf0d..273271e9a 100644 --- a/solver/sparse_matrix.hh +++ b/solver/sparse_matrix.hh @@ -1,157 +1,171 @@ /** * @file sparse_matrix.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Oct 4 20:33:00 2010 * * @brief sparse matrix storage class (distributed assembled matrix) * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SPARSE_MATRIX_HH__ #define __AKANTU_SPARSE_MATRIX_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class SparseMatrix : private Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: SparseMatrix(const Mesh & mesh, const SparseMatrixType & sparse_matrix_type, UInt nb_degre_of_freedom, const SparseMatrixID & id = "sparse_matrix", const MemoryID & memory_id = 0); SparseMatrix(UInt size, const SparseMatrixType & sparse_matrix_type, UInt nb_degre_of_freedom, const SparseMatrixID & id = "sparse_matrix", const MemoryID & memory_id = 0); virtual ~SparseMatrix(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// add a non-zero element UInt addToProfile(UInt i, UInt j); /// set the matrix to 0 inline void clear(); /// assemble a local matrix in the sparse one inline void addToMatrix(UInt i, UInt j, Real value); /// assemble a local matrix in the sparse one inline void addToMatrix(const Vector<Real> & local_matrix, const Element & element); /// function to print the contain of the class //virtual void printself(std::ostream & stream, int indent = 0) const; /// fill the profil of the matrix void buildProfile(); /// save the profil in a file using the MatrixMarket file format void saveProfile(const std::string & filename); /// save the matrix in a file using the MatrixMarket file format void saveMatrix(const std::string & filename); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(IRN, irn, const Vector<Int> &); AKANTU_GET_MACRO(JCN, jcn, const Vector<Int> &); AKANTU_GET_MACRO(A, a, const Vector<Real> &); AKANTU_GET_MACRO(NbNonZero, nb_non_zero, UInt); AKANTU_GET_MACRO(Size, size, UInt); AKANTU_GET_MACRO(NbDegreOfFreedom, nb_degre_of_freedom, UInt); AKANTU_GET_MACRO(SparseMatrixType, sparse_matrix_type, const SparseMatrixType &) /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// id of the SparseMatrix SparseMatrixID id; /// sparce matrix type SparseMatrixType sparse_matrix_type; /// number of degre of freedom UInt nb_degre_of_freedom; /// Mesh corresponding to the profile const Mesh * mesh; /// Size of the matrix UInt size; /// number of processors UInt nb_proc; /// number of non zero element UInt nb_non_zero; /// row indexes Vector<Int> irn; /// column indexes Vector<Int> jcn; /// values : A[k] = Matrix[irn[k]][jcn[k]] Vector<Real> a; /// information to know where to assemble an element in a global sparse matrix ByElementTypeUInt element_to_sparse_profile; /* map for (i,j) -> k correspondence \warning std::map are slow * \todo improve with hash_map (non standard in stl) or unordered_map (boost or C++0x) */ std::map<std::pair<UInt, UInt>, UInt> * irn_jcn_to_k; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "sparse_matrix_inline_impl.cc" // /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const SparseMatrix & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_SPARSE_MATRIX_HH__ */ diff --git a/solver/sparse_matrix_inline_impl.cc b/solver/sparse_matrix_inline_impl.cc index 9197612e5..8ebeb2dfd 100644 --- a/solver/sparse_matrix_inline_impl.cc +++ b/solver/sparse_matrix_inline_impl.cc @@ -1,75 +1,89 @@ /** * @file sparse_matrix_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Oct 4 21:09:38 2010 * * @brief implementation of inline methods of the SparseMatrix class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ inline UInt SparseMatrix::addToProfile(UInt i, UInt j) { if(!irn_jcn_to_k) irn_jcn_to_k = new std::map<std::pair<UInt, UInt>, UInt>; std::pair<UInt, UInt> jcn_irn = std::make_pair(i, j); AKANTU_DEBUG_ASSERT(irn_jcn_to_k->find(jcn_irn) == irn_jcn_to_k->end(), "Couple (i,j) = (" << i << "," << j << ") already in the profile"); irn.push_back(i + 1); jcn.push_back(j + 1); // a.resize(a.getSize() + 1); Real zero = 0; a.push_back(zero); (*irn_jcn_to_k)[jcn_irn] = nb_non_zero; nb_non_zero++; return nb_non_zero - 1; } /* -------------------------------------------------------------------------- */ inline void SparseMatrix::clear() { memset(a.values, 0, nb_non_zero*sizeof(Real)); } /* -------------------------------------------------------------------------- */ inline void SparseMatrix::addToMatrix(UInt i, UInt j, Real value) { std::pair<UInt, UInt> jcn_irn = std::make_pair(i, j); std::map<std::pair<UInt, UInt>, UInt>::iterator irn_jcn_to_k_it = irn_jcn_to_k->find(jcn_irn); AKANTU_DEBUG_ASSERT(irn_jcn_to_k_it != irn_jcn_to_k->end(), "Couple (i,j) = (" << i << "," << j << ") does not exist in the profile"); std::cerr << "AAAAAAAA " << irn_jcn_to_k_it->second << std::endl; a.values[irn_jcn_to_k_it->second] += value; } /* -------------------------------------------------------------------------- */ inline void SparseMatrix::addToMatrix(const Vector<Real> & local_matrix, const Element & element) { AKANTU_DEBUG_ASSERT(element_to_sparse_profile[element.type] != NULL, "No profile stored for this kind of element call first buildProfile()"); UInt nb_values_per_elem = element_to_sparse_profile[element.type]->getNbComponent(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type); Real * mat_val = local_matrix.values; UInt * elem_to_sparse_val = element_to_sparse_profile[element.type]->values + element.element * nb_values_per_elem; Real * a_val = a.values; for (UInt j = 0; j < nb_nodes_per_element * nb_degre_of_freedom; ++j) { UInt i_end = (sparse_matrix_type == _symmetric) ? j + 1 : nb_nodes_per_element * nb_degre_of_freedom; for (UInt i = 0; i < i_end; ++i) { UInt k = *(elem_to_sparse_val++); a_val[k] += *(mat_val++); } } } diff --git a/synchronizer/communicator.cc b/synchronizer/communicator.cc index a4c525269..610acafb2 100644 --- a/synchronizer/communicator.cc +++ b/synchronizer/communicator.cc @@ -1,577 +1,591 @@ /** * @file communicator.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Aug 26 16:36:21 2010 * * @brief implementation of a communicator using a static_communicator for real * send/receive * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "ghost_synchronizer.hh" #include "communicator.hh" #include "static_communicator.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Communicator::Communicator(SynchronizerID id, MemoryID memory_id) : Synchronizer(id, memory_id), static_communicator(StaticCommunicator::getStaticCommunicator()) { AKANTU_DEBUG_IN(); for (UInt t = _not_defined; t < _max_element_type; ++t) { element_to_send_offset [t] = NULL; element_to_send [t] = NULL; element_to_receive_offset[t] = NULL; element_to_receive [t] = NULL; } nb_proc = static_communicator->getNbProc(); rank = static_communicator->whoAmI(); send_buffer = new Vector<Real>[nb_proc]; recv_buffer = new Vector<Real>[nb_proc]; send_element = new std::vector<Element>[nb_proc]; recv_element = new std::vector<Element>[nb_proc]; size_to_send.clear(); size_to_receive.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Communicator::~Communicator() { AKANTU_DEBUG_IN(); for (UInt p = 0; p < nb_proc; ++p) { send_buffer[p].resize(0); recv_buffer[p].resize(0); send_element[p].clear(); recv_element[p].clear(); } delete [] send_buffer; delete [] recv_buffer; delete [] send_element; delete [] recv_element; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Communicator * Communicator::createCommunicatorDistributeMesh(Mesh & mesh, const MeshPartition * partition, UInt root, SynchronizerID id, MemoryID memory_id) { AKANTU_DEBUG_IN(); StaticCommunicator * comm = StaticCommunicator::getStaticCommunicator(); UInt nb_proc = comm->getNbProc(); UInt my_rank = comm->whoAmI(); UInt * local_connectivity = NULL; UInt * local_partitions = NULL; Vector<UInt> * old_nodes = mesh.getNodesGlobalIdsPointer(); Vector<Real> * nodes = mesh.getNodesPointer(); UInt spatial_dimension = nodes->getNbComponent(); Communicator * communicator = new Communicator(id, memory_id); if(nb_proc == 1) return communicator; /* ------------------------------------------------------------------------ */ /* Local (rank == root) */ /* ------------------------------------------------------------------------ */ if(my_rank == root) { AKANTU_DEBUG_ASSERT(partition->getNbPartition() == nb_proc, "The number of partition does not match the number of processors"); /** * connectivity and communications scheme construction */ const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != mesh.getSpatialDimension()) continue; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_element = mesh.getNbElement(*it); UInt nb_local_element[nb_proc]; UInt nb_ghost_element[nb_proc]; UInt nb_element_to_send[nb_proc]; memset(nb_local_element, 0, nb_proc*sizeof(UInt)); memset(nb_ghost_element, 0, nb_proc*sizeof(UInt)); memset(nb_element_to_send, 0, nb_proc*sizeof(UInt)); UInt * partition_num = partition->getPartition(type).values; UInt * ghost_partition = partition->getGhostPartition(type).values; UInt * ghost_partition_offset = partition->getGhostPartitionOffset(type).values; /// constricting the reordering structures for (UInt el = 0; el < nb_element; ++el) { nb_local_element[partition_num[el]]++; for (UInt part = ghost_partition_offset[el]; part < ghost_partition_offset[el + 1]; ++part) { nb_ghost_element[ghost_partition[part]]++; } nb_element_to_send[partition_num[el]] += ghost_partition_offset[el + 1] - ghost_partition_offset[el] + 1; } /// allocating buffers UInt * buffers[nb_proc]; UInt * buffers_tmp[nb_proc]; for (UInt p = 0; p < nb_proc; ++p) { UInt size = nb_nodes_per_element * (nb_local_element[p] + nb_ghost_element[p]); buffers[p] = new UInt[size]; buffers_tmp[p] = buffers[p]; } /// copying the local connectivity UInt * conn_val = mesh.getConnectivity(type).values; for (UInt el = 0; el < nb_element; ++el) { memcpy(buffers_tmp[partition_num[el]], conn_val + el * nb_nodes_per_element, nb_nodes_per_element * sizeof(UInt)); buffers_tmp[partition_num[el]] += nb_nodes_per_element; } /// copying the connectivity of ghost element for (UInt el = 0; el < nb_element; ++el) { for (UInt part = ghost_partition_offset[el]; part < ghost_partition_offset[el + 1]; ++part) { UInt proc = ghost_partition[part]; memcpy(buffers_tmp[proc], conn_val + el * nb_nodes_per_element, nb_nodes_per_element * sizeof(UInt)); buffers_tmp[proc] += nb_nodes_per_element; } } /// send all connectivity and ghost information to all processors std::vector<CommunicationRequest *> requests; for (UInt p = 0; p < nb_proc; ++p) { if(p != root) { UInt size[4]; size[0] = (UInt) type; size[1] = nb_local_element[p]; size[2] = nb_ghost_element[p]; size[3] = nb_element_to_send[p]; comm->send(size, 4, p, 0); AKANTU_DEBUG_INFO("Sending connectivities to proc " << p); requests.push_back(comm->asyncSend(buffers[p], nb_nodes_per_element * (nb_local_element[p] + nb_ghost_element[p]), p, 1)); } else { local_connectivity = buffers[p]; } } /// create the renumbered connectivity AKANTU_DEBUG_INFO("Renumbering local connectivities"); MeshUtils::renumberMeshNodes(mesh, local_connectivity, nb_local_element[root], nb_ghost_element[root], type, *old_nodes); comm->waitAll(requests); comm->freeCommunicationRequest(requests); requests.clear(); for (UInt p = 0; p < nb_proc; ++p) { delete [] buffers[p]; } for (UInt p = 0; p < nb_proc; ++p) { buffers[p] = new UInt[nb_ghost_element[p] + nb_element_to_send[p]]; buffers_tmp[p] = buffers[p]; } /// splitting the partition information to send them to processors UInt count_by_proc[nb_proc]; memset(count_by_proc, 0, nb_proc*sizeof(UInt)); for (UInt el = 0; el < nb_element; ++el) { *(buffers_tmp[partition_num[el]]++) = ghost_partition_offset[el + 1] - ghost_partition_offset[el]; for (UInt part = ghost_partition_offset[el], i = 0; part < ghost_partition_offset[el + 1]; ++part, ++i) { *(buffers_tmp[partition_num[el]]++) = ghost_partition[part]; } } for (UInt el = 0; el < nb_element; ++el) { for (UInt part = ghost_partition_offset[el], i = 0; part < ghost_partition_offset[el + 1]; ++part, ++i) { *(buffers_tmp[ghost_partition[part]]++) = partition_num[el]; } } /// last data to compute the communication scheme for (UInt p = 0; p < nb_proc; ++p) { if(p != root) { AKANTU_DEBUG_INFO("Sending partition informations to proc " << p); requests.push_back(comm->asyncSend(buffers[p], nb_element_to_send[p] + nb_ghost_element[p], p, 2)); } else { local_partitions = buffers[p]; } } AKANTU_DEBUG_INFO("Creating communications scheme"); communicator->fillCommunicationScheme(local_partitions, nb_local_element[root], nb_ghost_element[root], type); comm->waitAll(requests); comm->freeCommunicationRequest(requests); requests.clear(); for (UInt p = 0; p < nb_proc; ++p) { delete [] buffers[p]; } } for (UInt p = 0; p < nb_proc; ++p) { if(p != root) { UInt size[4]; size[0] = (UInt) _not_defined; size[1] = 0; size[2] = 0; size[3] = 0; comm->send(size, 4, p, 0); } } /** * Nodes coordinate construction and synchronization */ /// get the list of nodes to send and send them Real * local_nodes = NULL; for (UInt p = 0; p < nb_proc; ++p) { UInt nb_nodes; UInt * buffer; if(p != root) { AKANTU_DEBUG_INFO("Receiving list of nodes from proc " << p); comm->receive(&nb_nodes, 1, p, 0); buffer = new UInt[nb_nodes]; comm->receive(buffer, nb_nodes, p, 3); } else { nb_nodes = old_nodes->getSize(); buffer = old_nodes->values; } /// get the coordinates for the selected nodes Real * nodes_to_send = new Real[nb_nodes * spatial_dimension]; Real * nodes_to_send_tmp = nodes_to_send; for (UInt n = 0; n < nb_nodes; ++n) { memcpy(nodes_to_send_tmp, nodes->values + spatial_dimension * buffer[n], spatial_dimension * sizeof(Real)); nodes_to_send_tmp += spatial_dimension; } if(p != root) { /// send them for distant processors delete [] buffer; AKANTU_DEBUG_INFO("Sending coordinates to proc " << p); comm->send(nodes_to_send, nb_nodes * spatial_dimension, p, 4); delete [] nodes_to_send; } else { /// save them for local processor local_nodes = nodes_to_send; } } /// construct the local nodes coordinates UInt nb_nodes = old_nodes->getSize(); nodes->resize(nb_nodes); memcpy(nodes->values, local_nodes, nb_nodes * spatial_dimension * sizeof(Real)); delete [] local_nodes; /* ---------------------------------------------------------------------- */ /* Distant (rank != root) */ /* ---------------------------------------------------------------------- */ } else { /** * connectivity and communications scheme construction on distant processors */ ElementType type = _not_defined; do { UInt size[4]; comm->receive(size, 4, root, 0); type = (ElementType) size[0]; UInt nb_local_element = size[1]; UInt nb_ghost_element = size[2]; UInt nb_element_to_send = size[3]; if(type != _not_defined) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); local_connectivity = new UInt[(nb_local_element + nb_ghost_element) * nb_nodes_per_element]; AKANTU_DEBUG_INFO("Receiving connectivities from proc " << root); comm->receive(local_connectivity, nb_nodes_per_element * (nb_local_element + nb_ghost_element), root, 1); AKANTU_DEBUG_INFO("Renumbering local connectivities"); MeshUtils::renumberMeshNodes(mesh, local_connectivity, nb_local_element, nb_ghost_element, type, *old_nodes); delete [] local_connectivity; local_partitions = new UInt[nb_element_to_send + nb_ghost_element * 2]; AKANTU_DEBUG_INFO("Receiving partition informations from proc " << root); comm->receive(local_partitions, nb_element_to_send + nb_ghost_element * 2, root, 2); AKANTU_DEBUG_INFO("Creating communications scheme"); communicator->fillCommunicationScheme(local_partitions, nb_local_element, nb_ghost_element, type); delete [] local_partitions; } } while(type != _not_defined); /** * Nodes coordinate construction and synchronization on distant processors */ AKANTU_DEBUG_INFO("Sending list of nodes to proc " << root); UInt nb_nodes = old_nodes->getSize(); comm->send(&nb_nodes, 1, root, 0); comm->send(old_nodes->values, nb_nodes, root, 3); nodes->resize(nb_nodes); AKANTU_DEBUG_INFO("Receiving coordinates from proc " << root); comm->receive(nodes->values, nb_nodes * spatial_dimension, root, 4); } AKANTU_DEBUG_OUT(); return communicator; } /* -------------------------------------------------------------------------- */ void Communicator::fillCommunicationScheme(UInt * partition, UInt nb_local_element, UInt nb_ghost_element, ElementType type) { AKANTU_DEBUG_IN(); Element element; element.type = type; UInt * part = partition; part = partition; for (UInt lel = 0; lel < nb_local_element; ++lel) { UInt nb_send = *part; part++; element.element = lel; for (UInt p = 0; p < nb_send; ++p) { UInt proc = *part; part++; AKANTU_DEBUG(dblAccessory, "Must send : " << element << " to proc " << proc); (send_element[proc]).push_back(element); } } for (UInt gel = 0; gel < nb_ghost_element; ++gel) { UInt proc = *part; part++; element.element = gel; AKANTU_DEBUG(dblAccessory, "Must recv : " << element << " from proc " << proc); recv_element[proc].push_back(element); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Communicator::synchronize(GhostSynchronizationTag tag) { AKANTU_DEBUG_IN(); asynchronousSynchronize(tag); waitEndSynchronize(tag); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Communicator::asynchronousSynchronize(GhostSynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(send_requests.size() == 0, "There must be some pending sending communications"); for (UInt p = 0; p < nb_proc; ++p) { UInt ssize = (size_to_send[tag]).values[p]; if(p == rank || ssize == 0) continue; send_buffer[p].resize(ssize); Real * buffer = send_buffer[p].values; Element * elements = &(send_element[p].at(0)); UInt nb_elements = send_element[p].size(); AKANTU_DEBUG_INFO("Packing data for proc " << p << " (" << ssize << "/" << nb_elements <<" data to send/elements)"); for (UInt el = 0; el < nb_elements; ++el) { ghost_synchronizer->packData(&buffer, *elements, tag); elements++; } std::cerr << std::dec; AKANTU_DEBUG_INFO("Posting send to proc " << p); send_requests.push_back(static_communicator->asyncSend(send_buffer[p].values, ssize, p, (Int) tag)); } AKANTU_DEBUG_ASSERT(recv_requests.size() == 0, "There must be some pending receive communications"); for (UInt p = 0; p < nb_proc; ++p) { UInt rsize = (size_to_receive[tag]).values[p]; if(p == rank || rsize == 0) continue; recv_buffer[p].resize(rsize); AKANTU_DEBUG_INFO("Posting receive from proc " << p << " (" << rsize << " data to receive)"); recv_requests.push_back(static_communicator->asyncReceive(recv_buffer[p].values, rsize, p, (Int) tag)); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Communicator::waitEndSynchronize(GhostSynchronizationTag tag) { AKANTU_DEBUG_IN(); std::vector<CommunicationRequest *> req_not_finished; std::vector<CommunicationRequest *> * req_not_finished_tmp = &req_not_finished; std::vector<CommunicationRequest *> * recv_requests_tmp = &recv_requests; while(!recv_requests_tmp->empty()) { for (std::vector<CommunicationRequest *>::iterator req_it = recv_requests_tmp->begin(); req_it != recv_requests_tmp->end() ; ++req_it) { CommunicationRequest * req = *req_it; if(static_communicator->testRequest(req)) { UInt proc = req->getSource(); AKANTU_DEBUG_INFO("Unpacking data coming from proc " << proc); Real * buffer = recv_buffer[proc].values; Element * elements = &recv_element[proc].at(0); UInt nb_elements = recv_element[proc].size(); for (UInt el = 0; el < nb_elements; ++el) { ghost_synchronizer->unpackData(&buffer, *elements, tag); elements++; } static_communicator->freeCommunicationRequest(req); } else { req_not_finished_tmp->push_back(req); } } std::vector<CommunicationRequest *> * swap = req_not_finished_tmp; req_not_finished_tmp = recv_requests_tmp; recv_requests_tmp = swap; req_not_finished_tmp->clear(); } static_communicator->waitAll(send_requests); static_communicator->freeCommunicationRequest(send_requests); send_requests.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Communicator::allReduce(Real * values, UInt nb_values, const SynchronizerOperation & op) { AKANTU_DEBUG_IN(); static_communicator->allReduce(values, nb_values, op); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Communicator::registerTag(GhostSynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(size_to_send.find(tag) == size_to_send.end(), "The GhostSynchronizationTag " << tag << "is already registered in " << id); size_to_send [tag].resize(nb_proc); size_to_receive[tag].resize(nb_proc); for (UInt p = 0; p < nb_proc; ++p) { UInt ssend = 0; UInt sreceive = 0; if(p != rank) { for (std::vector<Element>::const_iterator sit = send_element[p].begin(); sit != send_element[p].end(); ++sit) { ssend += ghost_synchronizer->getNbDataToPack(*sit, tag); } for (std::vector<Element>::const_iterator rit = recv_element[p].begin(); rit != recv_element[p].end(); ++rit) { sreceive += ghost_synchronizer->getNbDataToUnpack(*rit, tag); } AKANTU_DEBUG_INFO("I have " << ssend << " data to send to " << p << " and " << sreceive << " data to receive for tag " << tag); } size_to_send [tag].values[p] = ssend; size_to_receive[tag].values[p] = sreceive; } AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/synchronizer/communicator.hh b/synchronizer/communicator.hh index d4abfd5ef..5cdc99521 100644 --- a/synchronizer/communicator.hh +++ b/synchronizer/communicator.hh @@ -1,127 +1,141 @@ /** * @file communicator.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Aug 19 15:28:35 2010 * * @brief wrapper to the static communicator * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COMMUNICATOR_HH__ #define __AKANTU_COMMUNICATOR_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_vector.hh" #include "static_communicator.hh" #include "synchronizer.hh" #include "mesh.hh" #include "mesh_partition.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class Communicator : public Synchronizer { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Communicator(SynchronizerID id = "communicator", MemoryID memory_id = 0); virtual ~Communicator(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// get a mesh and a partition and create the local mesh and the associated communicator static Communicator * createCommunicatorDistributeMesh(Mesh & mesh, const MeshPartition * partition, UInt root = 0, SynchronizerID id = "communicator", MemoryID memory_id = 0); /* ------------------------------------------------------------------------ */ /* Inherited from Synchronizer */ /* ------------------------------------------------------------------------ */ /// synchronize ghosts void synchronize(GhostSynchronizationTag tag); /// asynchronous synchronization of ghosts void asynchronousSynchronize(GhostSynchronizationTag tag); /// wait end of asynchronous synchronization of ghosts void waitEndSynchronize(GhostSynchronizationTag tag); /// do a all reduce operation void allReduce(Real * values, UInt nb_values, const SynchronizerOperation & op); /* ------------------------------------------------------------------------ */ /// register a new communication void registerTag(GhostSynchronizationTag tag); protected: /// fill the communications array of a communicator based on a partition array void fillCommunicationScheme(UInt * partition, UInt nb_local_element, UInt nb_ghost_element, ElementType type); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// the static memory instance StaticCommunicator * static_communicator; /// size of data to send to each processor by communication tag std::map< GhostSynchronizationTag, Vector<UInt> > size_to_send; /// size of data to receive form each processor by communication tag std::map< GhostSynchronizationTag, Vector<UInt> > size_to_receive; Vector<Real> * send_buffer; Vector<Real> * recv_buffer; /// send requests std::vector<CommunicationRequest *> send_requests; /// receive requests std::vector<CommunicationRequest *> recv_requests; /// list of real element to send ordered by type then by receiver processors ByElementTypeUInt element_to_send_offset; ByElementTypeUInt element_to_send; std::vector<Element> * send_element; std::vector<Element> * recv_element; /// list of ghost element to receive ordered by type then by sender processors ByElementTypeUInt element_to_receive_offset; ByElementTypeUInt element_to_receive; UInt nb_proc; UInt rank; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "communicator_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_COMMUNICATOR_HH__ */ diff --git a/synchronizer/ghost_synchronizer.cc b/synchronizer/ghost_synchronizer.cc index e41210776..1d182ac82 100644 --- a/synchronizer/ghost_synchronizer.cc +++ b/synchronizer/ghost_synchronizer.cc @@ -1,150 +1,164 @@ /** * @file ghost_synchronizer.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Aug 24 18:59:17 2010 * * @brief implementation of the ghost synchronizer * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "ghost_synchronizer.hh" #include "synchronizer.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ GhostSynchronizer::GhostSynchronizer() : nb_ghost_synchronization_tags(0) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ GhostSynchronizer::~GhostSynchronizer() { AKANTU_DEBUG_IN(); for (std::list<Synchronizer *>::iterator it = synchronizers.begin(); it != synchronizers.end(); ++it) { delete (*it); } synchronizers.clear(); registered_synchronization.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GhostSynchronizer::synchronize(GhostSynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(registered_synchronization.find(tag) != registered_synchronization.end(), "Tag " << tag << " is not registered."); AKANTU_DEBUG_INFO("Synchronizing the tag : " << registered_synchronization.find(tag)->second << " (" << tag <<")"); for (std::list<Synchronizer *>::iterator it = synchronizers.begin(); it != synchronizers.end(); ++it) { (*it)->synchronize(tag); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GhostSynchronizer::asynchronousSynchronize(GhostSynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(registered_synchronization.find(tag) != registered_synchronization.end(), "Tag " << tag << " is not registered."); for (std::list<Synchronizer *>::iterator it = synchronizers.begin(); it != synchronizers.end(); ++it) { (*it)->asynchronousSynchronize(tag); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GhostSynchronizer::waitEndSynchronize(GhostSynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(registered_synchronization.find(tag) != registered_synchronization.end(), "Tag " << tag << " is not registered."); for (std::list<Synchronizer *>::iterator it = synchronizers.begin(); it != synchronizers.end(); ++it) { (*it)->waitEndSynchronize(tag); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GhostSynchronizer::registerTag(GhostSynchronizationTag tag, const std::string & name) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(registered_synchronization.find(tag) == registered_synchronization.end(), "Tag " << tag << " (" << name << ") already registered."); registered_synchronization[tag] = name; for (std::list<Synchronizer *>::iterator it = synchronizers.begin(); it != synchronizers.end(); ++it) { (*it)->registerTag(tag); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GhostSynchronizer::allReduce(Real * values, const SynchronizerOperation & op, UInt nb_values) { AKANTU_DEBUG_IN(); for (std::list<Synchronizer *>::iterator it = synchronizers.begin(); it != synchronizers.end(); ++it) { (*it)->allReduce(values, nb_values, op); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void GhostSynchronizer::registerSynchronizer(Synchronizer & synchronizer) { AKANTU_DEBUG_IN(); synchronizers.push_back(&synchronizer); synchronizer.registerGhostSynchronizer(*this); std::map<GhostSynchronizationTag, std::string>::iterator it; for (it = registered_synchronization.begin(); it != registered_synchronization.end(); ++it) { synchronizer.registerTag(it->first); } AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/synchronizer/ghost_synchronizer.hh b/synchronizer/ghost_synchronizer.hh index 3de74c5d6..26578316a 100644 --- a/synchronizer/ghost_synchronizer.hh +++ b/synchronizer/ghost_synchronizer.hh @@ -1,116 +1,130 @@ /** * @file ghost_synchronizer.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Aug 20 17:40:08 2010 * * @brief Class of ghost synchronisation (PBC or parallel communication) * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_GHOST_SYNCHRONIZER_HH__ #define __AKANTU_GHOST_SYNCHRONIZER_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class Synchronizer; } __BEGIN_AKANTU__ class GhostSynchronizer { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: GhostSynchronizer(); virtual ~GhostSynchronizer(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /// synchronize ghosts void synchronize(GhostSynchronizationTag tag); /// asynchronous synchronization of ghosts void asynchronousSynchronize(GhostSynchronizationTag tag); /// wait end of asynchronous synchronization of ghosts void waitEndSynchronize(GhostSynchronizationTag tag); /// reduce a value (essentially for communications synchronizer) void allReduce(Real * values, const SynchronizerOperation & op, UInt nb_values = 1); /* ------------------------------------------------------------------------ */ /// register a new communication void registerTag(GhostSynchronizationTag tag, const std::string & name); /// register a new synchronization void registerSynchronizer(Synchronizer & synchronizer); public: virtual UInt getNbDataToPack(const Element & element, GhostSynchronizationTag tag) const = 0; virtual UInt getNbDataToUnpack(const Element & element, GhostSynchronizationTag tag) const = 0; virtual void packData(Real ** buffer, const Element & element, GhostSynchronizationTag tag) const = 0; virtual void unpackData(Real ** buffer, const Element & element, GhostSynchronizationTag tag) const = 0; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// list of synchronizers std::list<Synchronizer *> synchronizers; /// number of tags registered UInt nb_ghost_synchronization_tags; /// list of registered synchronization std::map<GhostSynchronizationTag, std::string> registered_synchronization; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "ghost_synchronizer_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const GhostSynchronizer & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_GHOST_SYNCHRONIZER_HH__ */ diff --git a/synchronizer/static_communicator.cc b/synchronizer/static_communicator.cc index 16dd03884..4c72ddb15 100644 --- a/synchronizer/static_communicator.cc +++ b/synchronizer/static_communicator.cc @@ -1,90 +1,104 @@ /** * @file static_communicator.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Aug 19 15:39:47 2010 * * @brief implementation of the common part of the static communicator * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "static_communicator.hh" #include "static_communicator_dummy.hh" #ifdef AKANTU_USE_MPI # include "static_communicator_mpi.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ bool StaticCommunicator::is_instantiated = false; StaticCommunicator * StaticCommunicator::static_communicator = NULL; UInt CommunicationRequest::counter = 0; /* -------------------------------------------------------------------------- */ CommunicationRequest::CommunicationRequest(UInt source, UInt dest) : source(source), destination(dest) { this->id = counter++; } /* -------------------------------------------------------------------------- */ CommunicationRequest::~CommunicationRequest() { } /* -------------------------------------------------------------------------- */ void CommunicationRequest::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "CommunicationRequest [" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + source : " << source << std::endl; stream << space << " + destination : " << destination << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ StaticCommunicator * StaticCommunicator::getStaticCommunicator(CommunicatorType type) { AKANTU_DEBUG_IN(); #ifdef AKANTU_USE_MPI if(type == _communicator_mpi) { if (!static_communicator) AKANTU_DEBUG_ERROR("You must call getStaticCommunicator(argc, argv) to create a MPI communicator"); } #endif if (!static_communicator) static_communicator = new StaticCommunicatorDummy(); is_instantiated = true; AKANTU_DEBUG_OUT(); return static_communicator; } /* -------------------------------------------------------------------------- */ StaticCommunicator * StaticCommunicator::getStaticCommunicator(__attribute__ ((unused)) int * argc, __attribute__ ((unused)) char *** argv, CommunicatorType type) { #ifdef AKANTU_USE_MPI if(type == _communicator_mpi) { if (!static_communicator) static_communicator = dynamic_cast<StaticCommunicator *>(new StaticCommunicatorMPI(argc, argv)); } #endif return getStaticCommunicator(type); } __END_AKANTU__ diff --git a/synchronizer/static_communicator.hh b/synchronizer/static_communicator.hh index 2523b6076..d494c1a91 100644 --- a/synchronizer/static_communicator.hh +++ b/synchronizer/static_communicator.hh @@ -1,140 +1,154 @@ /** * @file static_communicator.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Aug 19 15:34:09 2010 * * @brief Class handling the parallel communications * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_STATIC_COMMUNICATOR_HH__ #define __AKANTU_STATIC_COMMUNICATOR_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class CommunicationRequest { public: CommunicationRequest(UInt source, UInt dest); virtual ~CommunicationRequest(); virtual void printself(std::ostream & stream, int indent = 0) const; AKANTU_GET_MACRO(Source, source, UInt); AKANTU_GET_MACRO(Destination, destination, UInt); private: UInt source; UInt destination; UInt id; static UInt counter; }; class StaticCommunicator { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ protected: StaticCommunicator() { }; public: virtual ~StaticCommunicator() { }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void send(UInt * buffer, Int size, Int receiver, Int tag) = 0; virtual void send(Real * buffer, Int size, Int receiver, Int tag) = 0; virtual void receive(UInt * buffer, Int size, Int sender, Int tag) = 0; virtual void receive(Real * buffer, Int size, Int sender, Int tag) = 0; virtual CommunicationRequest * asyncSend(UInt * buffer, Int size, Int receiver, Int tag) = 0; virtual CommunicationRequest * asyncSend(Real * buffer, Int size, Int receiver, Int tag) = 0; virtual CommunicationRequest * asyncReceive(UInt * buffer, Int size, Int sender, Int tag) = 0; virtual CommunicationRequest * asyncReceive(Real * buffer, Int size, Int sender, Int tag) = 0; virtual bool testRequest(CommunicationRequest * request) = 0; virtual void wait(CommunicationRequest * request) = 0; virtual void waitAll(std::vector<CommunicationRequest *> & requests) = 0; virtual void freeCommunicationRequest(CommunicationRequest * request); virtual void freeCommunicationRequest(std::vector<CommunicationRequest *> & requests); virtual void barrier() = 0; virtual void allReduce(Real * values, Int nb_values, const SynchronizerOperation & op) = 0; virtual void allReduce(UInt * values, Int nb_values, const SynchronizerOperation & op) = 0; virtual void gather(Real * values, Int nb_values, Int root) = 0; virtual void gather(UInt * values, Int nb_values, Int root) = 0; virtual void gather(Int * values, Int nb_values, Int root) = 0; virtual void gatherv(Real * values, Int * nb_values, Int root) = 0; virtual void gatherv(UInt * values, Int * nb_values, Int root) = 0; virtual void gatherv(Int * values, Int * nb_values, Int root) = 0; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: virtual Int getNbProc() const = 0; virtual Int whoAmI() const = 0; static StaticCommunicator * getStaticCommunicator(CommunicatorType type = _communicator_mpi); static StaticCommunicator * getStaticCommunicator(int * argc, char *** argv, CommunicatorType type = _communicator_mpi); static bool isInstantiated() { return is_instantiated; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: static bool is_instantiated; static StaticCommunicator * static_communicator; protected: Int prank; Int psize; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "static_communicator_inline_impl.cc" /* -------------------------------------------------------------------------- */ /* Inline Functions VectorBase */ /* -------------------------------------------------------------------------- */ inline std::ostream & operator<<(std::ostream & stream, const CommunicationRequest & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_STATIC_COMMUNICATOR_HH__ */ diff --git a/synchronizer/static_communicator_dummy.hh b/synchronizer/static_communicator_dummy.hh index c37609c58..885fb1dc7 100644 --- a/synchronizer/static_communicator_dummy.hh +++ b/synchronizer/static_communicator_dummy.hh @@ -1,134 +1,148 @@ /** * @file static_communicator_dummy.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Aug 19 15:34:09 2010 * * @brief Class handling the parallel communications * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_STATIC_COMMUNICATOR_DUMMY_HH__ #define __AKANTU_STATIC_COMMUNICATOR_DUMMY_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class StaticCommunicatorDummy : public StaticCommunicator { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: virtual ~StaticCommunicatorDummy() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void send(__attribute__ ((unused)) UInt * buffer, __attribute__ ((unused)) Int size, __attribute__ ((unused)) Int receiver, __attribute__ ((unused)) Int tag) {}; virtual void send(__attribute__ ((unused)) Real * buffer, __attribute__ ((unused)) Int size, __attribute__ ((unused)) Int receiver, __attribute__ ((unused)) Int tag) {}; virtual void receive(__attribute__ ((unused)) UInt * buffer, __attribute__ ((unused)) Int size, __attribute__ ((unused)) Int sender, __attribute__ ((unused)) Int tag) {}; virtual void receive(__attribute__ ((unused)) Real * buffer, __attribute__ ((unused)) Int size, __attribute__ ((unused)) Int sender, __attribute__ ((unused)) Int tag) {}; virtual CommunicationRequest * asyncSend(__attribute__ ((unused)) UInt * buffer, __attribute__ ((unused)) Int size, __attribute__ ((unused)) Int receiver, __attribute__ ((unused)) Int tag) { return new CommunicationRequest(0, 0); }; virtual CommunicationRequest * asyncSend(__attribute__ ((unused)) Real * buffer, __attribute__ ((unused)) Int size, __attribute__ ((unused)) Int receiver, __attribute__ ((unused)) Int tag) { return new CommunicationRequest(0, 0); }; virtual CommunicationRequest * asyncReceive(__attribute__ ((unused)) UInt * buffer, __attribute__ ((unused)) Int size, __attribute__ ((unused)) Int sender, __attribute__ ((unused)) Int tag) { return new CommunicationRequest(0, 0); }; virtual CommunicationRequest * asyncReceive(__attribute__ ((unused)) Real * buffer, __attribute__ ((unused)) Int size, __attribute__ ((unused)) Int sender, __attribute__ ((unused)) Int tag) { return new CommunicationRequest(0, 0); }; virtual bool testRequest(__attribute__ ((unused)) CommunicationRequest * request) { return true; }; virtual void wait(__attribute__ ((unused)) CommunicationRequest * request) {}; virtual void waitAll(__attribute__ ((unused)) std::vector<CommunicationRequest *> & requests) {}; virtual void barrier() {}; virtual void allReduce(__attribute__ ((unused)) Real * values, __attribute__ ((unused)) Int nb_values, __attribute__ ((unused)) const SynchronizerOperation & op) {}; virtual void allReduce(__attribute__ ((unused)) UInt * values, __attribute__ ((unused)) Int nb_values, __attribute__ ((unused)) const SynchronizerOperation & op) {}; inline void gather(__attribute__ ((unused)) Real * values, __attribute__ ((unused)) Int nb_values, __attribute__ ((unused)) Int root) {}; inline void gather(__attribute__ ((unused)) UInt * values, __attribute__ ((unused)) Int nb_values, __attribute__ ((unused)) Int root) {}; inline void gather(__attribute__ ((unused)) Int * values, __attribute__ ((unused)) Int nb_values, __attribute__ ((unused)) Int root) {}; inline void gatherv(__attribute__ ((unused)) Real * values, __attribute__ ((unused)) Int * nb_values, __attribute__ ((unused)) Int root) {}; inline void gatherv(__attribute__ ((unused)) UInt * values, __attribute__ ((unused)) Int * nb_values, __attribute__ ((unused)) Int root) {}; inline void gatherv(__attribute__ ((unused)) Int * values, __attribute__ ((unused)) Int * nb_values, __attribute__ ((unused)) Int root) {}; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: virtual Int getNbProc() const { return 1; }; virtual Int whoAmI() const { return 0; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ }; __END_AKANTU__ #endif /* __AKANTU_STATIC_COMMUNICATOR_DUMMY_HH__ */ diff --git a/synchronizer/static_communicator_inline_impl.cc b/synchronizer/static_communicator_inline_impl.cc index e38f4da24..0eaa11bbb 100644 --- a/synchronizer/static_communicator_inline_impl.cc +++ b/synchronizer/static_communicator_inline_impl.cc @@ -1,25 +1,39 @@ /** * @file static_communicator_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Sep 6 00:16:19 2010 * * @brief implementation of inline functions * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ inline void StaticCommunicator::freeCommunicationRequest(CommunicationRequest * request) { delete request; } /* -------------------------------------------------------------------------- */ inline void StaticCommunicator::freeCommunicationRequest(std::vector<CommunicationRequest *> & requests) { std::vector<CommunicationRequest *>::iterator it; for(it = requests.begin(); it != requests.end(); ++it) { delete (*it); } } diff --git a/synchronizer/static_communicator_mpi.cc b/synchronizer/static_communicator_mpi.cc index 33f191c2f..19436924c 100644 --- a/synchronizer/static_communicator_mpi.cc +++ b/synchronizer/static_communicator_mpi.cc @@ -1,28 +1,42 @@ /** * @file static_communicator_mpi.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Sep 14 11:37:10 2010 * * @brief * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "static_communicator_mpi.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ MPI_Op StaticCommunicatorMPI::synchronizer_operation_to_mpi_op[_so_null + 1] = { MPI_SUM, MPI_MIN, MPI_MAX, MPI_OP_NULL }; __END_AKANTU__ diff --git a/synchronizer/static_communicator_mpi.hh b/synchronizer/static_communicator_mpi.hh index c64262dea..37fc0a85e 100644 --- a/synchronizer/static_communicator_mpi.hh +++ b/synchronizer/static_communicator_mpi.hh @@ -1,129 +1,143 @@ /** * @file static_communicator_mpi.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Sep 2 19:59:58 2010 * * @brief class handling parallel communication trough MPI * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_STATIC_COMMUNICATOR_MPI_HH__ #define __AKANTU_STATIC_COMMUNICATOR_MPI_HH__ /* -------------------------------------------------------------------------- */ #include <mpi.h> /* -------------------------------------------------------------------------- */ #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ class CommunicationRequestMPI : public CommunicationRequest { public: inline CommunicationRequestMPI(UInt source, UInt dest); inline ~CommunicationRequestMPI(); inline MPI_Request * getMPIRequest() { return request; }; private: MPI_Request * request; }; /* -------------------------------------------------------------------------- */ class StaticCommunicatorMPI : public virtual StaticCommunicator { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: inline StaticCommunicatorMPI(int * argc, char *** argv); inline virtual ~StaticCommunicatorMPI(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: inline void send(UInt * buffer, Int size, Int receiver, Int tag); inline void send(Real * buffer, Int size, Int receiver, Int tag); inline void receive(UInt * buffer, Int size, Int sender, Int tag); inline void receive(Real * buffer, Int size, Int sender, Int tag); inline CommunicationRequest * asyncSend(UInt * buffer, Int size, Int receiver, Int tag); inline CommunicationRequest * asyncSend(Real * buffer, Int size, Int receiver, Int tag); inline CommunicationRequest * asyncReceive(UInt * buffer, Int size, Int sender, Int tag); inline CommunicationRequest * asyncReceive(Real * buffer, Int size, Int sender, Int tag); inline bool testRequest(CommunicationRequest * request); inline void wait(CommunicationRequest * request); inline void waitAll(std::vector<CommunicationRequest *> & requests); inline void barrier(); inline void allReduce(Real * values, Int nb_values, const SynchronizerOperation & op); inline void allReduce(UInt * values, Int nb_values, const SynchronizerOperation & op); inline void gather(Real * values, Int nb_values, Int root) { _gather(values, nb_values, root); }; inline void gather(UInt * values, Int nb_values, Int root) { _gather(values, nb_values, root); }; inline void gather(Int * values, Int nb_values, Int root) { _gather(values, nb_values, root); }; inline void gatherv(Real * values, Int * nb_values, Int root) { _gatherv(values, nb_values, root); }; inline void gatherv(UInt * values, Int * nb_values, Int root) { _gatherv(values, nb_values, root); }; inline void gatherv(Int * values, Int * nb_values, Int root) { _gatherv(values, nb_values, root); }; private: template<typename T> inline MPI_Datatype getMPIDatatype(); template<typename T> inline void _gather(T * values, Int nb_values, Int root); template<typename T> inline void _gatherv(T * values, Int * nb_values, Int root); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: inline void setMPICommunicator(MPI_Comm comm); inline MPI_Comm getMPICommunicator() const; inline Int getNbProc() const { return psize; }; inline Int whoAmI() const { return prank; }; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: MPI_Comm communicator; static MPI_Op synchronizer_operation_to_mpi_op[_so_null + 1]; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "static_communicator_mpi_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_STATIC_COMMUNICATOR_MPI_HH__ */ diff --git a/synchronizer/static_communicator_mpi_inline_impl.cc b/synchronizer/static_communicator_mpi_inline_impl.cc index 5cc5d0a80..541774412 100644 --- a/synchronizer/static_communicator_mpi_inline_impl.cc +++ b/synchronizer/static_communicator_mpi_inline_impl.cc @@ -1,302 +1,316 @@ /** * @file static_communicator_mpi_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Sep 2 15:10:51 2010 * * @brief implementation of the mpi communicator * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ inline CommunicationRequestMPI::CommunicationRequestMPI(UInt source, UInt dest) : CommunicationRequest(source, dest) { request = new MPI_Request; } /* -------------------------------------------------------------------------- */ inline CommunicationRequestMPI::~CommunicationRequestMPI() { delete request; } /* -------------------------------------------------------------------------- */ inline StaticCommunicatorMPI::StaticCommunicatorMPI(int * argc, char *** argv) { MPI_Init(argc, argv); setMPICommunicator(MPI_COMM_WORLD); } /* -------------------------------------------------------------------------- */ inline StaticCommunicatorMPI::~StaticCommunicatorMPI() { MPI_Finalize(); } /* -------------------------------------------------------------------------- */ inline void StaticCommunicatorMPI::setMPICommunicator(MPI_Comm comm) { communicator = comm; MPI_Comm_rank(communicator, &prank); MPI_Comm_size(communicator, &psize); } /* -------------------------------------------------------------------------- */ inline MPI_Comm StaticCommunicatorMPI::getMPICommunicator() const { return communicator; } /* -------------------------------------------------------------------------- */ inline void StaticCommunicatorMPI::send(UInt * buffer, Int size, Int receiver, Int tag) { #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Send(buffer, size, MPI_UNSIGNED, receiver, tag, communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Send."); } /* -------------------------------------------------------------------------- */ inline void StaticCommunicatorMPI::send(Real * buffer, Int size, Int receiver, Int tag) { #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Send(buffer, size, MPI_DOUBLE, receiver, tag, communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Send."); } /* -------------------------------------------------------------------------- */ inline void StaticCommunicatorMPI::receive(UInt * buffer, Int size, Int sender, Int tag) { MPI_Status status; #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Recv(buffer, size, MPI_UNSIGNED, sender, tag, communicator, &status); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Recv."); } /* -------------------------------------------------------------------------- */ inline void StaticCommunicatorMPI::receive(Real * buffer, Int size, Int sender, Int tag) { MPI_Status status; #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Recv(buffer, size, MPI_DOUBLE, sender, tag, communicator, &status); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Recv."); } /* -------------------------------------------------------------------------- */ inline CommunicationRequest * StaticCommunicatorMPI::asyncSend(UInt * buffer, Int size, Int receiver, Int tag) { CommunicationRequestMPI * request = new CommunicationRequestMPI(prank, receiver); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Isend(buffer, size, MPI_UNSIGNED, receiver, tag, communicator, request->getMPIRequest()); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Isend."); return request; } /* -------------------------------------------------------------------------- */ inline CommunicationRequest * StaticCommunicatorMPI::asyncSend(Real * buffer, Int size, Int receiver, Int tag) { CommunicationRequestMPI * request = new CommunicationRequestMPI(prank, receiver); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Isend(buffer, size, MPI_DOUBLE, receiver, tag, communicator, request->getMPIRequest()); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Isend."); return request; } /* -------------------------------------------------------------------------- */ inline CommunicationRequest * StaticCommunicatorMPI::asyncReceive(UInt * buffer, Int size, Int sender, Int tag) { CommunicationRequestMPI * request = new CommunicationRequestMPI(sender, prank); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Irecv(buffer, size, MPI_UNSIGNED, sender, tag, communicator, request->getMPIRequest()); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Irecv."); return request; } /* -------------------------------------------------------------------------- */ inline CommunicationRequest * StaticCommunicatorMPI::asyncReceive(Real * buffer, Int size, Int sender, Int tag) { CommunicationRequestMPI * request = new CommunicationRequestMPI(sender, prank); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Irecv(buffer, size, MPI_DOUBLE, sender, tag, communicator, request->getMPIRequest()); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Irecv."); return request; } /* -------------------------------------------------------------------------- */ inline bool StaticCommunicatorMPI::testRequest(CommunicationRequest * request) { MPI_Status status; int flag; CommunicationRequestMPI * req_mpi = static_cast<CommunicationRequestMPI *>(request); MPI_Request * req = req_mpi->getMPIRequest(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Test(req, &flag, &status); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Test."); return (flag != 0); } /* -------------------------------------------------------------------------- */ inline void StaticCommunicatorMPI::wait(CommunicationRequest * request) { MPI_Status status; CommunicationRequestMPI * req_mpi = static_cast<CommunicationRequestMPI *>(request); MPI_Request * req = req_mpi->getMPIRequest(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Wait(req, &status); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Wait."); } /* -------------------------------------------------------------------------- */ inline void StaticCommunicatorMPI::waitAll(std::vector<CommunicationRequest *> & requests) { MPI_Status status; std::vector<CommunicationRequest *>::iterator it; for(it = requests.begin(); it != requests.end(); ++it) { MPI_Request * req = static_cast<CommunicationRequestMPI *>(*it)->getMPIRequest(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Wait(req, &status); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Wait."); } } /* -------------------------------------------------------------------------- */ inline void StaticCommunicatorMPI::barrier() { MPI_Barrier(communicator); } /* -------------------------------------------------------------------------- */ inline void StaticCommunicatorMPI::allReduce(UInt * values, Int nb_values, const SynchronizerOperation & op) { #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Allreduce(MPI_IN_PLACE, values, nb_values, MPI_UNSIGNED, synchronizer_operation_to_mpi_op[op], communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Allreduce."); } /* -------------------------------------------------------------------------- */ inline void StaticCommunicatorMPI::allReduce(Real * values, Int nb_values, const SynchronizerOperation & op) { #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Allreduce(MPI_IN_PLACE, values, nb_values, MPI_DOUBLE, synchronizer_operation_to_mpi_op[op], communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Allreduce."); } /* -------------------------------------------------------------------------- */ template<typename T> inline void StaticCommunicatorMPI::_gather(T * values, Int nb_values, Int root) { T * send_buf = NULL, * recv_buf = NULL; if(prank == root) { send_buf = (T *) MPI_IN_PLACE; recv_buf = values; } else { send_buf = values; } MPI_Datatype type = getMPIDatatype<T>(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Gather(send_buf, nb_values, type, recv_buf, nb_values, type, root, communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Gather."); } /* -------------------------------------------------------------------------- */ template<typename T> inline void StaticCommunicatorMPI::_gatherv(T * values, Int * nb_values, Int root) { Int * displs = NULL; if(prank == root) { displs = new Int[psize]; displs[0] = 0; for (Int i = 1; i < psize; ++i) { displs[i] = displs[i-1] + nb_values[i-1]; } } T * send_buf = NULL, * recv_buf = NULL; if(prank == root) { send_buf = (T *) MPI_IN_PLACE; recv_buf = values; } else send_buf = values; MPI_Datatype type = getMPIDatatype<T>(); #if !defined(AKANTU_NDEBUG) int ret = #endif MPI_Gatherv(send_buf, *nb_values, type, recv_buf, nb_values, displs, type, root, communicator); AKANTU_DEBUG_ASSERT(ret == MPI_SUCCESS, "Error in MPI_Gather."); if(prank == root) { delete [] displs; } } /* -------------------------------------------------------------------------- */ template<typename T> inline MPI_Datatype StaticCommunicatorMPI::getMPIDatatype() { return MPI_DATATYPE_NULL; } template<> inline MPI_Datatype StaticCommunicatorMPI::getMPIDatatype<Real>() { return MPI_DOUBLE; } template<> inline MPI_Datatype StaticCommunicatorMPI::getMPIDatatype<UInt>() { return MPI_UNSIGNED; } template<> inline MPI_Datatype StaticCommunicatorMPI::getMPIDatatype<Int>() { return MPI_INT; } /* -------------------------------------------------------------------------- */ diff --git a/synchronizer/synchronizer.cc b/synchronizer/synchronizer.cc index fc95c6315..41d9298cc 100644 --- a/synchronizer/synchronizer.cc +++ b/synchronizer/synchronizer.cc @@ -1,35 +1,49 @@ /** * @file synchronizer.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Aug 26 16:31:48 2010 * * @brief implementation of the common part * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "synchronizer.hh" #include "ghost_synchronizer.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Synchronizer::Synchronizer(SynchronizerID id, MemoryID memory_id) : Memory(memory_id), id(id) { } /* -------------------------------------------------------------------------- */ void Synchronizer::registerGhostSynchronizer(const GhostSynchronizer & ghost_synchronizer) { AKANTU_DEBUG_IN(); this->ghost_synchronizer = &ghost_synchronizer; AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/synchronizer/synchronizer.hh b/synchronizer/synchronizer.hh index b28511b48..d5643ad98 100644 --- a/synchronizer/synchronizer.hh +++ b/synchronizer/synchronizer.hh @@ -1,82 +1,96 @@ /** * @file synchronizer.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Aug 23 13:48:37 2010 * * @brief interface for communicator and pbc synchronizers * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SYNCHRONIZER_HH__ #define __AKANTU_SYNCHRONIZER_HH__ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class GhostSynchronizer; } __BEGIN_AKANTU__ class Synchronizer : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Synchronizer(SynchronizerID id = "synchronizer", MemoryID memory_id = 0); virtual ~Synchronizer() { }; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// synchronize ghosts virtual void synchronize(GhostSynchronizationTag tag) = 0; /// asynchronous synchronization of ghosts virtual void asynchronousSynchronize(GhostSynchronizationTag tag) = 0; /// wait end of asynchronous synchronization of ghosts virtual void waitEndSynchronize(GhostSynchronizationTag tag) = 0; virtual void allReduce(Real * values, UInt nb_values, const SynchronizerOperation & op) = 0; /* ------------------------------------------------------------------------ */ /// register a new communication virtual void registerTag(GhostSynchronizationTag tag) = 0; void registerGhostSynchronizer(const GhostSynchronizer & ghost_synchronizer); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the synchronizer SynchronizerID id; /// the associated ghost_synchonizer const GhostSynchronizer * ghost_synchronizer; }; __END_AKANTU__ #endif /* __AKANTU_SYNCHRONIZER_HH__ */ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5cfea2344..73a885d67 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,40 +1,54 @@ #=============================================================================== # @file CMakeLists.txt # @author Nicolas Richart <nicolas.richart@epfl.ch> # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== INCLUDE(${AKANTU_CMAKE_DIR}/AkantuTestAndExamples.cmake) #=============================================================================== # List of tests #=============================================================================== add_akantu_test(test_vector "Test akantu vector") add_akantu_test(test_static_memory "Test static memory") add_akantu_test(test_fem "Test finite element functionalties") add_akantu_test(test_mesh_io "Test mesh io object") add_akantu_test(test_facet_extraction "Test mesh utils facet extraction") add_akantu_test(test_model "Test model objects") add_akantu_test(test_solver "Test solver function") if(AKANTU_BUILD_CONTACT) #add_akantu_test(test_contact_neighbor_structure "Test contact neighbor structure") add_akantu_test(test_surface_extraction "Test mesh utils surface extraction") endif(AKANTU_BUILD_CONTACT) if(AKANTU_SCOTCH_ON) add_akantu_test(test_mesh_partitionate "Test mesh partition creation") endif(AKANTU_SCOTCH_ON) if(AKANTU_MPI_ON) add_akantu_test(test_synchronizer "Test synchronizers") endif(AKANTU_MPI_ON) diff --git a/test/test_facet_extraction/CMakeLists.txt b/test/test_facet_extraction/CMakeLists.txt index 499b56bd3..ad66576fe 100644 --- a/test/test_facet_extraction/CMakeLists.txt +++ b/test/test_facet_extraction/CMakeLists.txt @@ -1,26 +1,40 @@ #=============================================================================== # @file CMakeLists.txt # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_mesh(test_facet_square_mesh square.geo 2 1) register_test(test_facet_extraction_triangle_3 test_facet_extraction_triangle_3.cc) add_dependencies(test_facet_extraction_triangle_3 test_facet_square_mesh) #=============================================================================== add_mesh(test_facet_cube_mesh cube.geo 3 1) register_test(test_facet_extraction_tetrahedron_4 test_facet_extraction_tetrahedron_4.cc) add_dependencies(test_facet_extraction_tetrahedron_4 test_facet_cube_mesh) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) \ No newline at end of file diff --git a/test/test_facet_extraction/test_facet_extraction_tetrahedron_4.cc b/test/test_facet_extraction/test_facet_extraction_tetrahedron_4.cc index 5cf8a5de8..40da397cb 100644 --- a/test/test_facet_extraction/test_facet_extraction_tetrahedron_4.cc +++ b/test/test_facet_extraction/test_facet_extraction_tetrahedron_4.cc @@ -1,73 +1,87 @@ /** * @file test_facet_extraction_tetra1.cc * @author Guillaume ANCIAUX <anciaux@lsmscluster1.epfl.ch> * @date Thu Aug 19 13:05:27 2010 * * @brief test of internal facet extraction * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 3; Mesh mesh(dim); MeshIOMSH mesh_io; mesh_io.read("cube.msh", mesh); MeshUtils::buildFacets(mesh,1,1); #ifdef AKANTU_USE_IOHELPER unsigned int nb_nodes = mesh.getNbNodes(); DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-facet-extraction"); dumper.SetConnectivity((int*)mesh.getConnectivity(_tetrahedron_4).values, TETRA1, mesh.getNbElement(_tetrahedron_4), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); DumperParaview dumper_facet; dumper_facet.SetMode(TEXT); dumper_facet.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-facet-extraction_boundary"); dumper_facet.SetConnectivity((int*)mesh.getConnectivity(_triangle_3).values, TRIANGLE1, mesh.getNbElement(_triangle_3), C_MODE); dumper_facet.SetPrefix("paraview/"); dumper_facet.Init(); dumper_facet.Dump(); dumper_facet.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-facet-extraction_internal"); dumper_facet.SetConnectivity((int*)mesh.getInternalFacetsMesh().getConnectivity(_triangle_3).values, TRIANGLE1, mesh.getInternalFacetsMesh().getNbElement(_triangle_3), C_MODE); dumper_facet.Init(); dumper_facet.Dump(); #endif //AKANTU_USE_IOHELPER return EXIT_SUCCESS; } diff --git a/test/test_facet_extraction/test_facet_extraction_triangle_3.cc b/test/test_facet_extraction/test_facet_extraction_triangle_3.cc index e031d5782..bd7d300c4 100644 --- a/test/test_facet_extraction/test_facet_extraction_triangle_3.cc +++ b/test/test_facet_extraction/test_facet_extraction_triangle_3.cc @@ -1,72 +1,86 @@ /** * @file test_facet_extraction.cc * @author Guillaume ANCIAUX <anciaux@lsmscluster1.epfl.ch> * @date Thu Aug 19 13:05:27 2010 * * @brief test of internal facet extraction * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 2; Mesh mesh(dim); MeshIOMSH mesh_io; mesh_io.read("square.msh", mesh); MeshUtils::buildFacets(mesh,1,1); #ifdef AKANTU_USE_IOHELPER unsigned int nb_nodes = mesh.getNbNodes(); DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-facet-extraction"); dumper.SetConnectivity((int*)mesh.getConnectivity(_triangle_3).values, TRIANGLE1, mesh.getNbElement(_triangle_3), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); DumperParaview dumper_facet; dumper_facet.SetMode(TEXT); dumper_facet.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-facet-extraction_boundary"); dumper_facet.SetConnectivity((int*)mesh.getConnectivity(_segment_2).values, LINE1, mesh.getNbElement(_segment_2), C_MODE); dumper_facet.SetPrefix("paraview/"); dumper_facet.Init(); dumper_facet.Dump(); dumper_facet.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-facet-extraction_internal"); dumper_facet.SetConnectivity((int*)mesh.getInternalFacetsMesh().getConnectivity(_segment_2).values, LINE1, mesh.getInternalFacetsMesh().getNbElement(_segment_2), C_MODE); dumper_facet.Init(); dumper_facet.Dump(); #endif //AKANTU_USE_IOHELPER return EXIT_SUCCESS; } diff --git a/test/test_fem/CMakeLists.txt b/test/test_fem/CMakeLists.txt index dcfbb9c23..cb65fec7d 100644 --- a/test/test_fem/CMakeLists.txt +++ b/test/test_fem/CMakeLists.txt @@ -1,116 +1,130 @@ #=============================================================================== # @file CMakeLists.txt # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== # 1D #=============================================================================== add_mesh(test_fem_line_1_mesh line.geo 1 1 OUTPUT line1.msh) add_mesh(test_fem_line_2_mesh line.geo 1 2 OUTPUT line2.msh) #=============================================================================== # 1st order register_test(test_integrate_segment_2 test_integrate_segment_2.cc) add_dependencies(test_integrate_segment_2 test_fem_line_1_mesh) #=============================================================================== register_test(test_interpolate_segment_2 test_interpolate_segment_2.cc) add_dependencies(test_interpolate_segment_2 test_fem_line_1_mesh) #=============================================================================== register_test(test_gradient_segment_2 test_gradient_segment_2.cc) add_dependencies(test_gradient_segment_2 test_fem_line_1_mesh) #=============================================================================== # 2nd order register_test(test_integrate_segment_3 test_integrate_segment_3.cc) add_dependencies(test_integrate_segment_3 test_fem_line_2_mesh) #=============================================================================== register_test(test_interpolate_segment_3 test_interpolate_segment_3.cc) add_dependencies(test_interpolate_segment_3 test_fem_line_2_mesh) #=============================================================================== register_test(test_gradient_segment_3 test_gradient_segment_3.cc) add_dependencies(test_gradient_segment_3 test_fem_line_2_mesh) #=============================================================================== # 2D #=============================================================================== add_mesh(test_fem_square_1_mesh square.geo 2 1 OUTPUT square1.msh) add_mesh(test_fem_square_2_mesh square.geo 2 2 OUTPUT square2.msh) add_mesh(test_fem_circle_1_mesh circle.geo 2 1 OUTPUT circle1.msh) add_mesh(test_fem_circle_2_mesh circle.geo 2 2 OUTPUT circle2.msh) add_mesh(test_fem_square_struct_1_mesh square_structured.geo 2 1 OUTPUT square_structured1.msh) #=============================================================================== # 1st order unstructured register_test(test_integrate_triangle_3 test_integrate_triangle_3.cc) add_dependencies(test_integrate_triangle_3 test_fem_square_1_mesh test_fem_circle_1_mesh) #=============================================================================== register_test(test_interpolate_triangle_3 test_interpolate_triangle_3.cc) add_dependencies(test_interpolate_triangle_3 test_fem_square_1_mesh) #=============================================================================== register_test(test_gradient_triangle_3 test_gradient_triangle_3.cc) add_dependencies(test_gradient_triangle_3 test_fem_square_1_mesh) #=============================================================================== # 1st order structured register_test(test_integrate_quadrangle_4 test_integrate_quadrangle_4.cc) add_dependencies(test_integrate_quadrangle_4 test_fem_square_1_mesh test_fem_circle_1_mesh) #=============================================================================== register_test(test_interpolate_quadrangle_4 test_interpolate_quadrangle_4.cc) add_dependencies(test_interpolate_quadrangle_4 test_fem_square_struct_1_mesh) #=============================================================================== register_test(test_gradient_quadrangle_4 test_gradient_quadrangle_4.cc) add_dependencies(test_gradient_quadrangle_4 test_fem_square_struct_1_mesh) #=============================================================================== # 2nd order register_test(test_integrate_triangle_6 test_integrate_triangle_6.cc) add_dependencies(test_integrate_triangle_6 test_fem_square_2_mesh test_fem_circle_2_mesh) #=============================================================================== register_test(test_interpolate_triangle_6 test_interpolate_triangle_6.cc) add_dependencies(test_interpolate_triangle_6 test_fem_square_2_mesh) #=============================================================================== register_test(test_gradient_triangle_6 test_gradient_triangle_6.cc) add_dependencies(test_gradient_triangle_6 test_fem_square_2_mesh) #=============================================================================== # 3D #=============================================================================== add_mesh(test_fem_cube_1_mesh cube.geo 3 1 OUTPUT cube1.msh) add_mesh(test_fem_cube_2_mesh cube.geo 3 2 OUTPUT cube2.msh) #=============================================================================== # 1st order register_test(test_integrate_tetrahedron_4 test_integrate_tetrahedron_4.cc) add_dependencies(test_integrate_tetrahedron_4 test_fem_cube_1_mesh) #=============================================================================== register_test(test_interpolate_tetrahedron_4 test_interpolate_tetrahedron_4.cc) add_dependencies(test_interpolate_tetrahedron_4 test_fem_cube_1_mesh) #=============================================================================== register_test(test_gradient_tetrahedron_4 test_gradient_tetrahedron_4.cc) add_dependencies(test_gradient_tetrahedron_4 test_fem_cube_1_mesh) #=============================================================================== # 2nd order register_test(test_integrate_tetrahedron_10 test_integrate_tetrahedron_10.cc) add_dependencies(test_integrate_tetrahedron_10 test_fem_cube_2_mesh) #=============================================================================== register_test(test_interpolate_tetrahedron_10 test_interpolate_tetrahedron_10.cc) add_dependencies(test_interpolate_tetrahedron_10 test_fem_cube_2_mesh) #=============================================================================== register_test(test_gradient_tetrahedron_10 test_gradient_tetrahedron_10.cc) add_dependencies(test_gradient_tetrahedron_10 test_fem_cube_2_mesh) diff --git a/test/test_fem/test_fem.cc b/test/test_fem/test_fem.cc index 36bf032e9..83629b7a5 100644 --- a/test/test_fem/test_fem.cc +++ b/test/test_fem/test_fem.cc @@ -1,86 +1,100 @@ /** * @file test_fem.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { MeshIOMSH mesh_io; Mesh my_mesh(1); mesh_io.read("line1.msh", my_mesh); FEM *fem = new FEM(my_mesh,1,"my_fem"); fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2, "val_on_quad"); Vector<Real> grad_on_quad(0, 2, "grad_on_quad"); Vector<Real> int_val_on_elem(0, 2, "int_val_on_elem"); Vector<Real> val_on_nodes_per_elem(fem->getMesh().getNbElement(_segment_2), 2 * 2,"val_on_nodes_per_elem"); Vector<Real> int_val_on_nodes_per_elem(0, 2 * 2,"int_val_on_nodes_per_elem"); Vector<Real> assemble_val_on_nodes(0, 2,"assemble_val_on_nodes"); const Vector<Real> & shapes = fem->getShapes(_segment_2); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem->interpolateOnQuadraturePoints(const_val, val_on_quad, 2, _segment_2); std::cout << const_val << std::endl; std::cout << val_on_quad << std::endl; fem->gradientOnQuadraturePoints(const_val, grad_on_quad, 2, _segment_2); std::cout << grad_on_quad << std::endl; fem->integrate(val_on_quad, int_val_on_elem, 2, _segment_2); std::cout << int_val_on_elem << std::endl; for (UInt el = 0; el < shapes.getSize(); ++el) { val_on_nodes_per_elem.values[el * 4 + 0] = val_on_quad.values[el * 2 + 0] * shapes.values[el * 2 + 0]; val_on_nodes_per_elem.values[el * 4 + 1] = val_on_quad.values[el * 2 + 1] * shapes.values[el * 2 + 0]; val_on_nodes_per_elem.values[el * 4 + 2] = val_on_quad.values[el * 2 + 0] * shapes.values[el * 2 + 1]; val_on_nodes_per_elem.values[el * 4 + 3] = val_on_quad.values[el * 2 + 1] * shapes.values[el * 2 + 1]; } std::cout << val_on_nodes_per_elem << std::endl; fem->integrate(val_on_nodes_per_elem, int_val_on_nodes_per_elem, 4, _segment_2); std::cout << int_val_on_nodes_per_elem << std::endl; fem->assembleVector(int_val_on_nodes_per_elem, assemble_val_on_nodes, 2, _segment_2); std::cout << assemble_val_on_nodes << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_gradient_XXXX.cc b/test/test_fem/test_gradient_XXXX.cc index 286c8aa42..ff434a0eb 100644 --- a/test/test_fem/test_gradient_XXXX.cc +++ b/test/test_fem/test_gradient_XXXX.cc @@ -1,85 +1,99 @@ /** * @file test_gradient_XXXX.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { ElementType type = XXXX; UInt dim = DIM; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("FILE.msh", my_mesh); FEM fem(my_mesh, dim, "my_fem"); debug::setDebugLevel(dblDump); fem.initShapeFunctions(); std::cout << fem << std::endl; Vector<Real> const_val(fem.getMesh().getNbNodes(), 2, "const_val"); Vector<Real> grad_on_quad(0, 2 * dim, "grad_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem.gradientOnQuadraturePoints(const_val, grad_on_quad, 2, type); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << grad_on_quad << std::endl; // compute gradient of coordinates Vector<Real> grad_coord_on_quad(0, dim * dim, "grad_coord_on_quad"); fem.gradientOnQuadraturePoints(my_mesh.getNodes(), grad_coord_on_quad, my_mesh.getSpatialDimension(), type); my_file << my_mesh.getNodes() << std::endl; my_file << grad_coord_on_quad << std::endl; UInt nb_quads = my_mesh.getNbElement(type) * FEM::getNbQuadraturePoints(type); Real eps = 25 * std::numeric_limits<Real>::epsilon(); std::cout << "Epsilon : " << eps << std::endl; for (UInt q = 0; q < nb_quads; ++q) { for (UInt i = 0; i < dim; ++i) { for (UInt j = 0; j < dim; ++j) { if(!(fabs(grad_coord_on_quad.values[q*dim*dim+ i*dim + j] - (i == j)) <= eps)) { std::cerr << "Error on the quad point " << q << std::endl; for (UInt oi = 0; oi < dim; ++oi) { for (UInt oj = 0; oj < dim; ++oj) { std::cout << fabs(grad_coord_on_quad.values[q*dim*dim + i*dim + j] - (i == j)) << " "; } std::cout << std::endl; } exit(EXIT_FAILURE); } } } } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_gradient_quadrangle_4.cc b/test/test_fem/test_gradient_quadrangle_4.cc index 6a2476171..00014917f 100644 --- a/test/test_fem/test_gradient_quadrangle_4.cc +++ b/test/test_fem/test_gradient_quadrangle_4.cc @@ -1,87 +1,101 @@ /** * @file test_gradient_quadrangle_4.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { ElementType type = _quadrangle_4; UInt dim = 2; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("square_structured1.msh", my_mesh); FEM fem(my_mesh, dim, "my_fem"); debug::setDebugLevel(dblDump); fem.initShapeFunctions(); std::cout << fem << std::endl; Vector<Real> const_val(fem.getMesh().getNbNodes(), 2, "const_val"); Vector<Real> grad_on_quad(0, 2 * dim, "grad_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem.gradientOnQuadraturePoints(const_val, grad_on_quad, 2, type); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << grad_on_quad << std::endl; // compute gradient of coordinates Vector<Real> grad_coord_on_quad(0, dim * dim, "grad_coord_on_quad"); fem.gradientOnQuadraturePoints(my_mesh.getNodes(), grad_coord_on_quad, my_mesh.getSpatialDimension(), type); my_file << my_mesh.getNodes() << std::endl; my_file << grad_coord_on_quad << std::endl; UInt nb_quads = my_mesh.getNbElement(type) * FEM::getNbQuadraturePoints(type); Real eps = 25 * std::numeric_limits<Real>::epsilon(); std::cout << "Epsilon : " << eps << std::endl; for (UInt q = 0; q < nb_quads; ++q) { for (UInt i = 0; i < dim; ++i) { for (UInt j = 0; j < dim; ++j) { if(!(fabs(grad_coord_on_quad.values[q*dim*dim+ i*dim + j] - (i == j)) <= eps)) { std::cerr << "Error on the quad point " << q << std::endl; for (UInt oi = 0; oi < dim; ++oi) { for (UInt oj = 0; oj < dim; ++oj) { std::cout << fabs(grad_coord_on_quad.values[q*dim*dim + i*dim + j] - (i == j)) << " "; } std::cout << std::endl; } exit(EXIT_FAILURE); } } } } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_gradient_segment_2.cc b/test/test_fem/test_gradient_segment_2.cc index 9425a237d..bbfb3054d 100644 --- a/test/test_fem/test_gradient_segment_2.cc +++ b/test/test_fem/test_gradient_segment_2.cc @@ -1,69 +1,83 @@ /** * @file test_gradient_segment_2.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { MeshIOMSH mesh_io; Mesh my_mesh(1); mesh_io.read("line1.msh", my_mesh); FEM *fem = new FEM(my_mesh,1,"my_fem"); debug::setDebugLevel(dblDump); fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> grad_on_quad(0, 2, "grad_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem->gradientOnQuadraturePoints(const_val, grad_on_quad, 2, _segment_2); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << grad_on_quad << std::endl; // interpolate coordinates Vector<Real> grad_coord_on_quad(0, 1, "coord_on_quad"); fem->gradientOnQuadraturePoints(my_mesh.getNodes(), grad_coord_on_quad, my_mesh.getSpatialDimension(), _segment_2); my_file << my_mesh.getNodes() << std::endl; my_file << grad_coord_on_quad << std::endl; // delete fem; // finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_gradient_segment_3.cc b/test/test_fem/test_gradient_segment_3.cc index 0f2b3ee76..eabd22500 100644 --- a/test/test_fem/test_gradient_segment_3.cc +++ b/test/test_fem/test_gradient_segment_3.cc @@ -1,71 +1,85 @@ /** * @file test_gradient_segment_3.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Sun Oct 3 17:04:25 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { ElementType type = _segment_3; UInt dim = 1; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("line2.msh", my_mesh); FEM *fem = new FEM(my_mesh, dim, "my_fem"); debug::setDebugLevel(dblDump); fem->initShapeFunctions(); //UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> grad_on_quad(0, 2 * dim , "grad_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem->gradientOnQuadraturePoints(const_val, grad_on_quad, 2, type); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << grad_on_quad << std::endl; // compute gradient of coordinates Vector<Real> grad_coord_on_quad(0, dim * dim, "grad_coord_on_quad"); fem->gradientOnQuadraturePoints(my_mesh.getNodes(), grad_coord_on_quad, my_mesh.getSpatialDimension(), type); my_file << my_mesh.getNodes() << std::endl; my_file << grad_coord_on_quad << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_gradient_tetrahedron_10.cc b/test/test_fem/test_gradient_tetrahedron_10.cc index 2222d56f6..be9f599c0 100644 --- a/test/test_fem/test_gradient_tetrahedron_10.cc +++ b/test/test_fem/test_gradient_tetrahedron_10.cc @@ -1,84 +1,98 @@ /** * @file test_gradient_tetrahedron_10.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { UInt dim = 3; ElementType type = _tetrahedron_10; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("cube2.msh", my_mesh); FEM fem(my_mesh, dim, "my_fem"); debug::setDebugLevel(dblDump); fem.initShapeFunctions(); std::cout << fem << std::endl; Vector<Real> const_val(fem.getMesh().getNbNodes(), 2, "const_val"); Vector<Real> grad_on_quad(0, 2 * dim, "grad_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem.gradientOnQuadraturePoints(const_val, grad_on_quad, 2, type); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << grad_on_quad << std::endl; // compute gradient of coordinates Vector<Real> grad_coord_on_quad(0, 9, "grad_coord_on_quad"); fem.gradientOnQuadraturePoints(my_mesh.getNodes(), grad_coord_on_quad, my_mesh.getSpatialDimension(), type); my_file << my_mesh.getNodes() << std::endl; my_file << grad_coord_on_quad << std::endl; UInt nb_quads = my_mesh.getNbElement(type) * FEM::getNbQuadraturePoints(type); Real eps = 30 * std::numeric_limits<Real>::epsilon(); std::cout << "Epsilon : " << eps << std::endl; for (UInt q = 0; q < nb_quads; ++q) { for (UInt i = 0; i < dim; ++i) { for (UInt j = 0; j < dim; ++j) { if(!(fabs(grad_coord_on_quad.values[q*dim*dim+ i*dim + j] - (i == j)) <= eps)) { std::cerr << "Error on the quad point " << q << std::endl; for (UInt oi = 0; oi < dim; ++oi) { for (UInt oj = 0; oj < dim; ++oj) { std::cout << fabs(grad_coord_on_quad.values[q*dim*dim + i*dim + j] - (i == j)) << " "; } std::cout << std::endl; } exit(EXIT_FAILURE); } } } } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_gradient_tetrahedron_4.cc b/test/test_fem/test_gradient_tetrahedron_4.cc index 303f8a1a8..0278318d1 100644 --- a/test/test_fem/test_gradient_tetrahedron_4.cc +++ b/test/test_fem/test_gradient_tetrahedron_4.cc @@ -1,68 +1,82 @@ /** * @file test_gradient_tetrahedron_4.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { UInt dim = 3; ElementType type = _tetrahedron_4; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("cube1.msh", my_mesh); FEM *fem = new FEM(my_mesh, dim, "my_fem"); debug::setDebugLevel(dblDump); fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> grad_on_quad(0, 2 * dim, "grad_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem->gradientOnQuadraturePoints(const_val, grad_on_quad, 2, type); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << grad_on_quad << std::endl; // compute gradient of coordinates Vector<Real> grad_coord_on_quad(0, 9, "grad_coord_on_quad"); fem->gradientOnQuadraturePoints(my_mesh.getNodes(), grad_coord_on_quad, my_mesh.getSpatialDimension(), type); my_file << my_mesh.getNodes() << std::endl; my_file << grad_coord_on_quad << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_gradient_triangle_3.cc b/test/test_fem/test_gradient_triangle_3.cc index f34686f28..9383bd8eb 100644 --- a/test/test_fem/test_gradient_triangle_3.cc +++ b/test/test_fem/test_gradient_triangle_3.cc @@ -1,69 +1,83 @@ /** * @file test_gradient_triangle_3.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { MeshIOMSH mesh_io; Mesh my_mesh(2); mesh_io.read("square1.msh", my_mesh); FEM *fem = new FEM(my_mesh,2,"my_fem"); debug::setDebugLevel(dblDump); fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> grad_on_quad(0, 2*2, "grad_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem->gradientOnQuadraturePoints(const_val, grad_on_quad, 2, _triangle_3); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << grad_on_quad << std::endl; // compute gradient of coordinates Vector<Real> grad_coord_on_quad(0, 4, "grad_coord_on_quad"); fem->gradientOnQuadraturePoints(my_mesh.getNodes(), grad_coord_on_quad, my_mesh.getSpatialDimension(), _triangle_3); my_file << my_mesh.getNodes() << std::endl; my_file << grad_coord_on_quad << std::endl; // delete fem; // finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_gradient_triangle_6.cc b/test/test_fem/test_gradient_triangle_6.cc index bf7db8dba..5704fd6d5 100644 --- a/test/test_fem/test_gradient_triangle_6.cc +++ b/test/test_fem/test_gradient_triangle_6.cc @@ -1,71 +1,85 @@ /** * @file test_gradient_triangle_6.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { ElementType type = _triangle_6; UInt dim = 2; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("square2.msh", my_mesh); FEM *fem = new FEM(my_mesh, dim, "my_fem"); debug::setDebugLevel(dblDump); fem->initShapeFunctions(); //UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> grad_on_quad(0, 2 * dim, "grad_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem->gradientOnQuadraturePoints(const_val, grad_on_quad, 2, type); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << grad_on_quad << std::endl; // compute gradient of coordinates Vector<Real> grad_coord_on_quad(0, dim * dim, "grad_coord_on_quad"); fem->gradientOnQuadraturePoints(my_mesh.getNodes(), grad_coord_on_quad, my_mesh.getSpatialDimension(), type); my_file << my_mesh.getNodes() << std::endl; my_file << grad_coord_on_quad << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_integrate_XXXX.cc b/test/test_fem/test_integrate_XXXX.cc index 56a2e8f4a..97ee53e5b 100644 --- a/test/test_fem/test_integrate_XXXX.cc +++ b/test/test_fem/test_integrate_XXXX.cc @@ -1,87 +1,101 @@ /** * @file test_integrate_XXXX.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { ElementType type = TYPE; UInt dim = DIM; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("XXXX.msh", my_mesh); FEM fem(my_mesh, dim, "my_fem"); debug::_debug_level = dblDump; fem.initShapeFunctions(); std::cout << fem << std::endl; Vector<Real> const_val(fem.getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2 , "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } //interpolate function on quadrature points fem.interpolateOnQuadraturePoints(const_val, val_on_quad, 2, type); //integrate function on elements akantu::Vector<akantu::Real> int_val_on_elem(0, 2, "int_val_on_elem"); fem.integrate(val_on_quad, int_val_on_elem, 2, type); // get global integration value Real value[2] = {0,0}; std::ofstream my_file("out.txt"); my_file << val_on_quad << std::endl << int_val_on_elem << std::endl; for (UInt i = 0; i < fem.getMesh().getNbElement(type); ++i) { value[0] += int_val_on_elem.values[2*i]; value[1] += int_val_on_elem.values[2*i+1]; } my_file << "integral is " << value[0] << " " << value[1] << std::endl; FEM fem_boundary(my_mesh, dim-1, "my_fem_boundary"); fem_boundary.initShapeFunctions(); ElementType bound_type = Mesh::getFacetElementType(type); UInt nb_boundary_quad = FEM::getNbQuadraturePoints(bound_type); Vector<Real> val_on_bquad(0, nb_boundary_quad, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_integrate_quadrangle_4.cc b/test/test_fem/test_integrate_quadrangle_4.cc index 54a53950f..33c30504c 100644 --- a/test/test_fem/test_integrate_quadrangle_4.cc +++ b/test/test_fem/test_integrate_quadrangle_4.cc @@ -1,85 +1,99 @@ /** * @file test_integrate_quadrangle_4.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { ElementType type = _quadrangle_4; UInt dim = 2; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("square_structured1.msh", my_mesh); FEM fem(my_mesh, dim, "my_fem"); debug::_debug_level = dblDump; fem.initShapeFunctions(); std::cout << fem << std::endl; Vector<Real> const_val(fem.getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2 , "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } //interpolate function on quadrature points fem.interpolateOnQuadraturePoints(const_val, val_on_quad, 2, type); //integrate function on elements akantu::Vector<akantu::Real> int_val_on_elem(0, 2, "int_val_on_elem"); fem.integrate(val_on_quad, int_val_on_elem, 2, type); // get global integration value Real value[2] = {0,0}; std::ofstream my_file("out.txt"); my_file << val_on_quad << std::endl << int_val_on_elem << std::endl; for (UInt i = 0; i < fem.getMesh().getNbElement(type); ++i) { value[0] += int_val_on_elem.values[2*i]; value[1] += int_val_on_elem.values[2*i+1]; } my_file << "integral is " << value[0] << " " << value[1] << std::endl; FEM fem_boundary(my_mesh, dim-1, "my_fem_boundary"); fem_boundary.initShapeFunctions(); ElementType bound_type = Mesh::getFacetElementType(type); UInt nb_boundary_quad = FEM::getNbQuadraturePoints(bound_type); Vector<Real> val_on_bquad(0, nb_boundary_quad, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; } finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_integrate_segment_2.cc b/test/test_fem/test_integrate_segment_2.cc index 163c79536..41358f45d 100644 --- a/test/test_fem/test_integrate_segment_2.cc +++ b/test/test_fem/test_integrate_segment_2.cc @@ -1,73 +1,87 @@ /** * @file test_integrate_segment_2.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { MeshIOMSH mesh_io; Mesh my_mesh(1); mesh_io.read("line1.msh", my_mesh); FEM *fem = new FEM(my_mesh,1,"my_fem"); debug::_debug_level = dblDump; fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } //interpolate function on quadrature points fem->interpolateOnQuadraturePoints(const_val, val_on_quad, 2, _segment_2); //integrate function on elements akantu::Vector<akantu::Real> int_val_on_elem(0, 2, "int_val_on_elem"); fem->integrate(val_on_quad,int_val_on_elem,2,_segment_2); // get global integration value Real value[2] = {0,0}; std::ofstream my_file("out.txt"); my_file << int_val_on_elem << std::endl; for (UInt i = 0; i < fem->getMesh().getNbElement(_segment_2); ++i) { value[0] += int_val_on_elem.values[2*i]; value[1] += int_val_on_elem.values[2*i+1]; } my_file << "integral is " << value[0] << " " << value[1] << std::endl; // delete fem; // finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_integrate_segment_3.cc b/test/test_fem/test_integrate_segment_3.cc index 4ca7384d6..4cd365a40 100644 --- a/test/test_fem/test_integrate_segment_3.cc +++ b/test/test_fem/test_integrate_segment_3.cc @@ -1,77 +1,91 @@ /** * @file test_integrate_segment_3.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @date Sun Oct 3 16:59:26 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { ElementType type = _segment_3; UInt dim = 1; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("line2.msh", my_mesh); FEM *fem = new FEM(my_mesh, dim, "my_fem"); debug::_debug_level = dblDump; fem->initShapeFunctions(); //UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2 , "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } //interpolate function on quadrature points fem->interpolateOnQuadraturePoints(const_val, val_on_quad, 2, type); //integrate function on elements akantu::Vector<akantu::Real> int_val_on_elem(0, 2, "int_val_on_elem"); fem->integrate(val_on_quad, int_val_on_elem, 2, type); // get global integration value Real value[2] = {0,0}; std::ofstream my_file("out.txt"); my_file << int_val_on_elem << std::endl; for (UInt i = 0; i < fem->getMesh().getNbElement(type); ++i) { value[0] += int_val_on_elem.values[2*i]; value[1] += int_val_on_elem.values[2*i+1]; } my_file << "integral is " << value[0] << " " << value[1] << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_integrate_tetrahedron_10.cc b/test/test_fem/test_integrate_tetrahedron_10.cc index 9777caef7..347f51bd1 100644 --- a/test/test_fem/test_integrate_tetrahedron_10.cc +++ b/test/test_fem/test_integrate_tetrahedron_10.cc @@ -1,72 +1,86 @@ /** * @file test_integrate_tetrahedron_10.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { UInt dim = 3; ElementType type = _tetrahedron_10; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("cube2.msh", my_mesh); FEM *fem = new FEM(my_mesh, dim, "my_fem"); debug::_debug_level = dblDump; fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } //interpolate function on quadrature points fem->interpolateOnQuadraturePoints(const_val, val_on_quad, 2, type); //integrate function on elements akantu::Vector<akantu::Real> int_val_on_elem(0, 2, "int_val_on_elem"); fem->integrate(val_on_quad, int_val_on_elem, 2, type); // get global integration value Real value[2] = {0,0}; std::ofstream my_file("out.txt"); my_file << int_val_on_elem << std::endl; for (UInt i = 0; i < fem->getMesh().getNbElement(type); ++i) { value[0] += int_val_on_elem.values[2*i]; value[1] += int_val_on_elem.values[2*i+1]; } my_file << "integral is " << value[0] << " " << value[1] << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_integrate_tetrahedron_4.cc b/test/test_fem/test_integrate_tetrahedron_4.cc index 67b2c2906..f49772def 100644 --- a/test/test_fem/test_integrate_tetrahedron_4.cc +++ b/test/test_fem/test_integrate_tetrahedron_4.cc @@ -1,72 +1,86 @@ /** * @file test_integrate_tetrahedron_4.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { UInt dim = 3; ElementType type = _tetrahedron_4; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("cube1.msh", my_mesh); FEM *fem = new FEM(my_mesh, dim, "my_fem"); debug::_debug_level = dblDump; fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } //interpolate function on quadrature points fem->interpolateOnQuadraturePoints(const_val, val_on_quad, 2, type); //integrate function on elements akantu::Vector<akantu::Real> int_val_on_elem(0, 2, "int_val_on_elem"); fem->integrate(val_on_quad, int_val_on_elem, 2, type); // get global integration value Real value[2] = {0,0}; std::ofstream my_file("out.txt"); my_file << int_val_on_elem << std::endl; for (UInt i = 0; i < fem->getMesh().getNbElement(type); ++i) { value[0] += int_val_on_elem.values[2*i]; value[1] += int_val_on_elem.values[2*i+1]; } my_file << "integral is " << value[0] << " " << value[1] << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_integrate_triangle_3.cc b/test/test_fem/test_integrate_triangle_3.cc index 912adc062..d896819bf 100644 --- a/test/test_fem/test_integrate_triangle_3.cc +++ b/test/test_fem/test_integrate_triangle_3.cc @@ -1,70 +1,84 @@ /** * @file test_integrate_triangle_3.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { MeshIOMSH mesh_io; Mesh my_mesh(2); mesh_io.read("square1.msh", my_mesh); FEM *fem = new FEM(my_mesh,2,"my_fem"); debug::_debug_level = dblDump; fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } //interpolate function on quadrature points fem->interpolateOnQuadraturePoints(const_val, val_on_quad, 2, _triangle_3); //integrate function on elements akantu::Vector<akantu::Real> int_val_on_elem(0, 2, "int_val_on_elem"); fem->integrate(val_on_quad,int_val_on_elem,2,_triangle_3); // get global integration value Real value[2] = {0,0}; std::ofstream my_file("out.txt"); my_file << int_val_on_elem << std::endl; for (UInt i = 0; i < fem->getMesh().getNbElement(_triangle_3); ++i) { value[0] += int_val_on_elem.values[2*i]; value[1] += int_val_on_elem.values[2*i+1]; } my_file << "integral is " << value[0] << " " << value[1] << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_integrate_triangle_6.cc b/test/test_fem/test_integrate_triangle_6.cc index a4f8d9194..29f9d44f3 100644 --- a/test/test_fem/test_integrate_triangle_6.cc +++ b/test/test_fem/test_integrate_triangle_6.cc @@ -1,91 +1,105 @@ /** * @file test_integrate_triangle_6.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { ElementType type = _triangle_6; UInt dim = 2; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("square2.msh", my_mesh); //mesh_io.read("circle2.msh", my_mesh); FEM *fem = new FEM(my_mesh, dim, "my_fem"); debug::_debug_level = dblDump; fem->initShapeFunctions(); //UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2 , "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } //interpolate function on quadrature points fem->interpolateOnQuadraturePoints(const_val, val_on_quad, 2, type); //integrate function on elements akantu::Vector<akantu::Real> int_val_on_elem(0, 2, "int_val_on_elem"); fem->integrate(val_on_quad, int_val_on_elem, 2, type); // get global integration value Real value[2] = {0,0}; std::ofstream my_file("out.txt"); my_file << val_on_quad << std::endl << int_val_on_elem << std::endl; for (UInt i = 0; i < fem->getMesh().getNbElement(type); ++i) { value[0] += int_val_on_elem.values[2*i]; value[1] += int_val_on_elem.values[2*i+1]; } my_file << "integral is " << value[0] << " " << value[1] << std::endl; FEM * fem_boundary = new FEM(my_mesh, dim-1, "my_fem_boundary"); fem_boundary->initShapeFunctions(); //UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(_segment_3); UInt nb_boundary_quad = FEM::getNbQuadraturePoints(_segment_3); Vector<Real> val_on_bquad(0, nb_boundary_quad, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; } delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_interpolate_XXXX.cc b/test/test_fem/test_interpolate_XXXX.cc index 0d24955fc..60e3bfcbf 100644 --- a/test/test_fem/test_interpolate_XXXX.cc +++ b/test/test_fem/test_interpolate_XXXX.cc @@ -1,71 +1,85 @@ /** * @file test_interpolate_XXXX.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { ElementType type = XXXX; UInt dim = DIM; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("XXXX.msh", my_mesh); FEM fem(my_mesh, dim, "my_fem"); //UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); debug::setDebugLevel(dblDump); fem.initShapeFunctions(); std::cout << fem << std::endl; Vector<Real> const_val(fem.getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem.interpolateOnQuadraturePoints(const_val, val_on_quad, 2, type); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << val_on_quad << std::endl; // interpolate coordinates Vector<Real> coord_on_quad(0, my_mesh.getSpatialDimension(), "coord_on_quad"); fem.interpolateOnQuadraturePoints(my_mesh.getNodes(), coord_on_quad, my_mesh.getSpatialDimension(), type); my_file << my_mesh.getNodes() << std::endl; my_file << coord_on_quad << std::endl; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_interpolate_quadrangle_4.cc b/test/test_fem/test_interpolate_quadrangle_4.cc index 2cccf5621..70592287a 100644 --- a/test/test_fem/test_interpolate_quadrangle_4.cc +++ b/test/test_fem/test_interpolate_quadrangle_4.cc @@ -1,71 +1,85 @@ /** * @file test_interpolate_quadrangle_4.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { ElementType type = _quadrangle_4; UInt dim = 2; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("square_structured1.msh", my_mesh); FEM fem(my_mesh, dim, "my_fem"); //UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); debug::setDebugLevel(dblDump); fem.initShapeFunctions(); std::cout << fem << std::endl; Vector<Real> const_val(fem.getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem.interpolateOnQuadraturePoints(const_val, val_on_quad, 2, type); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << val_on_quad << std::endl; // interpolate coordinates Vector<Real> coord_on_quad(0, my_mesh.getSpatialDimension(), "coord_on_quad"); fem.interpolateOnQuadraturePoints(my_mesh.getNodes(), coord_on_quad, my_mesh.getSpatialDimension(), type); my_file << my_mesh.getNodes() << std::endl; my_file << coord_on_quad << std::endl; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_interpolate_segment_2.cc b/test/test_fem/test_interpolate_segment_2.cc index 58714581f..c1470746c 100644 --- a/test/test_fem/test_interpolate_segment_2.cc +++ b/test/test_fem/test_interpolate_segment_2.cc @@ -1,69 +1,83 @@ /** * @file test_interpolate_segment_2.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { MeshIOMSH mesh_io; Mesh my_mesh(1); mesh_io.read("line1.msh", my_mesh); FEM *fem = new FEM(my_mesh,1,"my_fem"); debug::setDebugLevel(dblDump); fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem->interpolateOnQuadraturePoints(const_val, val_on_quad, 2, _segment_2); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << val_on_quad << std::endl; // interpolate coordinates Vector<Real> coord_on_quad(0, 1, "coord_on_quad"); fem->interpolateOnQuadraturePoints(my_mesh.getNodes(), coord_on_quad, my_mesh.getSpatialDimension(), _segment_2); my_file << my_mesh.getNodes() << std::endl; my_file << coord_on_quad << std::endl; // delete fem; // finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_interpolate_segment_3.cc b/test/test_fem/test_interpolate_segment_3.cc index 41facbb80..7dc0166bc 100644 --- a/test/test_fem/test_interpolate_segment_3.cc +++ b/test/test_fem/test_interpolate_segment_3.cc @@ -1,79 +1,93 @@ /** * @file test_interpolate_segment_3.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Sun Oct 3 16:53:59 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { ElementType type = _segment_3; UInt dim = 1; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("line2.msh", my_mesh); FEM *fem = new FEM(my_mesh, dim, "my_fem"); //UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); debug::setDebugLevel(dblDump); fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2 , "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem->interpolateOnQuadraturePoints(const_val, val_on_quad, 2, type); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << val_on_quad << std::endl; // interpolate coordinates Vector<Real> coord_on_quad(0, my_mesh.getSpatialDimension() , "coord_on_quad"); fem->interpolateOnQuadraturePoints(my_mesh.getNodes(), coord_on_quad, my_mesh.getSpatialDimension(), type); my_file << my_mesh.getNodes() << std::endl; my_file << coord_on_quad << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_interpolate_tetrahedron_10.cc b/test/test_fem/test_interpolate_tetrahedron_10.cc index 3c77faec6..e8125b0ab 100644 --- a/test/test_fem/test_interpolate_tetrahedron_10.cc +++ b/test/test_fem/test_interpolate_tetrahedron_10.cc @@ -1,69 +1,83 @@ /** * @file test_interpolate_tetrahedron_10.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { UInt dim = 3; ElementType type = _tetrahedron_10; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("cube2.msh", my_mesh); FEM *fem = new FEM(my_mesh, dim, "my_fem"); debug::setDebugLevel(dblDump); fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), dim, "const_val"); Vector<Real> val_on_quad(0, dim, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { for (UInt j = 0; j < dim; ++j) { const_val.values[i * dim + j] = j; } } fem->interpolateOnQuadraturePoints(const_val, val_on_quad, dim, type); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << val_on_quad << std::endl; // interpolate coordinates Vector<Real> coord_on_quad(0, my_mesh.getSpatialDimension(), "coord_on_quad"); fem->interpolateOnQuadraturePoints(my_mesh.getNodes(), coord_on_quad, my_mesh.getSpatialDimension(), type); my_file << my_mesh.getNodes() << std::endl; my_file << coord_on_quad << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_interpolate_tetrahedron_4.cc b/test/test_fem/test_interpolate_tetrahedron_4.cc index de177cda1..072f52eff 100644 --- a/test/test_fem/test_interpolate_tetrahedron_4.cc +++ b/test/test_fem/test_interpolate_tetrahedron_4.cc @@ -1,68 +1,82 @@ /** * @file test_interpolate_tetrahedron_4.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { UInt dim = 3; ElementType type = _tetrahedron_4; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("cube1.msh", my_mesh); FEM *fem = new FEM(my_mesh, dim, "my_fem"); debug::setDebugLevel(dblDump); fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem->interpolateOnQuadraturePoints(const_val, val_on_quad, 2, type); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << val_on_quad << std::endl; // interpolate coordinates Vector<Real> coord_on_quad(0, my_mesh.getSpatialDimension(), "coord_on_quad"); fem->interpolateOnQuadraturePoints(my_mesh.getNodes(), coord_on_quad, my_mesh.getSpatialDimension(), type); my_file << my_mesh.getNodes() << std::endl; my_file << coord_on_quad << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_interpolate_triangle_3.cc b/test/test_fem/test_interpolate_triangle_3.cc index dce21a8cc..5307ee5e4 100644 --- a/test/test_fem/test_interpolate_triangle_3.cc +++ b/test/test_fem/test_interpolate_triangle_3.cc @@ -1,63 +1,77 @@ /** * @file test_interpolate_triangle_3.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { MeshIOMSH mesh_io; Mesh my_mesh(2); mesh_io.read("square1.msh", my_mesh); FEM *fem = new FEM(my_mesh,2,"my_fem"); debug::setDebugLevel(dblDump); fem->initShapeFunctions(); std::cout << *fem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem->interpolateOnQuadraturePoints(const_val, val_on_quad, 2, _triangle_3); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << val_on_quad << std::endl; // interpolate coordinates Vector<Real> coord_on_quad(0, my_mesh.getSpatialDimension(), "coord_on_quad"); fem->interpolateOnQuadraturePoints(my_mesh.getNodes(), coord_on_quad, my_mesh.getSpatialDimension(), _triangle_3); my_file << my_mesh.getNodes() << std::endl; my_file << coord_on_quad << std::endl; delete fem; // finalize(); return EXIT_SUCCESS; } diff --git a/test/test_fem/test_interpolate_triangle_6.cc b/test/test_fem/test_interpolate_triangle_6.cc index bf790a1f5..4fad7847f 100644 --- a/test/test_fem/test_interpolate_triangle_6.cc +++ b/test/test_fem/test_interpolate_triangle_6.cc @@ -1,77 +1,91 @@ /** * @file test_interpolate_triangle_6.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Mon Jul 19 10:55:49 2010 * * @brief test of the fem class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "fem.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; int main(int argc, char *argv[]) { ElementType type = _triangle_6; UInt dim = 2; MeshIOMSH mesh_io; Mesh my_mesh(dim); mesh_io.read("square2.msh", my_mesh); FEM *fem = new FEM(my_mesh, dim, "my_fem"); //UInt nb_quadrature_points = FEM::getNbQuadraturePoints(type); debug::setDebugLevel(dblDump); fem->initShapeFunctions(); std::cout << *fem << std::endl; StaticMemory * st_mem = StaticMemory::getStaticMemory(); std::cout << *st_mem << std::endl; Vector<Real> const_val(fem->getMesh().getNbNodes(), 2, "const_val"); Vector<Real> val_on_quad(0, 2, "val_on_quad"); for (UInt i = 0; i < const_val.getSize(); ++i) { const_val.values[i * 2 + 0] = 1.; const_val.values[i * 2 + 1] = 2.; } fem->interpolateOnQuadraturePoints(const_val, val_on_quad, 2, type); std::ofstream my_file("out.txt"); my_file << const_val << std::endl; my_file << val_on_quad << std::endl; // interpolate coordinates Vector<Real> coord_on_quad(0, my_mesh.getSpatialDimension(), "coord_on_quad"); fem->interpolateOnQuadraturePoints(my_mesh.getNodes(), coord_on_quad, my_mesh.getSpatialDimension(), type); my_file << my_mesh.getNodes() << std::endl; my_file << coord_on_quad << std::endl; delete fem; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_mesh_io/CMakeLists.txt b/test/test_mesh_io/CMakeLists.txt index 6fe37afaa..c55b62e6c 100644 --- a/test/test_mesh_io/CMakeLists.txt +++ b/test/test_mesh_io/CMakeLists.txt @@ -1,17 +1,31 @@ #=============================================================================== # @file CMakeLists.txt # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== add_mesh(test_mesh_io_mesh cube.geo 3 1) register_test(test_mesh_io_msh test_mesh_io_msh.cc) add_dependencies(test_mesh_io_msh test_mesh_io_mesh) \ No newline at end of file diff --git a/test/test_mesh_io/test_mesh_io_msh.cc b/test/test_mesh_io/test_mesh_io_msh.cc index 57886f9ad..dd09be295 100644 --- a/test/test_mesh_io/test_mesh_io_msh.cc +++ b/test/test_mesh_io/test_mesh_io_msh.cc @@ -1,34 +1,48 @@ /** * @file test_mesh_io_msh.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Wed Jul 14 14:27:11 2010 * * @brief unit test for the MeshIOMSH class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> /* -------------------------------------------------------------------------- */ #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::MeshIOMSH mesh_io; akantu::Mesh mesh(3); mesh_io.read("./cube.msh", mesh); std::cout << mesh << std::endl; return EXIT_SUCCESS; } diff --git a/test/test_mesh_partitionate/CMakeLists.txt b/test/test_mesh_partitionate/CMakeLists.txt index e37e77161..190460f83 100644 --- a/test/test_mesh_partitionate/CMakeLists.txt +++ b/test/test_mesh_partitionate/CMakeLists.txt @@ -1,20 +1,34 @@ #=============================================================================== # @file CMakeLists.txt # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== add_mesh(test_mesh_partitionate_mesh triangle.geo 2 2) register_test(test_mesh_partitionate_scotch test_mesh_partitionate_scotch.cc) add_dependencies(test_mesh_partitionate_scotch test_mesh_partitionate_mesh) \ No newline at end of file diff --git a/test/test_mesh_partitionate/test_mesh_partitionate_scotch.cc b/test/test_mesh_partitionate/test_mesh_partitionate_scotch.cc index 5d1dda1e6..6caca38c3 100644 --- a/test/test_mesh_partitionate/test_mesh_partitionate_scotch.cc +++ b/test/test_mesh_partitionate/test_mesh_partitionate_scotch.cc @@ -1,81 +1,95 @@ /** * @file test_mesh_partitionate_scotch.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Aug 19 13:05:27 2010 * * @brief test of internal facet extraction * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "fem.hh" #include "mesh_io_msh.hh" #include "mesh_partition_scotch.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER /* -------------------------------------------------------------------------- */ /* Main */ /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); akantu::debug::setDebugLevel(akantu::dblDump); int dim = 2; #ifdef AKANTU_USE_IOHELPER akantu::ElementType type = akantu::_triangle_6; #endif //AKANTU_USE_IOHELPER akantu::Mesh mesh(dim); akantu::MeshIOMSH mesh_io; mesh_io.read("triangle.msh", mesh); akantu::MeshPartition * partition = new akantu::MeshPartitionScotch(mesh, dim); partition->partitionate(8); #ifdef AKANTU_USE_IOHELPER unsigned int nb_nodes = mesh.getNbNodes(); unsigned int nb_element = mesh.getNbElement(type); DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-scotch-partition"); dumper.SetConnectivity((int*) mesh.getConnectivity(type).values, TRIANGLE2, nb_element, C_MODE); akantu::UInt nb_quadrature_points = akantu::FEM::getNbQuadraturePoints(type); double * part = new double[nb_element*nb_quadrature_points]; akantu::UInt * part_val = partition->getPartition(type).values; for (unsigned int i = 0; i < nb_element; ++i) for (unsigned int q = 0; q < nb_quadrature_points; ++q) part[i*nb_quadrature_points + q] = part_val[i]; dumper.AddElemDataField(part, 1, "partitions"); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); delete [] part; #endif //AKANTU_USE_IOHELPER partition->reorder(); delete partition; akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/CMakeLists.txt b/test/test_model/CMakeLists.txt index 5738aa6fa..7a818f306 100644 --- a/test/test_model/CMakeLists.txt +++ b/test/test_model/CMakeLists.txt @@ -1,16 +1,30 @@ #=============================================================================== # @file CMakeLists.txt # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_subdirectory(test_solid_mechanics_model) diff --git a/test/test_model/test_solid_mechanics_model/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/CMakeLists.txt index 02ea423fa..a623a6344 100644 --- a/test/test_model/test_solid_mechanics_model/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/CMakeLists.txt @@ -1,93 +1,107 @@ #=============================================================================== # @file CMakeLists.txt # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== add_subdirectory("test_materials") if(AKANTU_BUILD_CONTACT) add_subdirectory("test_contact") endif(AKANTU_BUILD_CONTACT) #=============================================================================== add_mesh(test_solid_mechanics_model_square_mesh square.geo 2 1) add_mesh(test_solid_mechanics_model_circle_mesh1 circle.geo 2 1 OUTPUT circle1.msh) add_mesh(test_solid_mechanics_model_circle_mesh2 circle.geo 2 2 OUTPUT circle2.msh) register_test(test_solid_mechanics_model_square test_solid_mechanics_model_square.cc) add_dependencies(test_solid_mechanics_model_square test_solid_mechanics_model_square_mesh ) register_test(test_solid_mechanics_model_circle_2 test_solid_mechanics_model_circle_2.cc) add_dependencies(test_solid_mechanics_model_circle_2 test_solid_mechanics_model_circle_mesh2) #=============================================================================== add_mesh(test_bar_traction_2d_mesh1 bar.geo 2 1 OUTPUT bar1.msh) add_mesh(test_bar_traction_2d_mesh2 bar.geo 2 2 OUTPUT bar2.msh) add_mesh(test_bar_traction_2d_mesh_structured1 bar_structured.geo 2 1 OUTPUT bar_structured1.msh) register_test(test_solid_mechanics_model_bar_traction2d test_solid_mechanics_model_bar_traction2d.cc) add_dependencies(test_solid_mechanics_model_bar_traction2d test_bar_traction_2d_mesh1 test_bar_traction_2d_mesh2) register_test(test_solid_mechanics_model_bar_traction2d_structured test_solid_mechanics_model_bar_traction2d_structured.cc) add_dependencies(test_solid_mechanics_model_bar_traction2d_structured test_bar_traction_2d_mesh_structured1) if(AKANTU_SCOTCH_ON AND AKANTU_MPI_ON) register_test(test_solid_mechanics_model_bar_traction2d_parallel test_solid_mechanics_model_bar_traction2d_parallel.cc) add_dependencies(test_solid_mechanics_model_bar_traction2d_parallel test_bar_traction_2d_mesh2) add_mesh(test_solid_mechanics_model_segment_mesh segment.geo 1 2) register_test(test_solid_mechanics_model_segment_parallel test_solid_mechanics_model_segment_parallel.cc) add_dependencies(test_solid_mechanics_model_segment_parallel test_solid_mechanics_model_segment_mesh) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/test_solid_mechanics_model_bar_traction2d_parallel.sh ${CMAKE_CURRENT_BINARY_DIR}/test_solid_mechanics_model_bar_traction2d_parallel.sh COPYONLY ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/test_solid_mechanics_model_segment_parallel.sh ${CMAKE_CURRENT_BINARY_DIR}/test_solid_mechanics_model_segment_parallel.sh COPYONLY ) endif() #=============================================================================== add_mesh(test_cube3d_mesh1 cube.geo 3 1 OUTPUT cube1.msh) add_mesh(test_cube3d_mesh2 cube.geo 3 2 OUTPUT cube2.msh) register_test(test_solid_mechanics_model_cube3d test_solid_mechanics_model_cube3d.cc) add_dependencies(test_solid_mechanics_model_cube3d test_cube3d_mesh1) register_test(test_solid_mechanics_model_cube3d_tetra10 test_solid_mechanics_model_cube3d_tetra10.cc) add_dependencies(test_solid_mechanics_model_cube3d_tetra10 test_cube3d_mesh2) #=============================================================================== configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/material.dat ${CMAKE_CURRENT_BINARY_DIR}/material.dat COPYONLY ) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) diff --git a/test/test_model/test_solid_mechanics_model/test_contact/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/CMakeLists.txt index f3d424690..3c0f29d35 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/CMakeLists.txt @@ -1,20 +1,34 @@ #=============================================================================== # @file CMakeLists.txt # @author David Kammer <david.kammer@epfl.ch> # @date Fri Dec 03 11:09:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_subdirectory("test_neighbor_structure") add_subdirectory("test_contact_search") add_subdirectory("test_contact_2d") add_subdirectory("test_contact_rigid_no_friction") diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/CMakeLists.txt index d023b1e51..27e3e0e03 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/CMakeLists.txt @@ -1,20 +1,34 @@ #=============================================================================== # @file CMakeLists.txt # @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> # @date Mon Jan 17 11:48:11 2011 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_subdirectory("test_contact_2d_expli") #add_subdirectory("test_contact_2d_expli_fric") diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/CMakeLists.txt index f56fadb62..884341fbd 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/CMakeLists.txt @@ -1,18 +1,32 @@ #=============================================================================== # @file CMakeLists.txt # @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> # @date Fri Dec 3 15:12:22 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_mesh(test_contact_2d_expli_mesh squares.geo 2 1) register_test(test_contact_2d_expli test_contact_2d_expli.cc) add_dependencies(test_contact_2d_expli test_contact_2d_expli_mesh) diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/test_contact_2d_expli.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/test_contact_2d_expli.cc index 991a4773a..188e4b29d 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/test_contact_2d_expli.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/test_contact_2d_expli.cc @@ -1,251 +1,265 @@ /** * @file test_contact_2d_expli.cc * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @date Fri Nov 26 07:43:47 2010 * * @brief test explicit DCR contact algorithm for 2d * * @section LICENSE * - * <insert lisence here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "io_helper.h" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #include "io_helper.h" #endif //AKANTU_USE_IOHELPER #define NORMAL_PRESSURE -1.e6 using namespace akantu; static void reduceGap(const SolidMechanicsModel & model, const Real threshold, const Real gap); static void setBoundaryConditions(SolidMechanicsModel & model); void my_force(double * coord, double *T); static void reduceVelocities(const SolidMechanicsModel & model, const Real ratio); static void initParaview(SolidMechanicsModel & model); Real y_min, y_max; DumperParaview dumper; int main(int argc, char *argv[]) { UInt spatial_dimension = 2; UInt max_steps = 30000; Real time_factor = 0.2; Mesh mesh(spatial_dimension); MeshIOMSH mesh_io; mesh_io.read("squares.msh", mesh); SolidMechanicsModel * model = new SolidMechanicsModel(mesh); /// get two squares closer // reduceGap(*model, 0.05, 1.e-6); UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); UInt nb_elements = model->getFEM().getMesh().getNbElement(_triangle_3); /// model initialization model->initVectors(); model->readMaterials("materials.dat"); model->initMaterials(); model->initModel(); std::cout << model->getMaterial(0) << std::endl; model->assembleMassLumped(); /// set vectors to zero memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getVelocity().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getAcceleration().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getDisplacement().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getResidual().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getMaterial(0).getStrain(_triangle_3).values, 0, spatial_dimension*spatial_dimension*nb_elements*sizeof(Real)); memset(model->getMaterial(0).getStress(_triangle_3).values, 0, spatial_dimension*spatial_dimension*nb_elements*sizeof(Real)); /// Paraview Helper #ifdef AKANTU_USE_IOHELPER initParaview(*model); #endif //AKANTU_USE_IOHELPER Real time_step = model->getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); /// set boundary conditions setBoundaryConditions(*model); /// define and initialize contact Contact * my_contact = Contact::newContact(*model, _ct_2d_expli, _cst_2d_expli, _cnst_2d_grid); my_contact->initContact(true); my_contact->setFrictionCoefficient(0.); my_contact->initNeighborStructure(); my_contact->initSearch(); for (UInt s = 0; s < max_steps; ++s) { model->explicitPred(); model->updateCurrentPosition(); my_contact->solveContact(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); if(s % 200 == 0) dumper.Dump(); if(s%100 == 0 && s>499) reduceVelocities(*model, 0.95); if(s % 500 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } delete my_contact; delete model; finalize(); return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ static void reduceGap(const SolidMechanicsModel & model, const Real threshold, const Real gap) { UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); Real * coord = model.getFEM().getMesh().getNodes().values; Real y_top = HUGE_VAL, y_bot = -HUGE_VAL; for (UInt n = 0; n < nb_nodes; ++n) { if (coord[2*n+1] > threshold) { if(coord[2*n+1] < y_top) y_top = coord[2*n+1]; } else { if (coord[2*n+1] > y_bot) y_bot = coord[2*n+1]; } } Real delta = y_top - y_bot - gap; /// move all nodes belonging to the top cube for (UInt n = 0; n < nb_nodes; ++n) { if (coord[2*n+1] > threshold) coord[2*n+1] -= delta; } } /* -------------------------------------------------------------------------- */ static void setBoundaryConditions(SolidMechanicsModel & model) { UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); Real * coord = model.getFEM().getMesh().getNodes().values; for (UInt n = 0; n < nb_nodes; ++n) { if (coord[2*n+1] > y_max) y_max = coord[2*n+1]; if (coord[2*n+1] < y_min) y_min = coord[2*n+1]; } FEM & b_fem = model.getFEMBoundary(); b_fem.initShapeFunctions(); b_fem.computeNormalsOnQuadPoints(); bool * id = model.getBoundary().values; memset(id, 0, 2*nb_nodes*sizeof(bool)); std::cout << "Nodes "; for (UInt i = 0; i < nb_nodes; ++i) { if (coord[2*i+1] < y_min + 1.e-5) { id[2*i+1] = true; std::cout << " " << i << " "; } } std::cout << "are blocked" << std::endl; model.computeForcesFromFunction(my_force, _bft_stress); } /* -------------------------------------------------------------------------- */ void my_force(double * coord, double *T) { memset(T, 0, 4*sizeof(double)); if(*(coord+1) > y_max-1.e-5) T[3] = NORMAL_PRESSURE; } /* -------------------------------------------------------------------------- */ /// artificial damping of velocities in order to reach a global static equilibrium static void reduceVelocities(const SolidMechanicsModel & model, const Real ratio) { UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); Real * velocities = model.getVelocity().values; if(ratio>1.) { fprintf(stderr,"**error** in Reduce_Velocities ratio bigger than 1!\n"); exit(-1); } for(UInt i =0; i<nb_nodes; i++) { velocities[2*i] *= ratio; velocities[2*i+1] *= ratio; } } /* -------------------------------------------------------------------------- */ static void initParaview(SolidMechanicsModel & model) { UInt spatial_dimension = model.getSpatialDimension(); UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); UInt nb_elements = model.getFEM().getMesh().getNbElement(_triangle_3); dumper.SetMode(TEXT); dumper.SetPoints(model.getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, "coordinates"); dumper.SetConnectivity((int *)model.getFEM().getMesh().getConnectivity(_triangle_3).values, TRIANGLE1, nb_elements, C_MODE); dumper.AddNodeDataField(model.getDisplacement().values, spatial_dimension, "displacements"); dumper.AddNodeDataField(model.getVelocity().values, spatial_dimension, "velocity"); dumper.AddNodeDataField(model.getResidual().values, spatial_dimension, "force"); dumper.AddElemDataField(model.getMaterial(0).getStrain(_triangle_3).values, spatial_dimension*spatial_dimension, "strain"); dumper.AddElemDataField(model.getMaterial(0).getStress(_triangle_3).values, spatial_dimension*spatial_dimension, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli_fric/test_contact_2d_expli_fric.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli_fric/test_contact_2d_expli_fric.cc index 020a769d2..12d3cfeca 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli_fric/test_contact_2d_expli_fric.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli_fric/test_contact_2d_expli_fric.cc @@ -1,279 +1,293 @@ /** * @file test_contact_2d_expli.cc * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @date Fri Nov 26 07:43:47 2010 * * @brief test explicit DCR contact algorithm for 2d * * @section LICENSE * - * <insert lisence here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "io_helper.h" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #include "io_helper.h" #endif //AKANTU_USE_IOHELPER #define NORMAL_PRESSURE -1.e6 #define IMP_VEL 1. using namespace akantu; class Boundary { -public: +public: Boundary(Mesh & mesh, SolidMechanicsModel & model); virtual ~Boundary(); - + reduceGap(const Real threshold, const Real gap); setBoundaryConditions(); - + public: - + public: private: - /// + /// SolidMechanicsModel & model; - /// + /// Mesh & mesh; Real top_bounds[]; Real }; -static void +static void static void setBoundaryConditions(SolidMechanicsModel & model); void my_force(double * coord, double *T); static void reduceVelocities(const SolidMechanicsModel & model, const Real ratio); static void initParaview(SolidMechanicsModel & model); Real y_min, y_max; DumperParaview dumper; int main(int argc, char *argv[]) { UInt spatial_dimension = 2; UInt max_steps = 30000; Real time_factor = 0.2; Mesh mesh(spatial_dimension); MeshIOMSH mesh_io; mesh_io.read("squares.msh", mesh); SolidMechanicsModel * model = new SolidMechanicsModel(mesh); /// get two squares closer // reduceGap(*model, 0.05, 1.e-6); UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); UInt nb_elements = model->getFEM().getMesh().getNbElement(_triangle_3); /// model initialization model->initVectors(); model->readMaterials("materials.dat"); model->initMaterials(); model->initModel(); std::cout << model->getMaterial(0) << std::endl; model->assembleMassLumped(); /// set vectors to zero memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getVelocity().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getAcceleration().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getDisplacement().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getResidual().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getMaterial(0).getStrain(_triangle_3).values, 0, spatial_dimension*spatial_dimension*nb_elements*sizeof(Real)); memset(model->getMaterial(0).getStress(_triangle_3).values, 0, spatial_dimension*spatial_dimension*nb_elements*sizeof(Real)); - + /// Paraview Helper #ifdef AKANTU_USE_IOHELPER initParaview(*model); #endif //AKANTU_USE_IOHELPER Real time_step = model->getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); /// set boundary conditions Boundary * my_boudary; setBoundaryConditions(*model); /// define and initialize contact - Contact * my_contact = Contact::newContact(*model, - _ct_2d_expli, - _cst_2d_expli, + Contact * my_contact = Contact::newContact(*model, + _ct_2d_expli, + _cst_2d_expli, _cnst_2d_grid); my_contact->initContact(true); my_contact->setFrictionCoefficient(0.); my_contact->initNeighborStructure(); my_contact->initSearch(); for (UInt s = 0; s < max_steps; ++s) { model->explicitPred(); model->updateCurrentPosition(); my_contact->solveContact(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); - + if(s % 200 == 0) dumper.Dump(); if(s%100 == 0 && s>499) reduceVelocities(*model, 0.95); - + if(s % 500 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } delete my_boudary; delete my_contact; delete model; finalize(); return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ static void reduceGap(const SolidMechanicsModel & model, const Real threshold, const Real gap) { UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); Real * coord = model.getFEM().getMesh().getNodes().values; Real y_top = HUGE_VAL, y_bot = -HUGE_VAL; for (UInt n = 0; n < nb_nodes; ++n) { if (coord[2*n+1] > threshold) { if(coord[2*n+1] < y_top) y_top = coord[2*n+1]; } else { if (coord[2*n+1] > y_bot) y_bot = coord[2*n+1]; } } Real delta = y_top - y_bot - gap; /// move all nodes belonging to the top cube for (UInt n = 0; n < nb_nodes; ++n) { if (coord[2*n+1] > threshold) coord[2*n+1] -= delta; } } /* -------------------------------------------------------------------------- */ static void setBoundaryConditions(SolidMechanicsModel & model) { UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); Real * coord = model.getFEM().getMesh().getNodes().values; for (UInt n = 0; n < nb_nodes; ++n) { if (coord[2*n+1] > y_max) y_max = coord[2*n+1]; if (coord[2*n+1] < y_min) - y_min = coord[2*n+1]; + y_min = coord[2*n+1]; } FEM & b_fem = model.getFEMBoundary(); b_fem.initShapeFunctions(); b_fem.computeNormalsOnQuadPoints(); bool * id = model.getBoundary().values; memset(id, 0, 2*nb_nodes*sizeof(bool)); std::cout << "Nodes "; for (UInt i = 0; i < nb_nodes; ++i) { if (coord[2*i+1] < y_min + 1.e-5) { id[2*i+1] = true; - std::cout << " " << i << " "; + std::cout << " " << i << " "; } } std::cout << "are blocked" << std::endl; model.computeForcesFromFunction(my_force, _bft_stress); } /* -------------------------------------------------------------------------- */ void my_force(double * coord, double *T) { memset(T, 0, 4*sizeof(double)); if(*(coord+1) > y_max-1.e-5) T[3] = NORMAL_PRESSURE; } /* -------------------------------------------------------------------------- */ /// artificial damping of velocities in order to reach a global static equilibrium static void reduceVelocities(const SolidMechanicsModel & model, const Real ratio) { UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); Real * velocities = model.getVelocity().values; - + if(ratio>1.) { fprintf(stderr,"**error** in Reduce_Velocities ratio bigger than 1!\n"); exit(-1); } - + for(UInt i =0; i<nb_nodes; i++) { velocities[2*i] *= ratio; velocities[2*i+1] *= ratio; } } /* -------------------------------------------------------------------------- */ static void initParaview(SolidMechanicsModel & model) { UInt spatial_dimension = model.getSpatialDimension(); UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); UInt nb_elements = model.getFEM().getMesh().getNbElement(_triangle_3); dumper.SetMode(TEXT); dumper.SetPoints(model.getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, "coordinates"); dumper.SetConnectivity((int *)model.getFEM().getMesh().getConnectivity(_triangle_3).values, TRIANGLE1, nb_elements, C_MODE); dumper.AddNodeDataField(model.getDisplacement().values, spatial_dimension, "displacements"); dumper.AddNodeDataField(model.getVelocity().values, spatial_dimension, "velocity"); dumper.AddNodeDataField(model.getResidual().values, spatial_dimension, "force"); dumper.AddElemDataField(model.getMaterial(0).getStrain(_triangle_3).values, spatial_dimension*spatial_dimension, "strain"); dumper.AddElemDataField(model.getMaterial(0).getStress(_triangle_3).values, spatial_dimension*spatial_dimension, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/CMakeLists.txt index 78112bf34..24d514c96 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/CMakeLists.txt @@ -1,69 +1,83 @@ #=============================================================================== # @file CMakeLists.txt # @author David Kammer <david.kammer@epfl.ch> # @date Wed Jan 19 12:37:24 2011 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_mesh(test_squares_mesh squares.geo 2 1) register_test(test_contact_rigid_no_friction_triangle_3 test_contact_rigid_no_friction_triangle_3.cc) add_dependencies(test_contact_rigid_no_friction_triangle_3 test_squares_mesh) #=============================================================================== add_mesh(test_cubes_mesh cubes.geo 3 1) register_test(test_contact_rigid_no_friction_tetrahedron_4 test_contact_rigid_no_friction_tetrahedron_4.cc) add_dependencies(test_contact_rigid_no_friction_tetrahedron_4 test_cubes_mesh) #=============================================================================== add_mesh(test_hertz_2d_mesh hertz_2d.geo 2 1) register_test(test_contact_rigid_no_friction_hertz_2d test_contact_rigid_no_friction_hertz_2d.cc) add_dependencies(test_contact_rigid_no_friction_hertz_2d test_hertz_2d_mesh) #=============================================================================== add_mesh(test_hertz_3d_mesh hertz_3d.geo 3 1) register_test(test_contact_rigid_no_friction_hertz_3d test_contact_rigid_no_friction_hertz_3d.cc) add_dependencies(test_contact_rigid_no_friction_hertz_3d test_hertz_3d_mesh) #=============================================================================== add_mesh(test_hertz_3d_full_mesh hertz_3d_full.geo 3 1) register_test(test_contact_rigid_no_friction_hertz_3d_full test_contact_rigid_no_friction_hertz_3d_full.cc) add_dependencies(test_contact_rigid_no_friction_hertz_3d_full test_hertz_3d_full_mesh) #=============================================================================== add_mesh(test_force_2d_mesh force_2d.geo 2 1) register_test(test_contact_rigid_no_friction_force_2d test_contact_rigid_no_friction_force_2d.cc) add_dependencies(test_contact_rigid_no_friction_force_2d test_force_2d_mesh) #=============================================================================== add_mesh(test_force_3d_mesh force_3d.geo 3 1) register_test(test_contact_rigid_no_friction_force_3d test_contact_rigid_no_friction_force_3d.cc) add_dependencies(test_contact_rigid_no_friction_force_3d test_force_3d_mesh) #=============================================================================== configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/material.dat ${CMAKE_CURRENT_BINARY_DIR}/material.dat COPYONLY ) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview/hertz_2d) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview/hertz_3d) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview/hertz_3d_full) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview/force_2d) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview/force_3d) diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_force_2d.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_force_2d.cc index 729c2ea07..30bfbac7b 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_force_2d.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_force_2d.cc @@ -1,225 +1,239 @@ /** * @file test_contact_rigid_no_friction_force_2d.cc * @author David Kammer <david.kammer@epfl.ch> * @date Mon Jan 24 10:04:42 2011 * * @brief test for force in 2d rigid contact in explicit * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_3d_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 2; const ElementType element_type = _triangle_3; const UInt paraview_type = TRIANGLE1; UInt max_steps = 200000; UInt imposing_steps = 100000; Real max_displacement = -0.1; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("force_2d.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getBoundary().values, false, dim*nb_nodes*sizeof(bool)); my_model.readMaterials("material.dat"); my_model.initMaterials(); my_model.initModel(); UInt nb_element = my_model.getFEM().getMesh().getNbElement(element_type); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * my_contact = Contact::newContact(my_model, _ct_rigid_no_fric, _cst_3d_expli, _cnst_regular_grid); my_contact->initContact(false); Surface master = 1; my_contact->addMasterSurface(master); /*const RegularGridNeighborStructure<2> & my_rgns = dynamic_cast<const RegularGridNeighborStructure<2> &>(my_contact->getContactSearch().getContactNeighborStructure(master)); const_cast<RegularGridNeighborStructure<2>&>(my_rgns).setGridSpacing(0.075, 0); const_cast<RegularGridNeighborStructure<2>&>(my_rgns).setGridSpacing(0.075, 1);*/ my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); my_contact->initSearch(); // does nothing so far // boundary conditions Surface impactor = 0; Vector<UInt> * top_nodes = new Vector<UInt>(0, 1); UInt middle_point; Real * coordinates = my_mesh.getNodes().values; Real * displacement = my_model.getDisplacement().values; bool * boundary = my_model.getBoundary().values; UInt * surface_to_nodes_offset = my_contact->getSurfaceToNodesOffset().values; UInt * surface_to_nodes = my_contact->getSurfaceToNodes().values; // symetry boundary conditions for(UInt n = surface_to_nodes_offset[impactor]; n < surface_to_nodes_offset[impactor+1]; ++n) { UInt node = surface_to_nodes[n]; Real x_coord = coordinates[node*dim]; Real y_coord = coordinates[node*dim + 1]; if (x_coord < 0.00001) boundary[node*dim] = true; if (y_coord > -0.00001) { boundary[node*dim + 1] = true; top_nodes->push_back(node); } if (x_coord < 0.00001 && y_coord > -0.00001) middle_point = node; } // ground boundary conditions for(UInt n = surface_to_nodes_offset[master]; n < surface_to_nodes_offset[master+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord < -1.2) boundary[node*dim] = true; boundary[node*dim + 1] = true; } UInt * top_nodes_val = top_nodes->values; #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_model.getFEM().getMesh().getNodes().values, dim, nb_nodes, "coordinates_force_2d"); dumper.SetConnectivity((int *)my_model.getFEM().getMesh().getConnectivity(element_type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(my_model.getDisplacement().values, dim, "displacements"); dumper.AddNodeDataField(my_model.getVelocity().values, dim, "velocity"); dumper.AddNodeDataField(my_model.getResidual().values, dim, "force"); dumper.AddNodeDataField(my_model.getForce().values, dim, "applied_force"); dumper.AddElemDataField(my_model.getMaterial(0).getStrain(element_type).values, dim*dim, "strain"); dumper.AddElemDataField(my_model.getMaterial(0).getStress(element_type).values, dim*dim, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/force_2d/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream force_out; force_out.open("force_2d.csv"); force_out << "%id,ftop,fcont,zone" << std::endl; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; if(s == imposing_steps){ my_model.updateCurrentPosition(); my_contact->updateContact(); } if(s <= imposing_steps) { Real current_displacement = max_displacement/(static_cast<Real>(imposing_steps))*s; for(UInt n=0; n<top_nodes->getSize(); ++n) { UInt node = top_nodes_val[n]; displacement[node*dim + 1] = current_displacement; } } my_model.explicitPred(); my_model.updateCurrentPosition(); /// compute the penetration list PenetrationList * my_penetration_list = new PenetrationList(); const_cast<ContactSearch &>(my_contact->getContactSearch()).findPenetration(master, *my_penetration_list); UInt nb_nodes_pen = my_penetration_list->penetrating_nodes.getSize(); Vector<UInt> pen_nodes = my_penetration_list->penetrating_nodes; UInt * pen_nodes_val = pen_nodes.values; my_contact->solveContact(); my_model.updateResidual(false); Real * residual = my_model.getResidual().values; Real top_force = 0.; for(UInt n=0; n<top_nodes->getSize(); ++n) { UInt node = top_nodes_val[n]; top_force += residual[node*dim + 1]; } my_model.updateCurrentPosition(); Real * current_position = my_model.getCurrentPosition().values; Real contact_force = 0.; Real contact_zone = 0.; for (UInt i = 0; i < nb_nodes_pen; ++i) { UInt node = pen_nodes_val[i]; contact_force += residual[node*dim + 1]; contact_zone = std::max(contact_zone, current_position[node*dim]); } delete my_penetration_list; force_out << s << "," << top_force << "," << contact_force << "," << contact_zone << std::endl; my_model.updateAcceleration(); my_model.explicitCorr(); #ifdef AKANTU_USE_IOHELPER if(s % 1000 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } force_out.close(); delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_force_3d.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_force_3d.cc index f47076b7f..ecf458c66 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_force_3d.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_force_3d.cc @@ -1,227 +1,241 @@ /** * @file test_contact_rigid_no_friction_force_3d.cc * @author David Kammer <david.kammer@epfl.ch> * @date Mon Jan 24 11:56:42 2011 * * @brief test force for rigid contact 3d in explicit * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_3d_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 3; const ElementType element_type = _tetrahedron_4; const UInt paraview_type = TETRA1; UInt max_steps = 200000; UInt imposing_steps = 100000; Real max_displacement = -0.1; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("force_3d.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getBoundary().values, false, dim*nb_nodes*sizeof(bool)); my_model.readMaterials("material.dat"); my_model.initMaterials(); my_model.initModel(); UInt nb_element = my_model.getFEM().getMesh().getNbElement(element_type); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * my_contact = Contact::newContact(my_model, _ct_rigid_no_fric, _cst_3d_expli, _cnst_regular_grid); my_contact->initContact(false); Surface master = 1; my_contact->addMasterSurface(master); /*const RegularGridNeighborStructure<3> & my_rgns = dynamic_cast<const RegularGridNeighborStructure<3> &>(my_contact->getContactSearch().getContactNeighborStructure(master)); const_cast<RegularGridNeighborStructure<3>&>(my_rgns).setGridSpacing(0.075, 0); const_cast<RegularGridNeighborStructure<3>&>(my_rgns).setGridSpacing(0.075, 1); const_cast<RegularGridNeighborStructure<3>&>(my_rgns).setGridSpacing(0.075, 2);*/ my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); my_contact->initSearch(); // does nothing so far // boundary conditions Surface impactor = 0; Vector<UInt> * top_nodes = new Vector<UInt>(0, 1); Real * coordinates = my_mesh.getNodes().values; Real * displacement = my_model.getDisplacement().values; bool * boundary = my_model.getBoundary().values; UInt * surface_to_nodes_offset = my_contact->getSurfaceToNodesOffset().values; UInt * surface_to_nodes = my_contact->getSurfaceToNodes().values; // symetry boundary conditions for(UInt n = surface_to_nodes_offset[impactor]; n < surface_to_nodes_offset[impactor+1]; ++n) { UInt node = surface_to_nodes[n]; Real x_coord = coordinates[node*dim]; Real y_coord = coordinates[node*dim + 1]; Real z_coord = coordinates[node*dim + 2]; /*if (x_coord < 0.00001) boundary[node*dim] = true; if (z_coord < 0.00001) boundary[node*dim+2] = true;*/ if (y_coord > -0.00001) { boundary[node*dim + 1] = true; top_nodes->push_back(node); } } // ground boundary conditions for(UInt n = surface_to_nodes_offset[master]; n < surface_to_nodes_offset[master+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord < -1.2) boundary[node*dim] = true; boundary[node*dim + 1] = true; boundary[node*dim + 2] = true; } UInt * top_nodes_val = top_nodes->values; #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_model.getFEM().getMesh().getNodes().values, dim, nb_nodes, "coordinates_force_3d"); dumper.SetConnectivity((int *)my_model.getFEM().getMesh().getConnectivity(element_type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(my_model.getDisplacement().values, dim, "displacements"); dumper.AddNodeDataField(my_model.getVelocity().values, dim, "velocity"); dumper.AddNodeDataField(my_model.getResidual().values, dim, "force"); dumper.AddNodeDataField(my_model.getForce().values, dim, "applied_force"); dumper.AddElemDataField(my_model.getMaterial(0).getStrain(element_type).values, dim*dim, "strain"); dumper.AddElemDataField(my_model.getMaterial(0).getStress(element_type).values, dim*dim, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/force_3d/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream force_out; force_out.open("force_3d.csv"); force_out << "%id,ftop,fcont,zone" << std::endl; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; if(s == imposing_steps){ my_model.updateCurrentPosition(); my_contact->updateContact(); } if(s <= imposing_steps) { Real current_displacement = max_displacement/(static_cast<Real>(imposing_steps))*s; for(UInt n=0; n<top_nodes->getSize(); ++n) { UInt node = top_nodes_val[n]; displacement[node*dim + 1] = current_displacement; } } my_model.explicitPred(); my_model.updateCurrentPosition(); /// compute the penetration list PenetrationList * my_penetration_list = new PenetrationList(); const_cast<ContactSearch &>(my_contact->getContactSearch()).findPenetration(master, *my_penetration_list); UInt nb_nodes_pen = my_penetration_list->penetrating_nodes.getSize(); Vector<UInt> pen_nodes = my_penetration_list->penetrating_nodes; UInt * pen_nodes_val = pen_nodes.values; my_contact->solveContact(); my_model.updateResidual(false); Real * residual = my_model.getResidual().values; Real top_force = 0.; for(UInt n=0; n<top_nodes->getSize(); ++n) { UInt node = top_nodes_val[n]; top_force += residual[node*dim + 1]; } my_model.updateCurrentPosition(); Real * current_position = my_model.getCurrentPosition().values; Real contact_force = 0.; Real contact_zone = 0.; for (UInt i = 0; i < nb_nodes_pen; ++i) { UInt node = pen_nodes_val[i]; contact_force += residual[node*dim + 1]; contact_zone = std::max(contact_zone, current_position[node*dim]); } delete my_penetration_list; force_out << s << "," << top_force << "," << contact_force << "," << contact_zone << std::endl; my_model.updateAcceleration(); my_model.explicitCorr(); #ifdef AKANTU_USE_IOHELPER if(s % 1000 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } force_out.close(); delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_hertz_2d.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_hertz_2d.cc index 5ed5602b1..a759e053d 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_hertz_2d.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_hertz_2d.cc @@ -1,225 +1,239 @@ /** * @file test_contact_rigid_no_friction_hertz_2d.cc * @author David Kammer <david.kammer@epfl.ch> * @date Wed Jan 19 15:04:42 2011 * * @brief test contact search for 2d hertz in explicit * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_3d_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 2; const ElementType element_type = _triangle_3; const UInt paraview_type = TRIANGLE1; UInt max_steps = 200000; UInt imposing_steps = 100000; Real max_displacement = -0.1; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("hertz_2d.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getBoundary().values, false, dim*nb_nodes*sizeof(bool)); my_model.readMaterials("material.dat"); my_model.initMaterials(); my_model.initModel(); UInt nb_element = my_model.getFEM().getMesh().getNbElement(element_type); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * my_contact = Contact::newContact(my_model, _ct_rigid_no_fric, _cst_3d_expli, _cnst_regular_grid); my_contact->initContact(false); Surface master = 1; my_contact->addMasterSurface(master); /*const RegularGridNeighborStructure<2> & my_rgns = dynamic_cast<const RegularGridNeighborStructure<2> &>(my_contact->getContactSearch().getContactNeighborStructure(master)); const_cast<RegularGridNeighborStructure<2>&>(my_rgns).setGridSpacing(0.075, 0); const_cast<RegularGridNeighborStructure<2>&>(my_rgns).setGridSpacing(0.075, 1); */ my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); my_contact->initSearch(); // does nothing so far // boundary conditions Surface impactor = 0; Vector<UInt> * top_nodes = new Vector<UInt>(0, 1); UInt middle_point; Real * coordinates = my_mesh.getNodes().values; Real * displacement = my_model.getDisplacement().values; bool * boundary = my_model.getBoundary().values; UInt * surface_to_nodes_offset = my_contact->getSurfaceToNodesOffset().values; UInt * surface_to_nodes = my_contact->getSurfaceToNodes().values; // symetry boundary conditions for(UInt n = surface_to_nodes_offset[impactor]; n < surface_to_nodes_offset[impactor+1]; ++n) { UInt node = surface_to_nodes[n]; Real x_coord = coordinates[node*dim]; Real y_coord = coordinates[node*dim + 1]; if (x_coord < 0.00001) boundary[node*dim] = true; if (y_coord > -0.00001) { boundary[node*dim + 1] = true; top_nodes->push_back(node); } if (x_coord < 0.00001 && y_coord > -0.00001) middle_point = node; } // ground boundary conditions for(UInt n = surface_to_nodes_offset[master]; n < surface_to_nodes_offset[master+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord < -1.2) boundary[node*dim] = true; boundary[node*dim + 1] = true; } UInt * top_nodes_val = top_nodes->values; #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_model.getFEM().getMesh().getNodes().values, dim, nb_nodes, "coordinates_2d"); dumper.SetConnectivity((int *)my_model.getFEM().getMesh().getConnectivity(element_type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(my_model.getDisplacement().values, dim, "displacements"); dumper.AddNodeDataField(my_model.getVelocity().values, dim, "velocity"); dumper.AddNodeDataField(my_model.getResidual().values, dim, "force"); dumper.AddNodeDataField(my_model.getForce().values, dim, "applied_force"); dumper.AddElemDataField(my_model.getMaterial(0).getStrain(element_type).values, dim*dim, "strain"); dumper.AddElemDataField(my_model.getMaterial(0).getStress(element_type).values, dim*dim, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/hertz_2d/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream hertz; hertz.open("hertz_2d.csv"); hertz << "%id,ftop,fcont,zone" << std::endl; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; if(s % 200 == 0){ my_model.updateCurrentPosition(); my_contact->updateContact(); } if(s <= imposing_steps) { Real current_displacement = max_displacement/(static_cast<Real>(imposing_steps))*s; for(UInt n=0; n<top_nodes->getSize(); ++n) { UInt node = top_nodes_val[n]; displacement[node*dim + 1] = current_displacement; } } my_model.explicitPred(); my_model.updateCurrentPosition(); /// compute the penetration list PenetrationList * my_penetration_list = new PenetrationList(); const_cast<ContactSearch &>(my_contact->getContactSearch()).findPenetration(master, *my_penetration_list); UInt nb_nodes_pen = my_penetration_list->penetrating_nodes.getSize(); Vector<UInt> pen_nodes = my_penetration_list->penetrating_nodes; UInt * pen_nodes_val = pen_nodes.values; my_contact->solveContact(); my_model.updateResidual(false); Real * residual = my_model.getResidual().values; Real top_force = 0.; for(UInt n=0; n<top_nodes->getSize(); ++n) { UInt node = top_nodes_val[n]; top_force += residual[node*dim + 1]; } my_model.updateCurrentPosition(); Real * current_position = my_model.getCurrentPosition().values; Real contact_force = 0.; Real contact_zone = 0.; for (UInt i = 0; i < nb_nodes_pen; ++i) { UInt node = pen_nodes_val[i]; contact_force += residual[node*dim + 1]; contact_zone = std::max(contact_zone, current_position[node*dim]); } delete my_penetration_list; hertz << s << "," << top_force << "," << contact_force << "," << contact_zone << std::endl; my_model.updateAcceleration(); my_model.explicitCorr(); #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } hertz.close(); delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_hertz_3d.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_hertz_3d.cc index 8f109fd44..f6114dacc 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_hertz_3d.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_hertz_3d.cc @@ -1,230 +1,244 @@ /** * @file test_contact_rigid_no_friction_hertz_3d.cc * @author David Kammer <david.kammer@epfl.ch> * @date Thu Jan 20 15:50:42 2011 * * @brief test rigid contact for 3d hertz in explicit * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_3d_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 3; const ElementType element_type = _tetrahedron_4; const UInt paraview_type = TETRA1; UInt max_steps = 200000; UInt imposing_steps = 100000; Real max_displacement = -0.1; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("hertz_3d.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getBoundary().values, false, dim*nb_nodes*sizeof(bool)); my_model.readMaterials("material.dat"); my_model.initMaterials(); my_model.initModel(); UInt nb_element = my_model.getFEM().getMesh().getNbElement(element_type); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * my_contact = Contact::newContact(my_model, _ct_rigid_no_fric, _cst_3d_expli, _cnst_regular_grid); my_contact->initContact(false); Surface master = 1; my_contact->addMasterSurface(master); /* const RegularGridNeighborStructure<3> & my_rgns = dynamic_cast<const RegularGridNeighborStructure<3> &>(my_contact->getContactSearch().getContactNeighborStructure(master)); const_cast<RegularGridNeighborStructure<3>&>(my_rgns).setGridSpacing(0.075, 0); const_cast<RegularGridNeighborStructure<3>&>(my_rgns).setGridSpacing(0.075, 1); const_cast<RegularGridNeighborStructure<3>&>(my_rgns).setGridSpacing(0.075, 2);*/ my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); my_contact->initSearch(); // does nothing so far // boundary conditions Surface impactor = 0; Vector<UInt> * top_nodes = new Vector<UInt>(0, 1); UInt middle_point; Real * coordinates = my_mesh.getNodes().values; Real * displacement = my_model.getDisplacement().values; bool * boundary = my_model.getBoundary().values; UInt * surface_to_nodes_offset = my_contact->getSurfaceToNodesOffset().values; UInt * surface_to_nodes = my_contact->getSurfaceToNodes().values; // symetry boundary conditions for(UInt n = surface_to_nodes_offset[impactor]; n < surface_to_nodes_offset[impactor+1]; ++n) { UInt node = surface_to_nodes[n]; Real x_coord = coordinates[node*dim]; Real y_coord = coordinates[node*dim + 1]; Real z_coord = coordinates[node*dim + 2]; if (x_coord < 0.00001) boundary[node*dim] = true; if (z_coord < 0.00001) boundary[node*dim+2] = true; if (y_coord > -0.00001) { boundary[node*dim + 1] = true; top_nodes->push_back(node); } if (x_coord < 0.00001 && y_coord > -0.00001 && z_coord < 0.00001) middle_point = node; } // ground boundary conditions for(UInt n = surface_to_nodes_offset[master]; n < surface_to_nodes_offset[master+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord < -1.2) boundary[node*dim] = true; boundary[node*dim + 1] = true; boundary[node*dim + 2] = true; } UInt * top_nodes_val = top_nodes->values; #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_model.getFEM().getMesh().getNodes().values, dim, nb_nodes, "coordinates_3d"); dumper.SetConnectivity((int *)my_model.getFEM().getMesh().getConnectivity(element_type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(my_model.getDisplacement().values, dim, "displacements"); dumper.AddNodeDataField(my_model.getVelocity().values, dim, "velocity"); dumper.AddNodeDataField(my_model.getResidual().values, dim, "force"); dumper.AddNodeDataField(my_model.getForce().values, dim, "applied_force"); dumper.AddElemDataField(my_model.getMaterial(0).getStrain(element_type).values, dim*dim, "strain"); dumper.AddElemDataField(my_model.getMaterial(0).getStress(element_type).values, dim*dim, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/hertz_3d/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream hertz; hertz.open("hertz_3d.csv"); hertz << "%id,ftop,fcont,zone" << std::endl; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; if(s % 250 == 0){ my_model.updateCurrentPosition(); my_contact->updateContact(); } if(s <= imposing_steps) { Real current_displacement = max_displacement/(static_cast<Real>(imposing_steps))*s; for(UInt n=0; n<top_nodes->getSize(); ++n) { UInt node = top_nodes_val[n]; displacement[node*dim + 1] = current_displacement; } } my_model.explicitPred(); my_model.updateCurrentPosition(); /// compute the penetration list PenetrationList * my_penetration_list = new PenetrationList(); const_cast<ContactSearch &>(my_contact->getContactSearch()).findPenetration(master, *my_penetration_list); UInt nb_nodes_pen = my_penetration_list->penetrating_nodes.getSize(); Vector<UInt> pen_nodes = my_penetration_list->penetrating_nodes; UInt * pen_nodes_val = pen_nodes.values; my_contact->solveContact(); my_model.updateResidual(false); Real * residual = my_model.getResidual().values; Real top_force = 0.; for(UInt n=0; n<top_nodes->getSize(); ++n) { UInt node = top_nodes_val[n]; top_force += residual[node*dim + 1]; } my_model.updateCurrentPosition(); Real * current_position = my_model.getCurrentPosition().values; Real contact_force = 0.; Real contact_zone = 0.; for (UInt i = 0; i < nb_nodes_pen; ++i) { UInt node = pen_nodes_val[i]; contact_force += residual[node*dim + 1]; contact_zone = std::max(contact_zone, current_position[node*dim]); } delete my_penetration_list; hertz << s << "," << top_force << "," << contact_force << "," << contact_zone << std::endl; my_model.updateAcceleration(); my_model.explicitCorr(); #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } hertz.close(); delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_hertz_3d_full.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_hertz_3d_full.cc index 68be5a2bb..89dde61ab 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_hertz_3d_full.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_hertz_3d_full.cc @@ -1,228 +1,242 @@ /** * @file test_contact_rigid_no_friction_hertz_3d_full.cc * @author David Kammer <david.kammer@epfl.ch> * @date Mon Jan 24 15:53:42 2011 * * @brief test rigid contact without friction for full 3d hertz in explicit * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_3d_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 3; const ElementType element_type = _tetrahedron_4; const UInt paraview_type = TETRA1; UInt max_steps = 200000; UInt imposing_steps = 100000; Real max_displacement = -0.1; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("hertz_3d_full.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getBoundary().values, false, dim*nb_nodes*sizeof(bool)); my_model.readMaterials("material.dat"); my_model.initMaterials(); my_model.initModel(); UInt nb_element = my_model.getFEM().getMesh().getNbElement(element_type); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * my_contact = Contact::newContact(my_model, _ct_rigid_no_fric, _cst_3d_expli, _cnst_regular_grid); my_contact->initContact(false); Surface master = 1; my_contact->addMasterSurface(master); /*const RegularGridNeighborStructure<3> & my_rgns = dynamic_cast<const RegularGridNeighborStructure<3> &>(my_contact->getContactSearch().getContactNeighborStructure(master)); const_cast<RegularGridNeighborStructure<3>&>(my_rgns).setGridSpacing(0.075, 0); const_cast<RegularGridNeighborStructure<3>&>(my_rgns).setGridSpacing(0.075, 1); const_cast<RegularGridNeighborStructure<3>&>(my_rgns).setGridSpacing(0.075, 2);*/ my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); my_contact->initSearch(); // does nothing so far // boundary conditions Surface impactor = 0; Vector<UInt> * top_nodes = new Vector<UInt>(0, 1); Real * coordinates = my_mesh.getNodes().values; Real * displacement = my_model.getDisplacement().values; bool * boundary = my_model.getBoundary().values; UInt * surface_to_nodes_offset = my_contact->getSurfaceToNodesOffset().values; UInt * surface_to_nodes = my_contact->getSurfaceToNodes().values; // symetry boundary conditions for(UInt n = surface_to_nodes_offset[impactor]; n < surface_to_nodes_offset[impactor+1]; ++n) { UInt node = surface_to_nodes[n]; Real x_coord = coordinates[node*dim]; Real y_coord = coordinates[node*dim + 1]; Real z_coord = coordinates[node*dim + 2]; /*if (x_coord < 0.00001) boundary[node*dim] = true; if (z_coord < 0.00001) boundary[node*dim+2] = true;*/ if (y_coord > -0.00001) { boundary[node*dim + 1] = true; top_nodes->push_back(node); } } // ground boundary conditions for(UInt n = surface_to_nodes_offset[master]; n < surface_to_nodes_offset[master+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord < -1.2) boundary[node*dim] = true; boundary[node*dim + 1] = true; boundary[node*dim + 2] = true; } UInt * top_nodes_val = top_nodes->values; #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_model.getFEM().getMesh().getNodes().values, dim, nb_nodes, "coordinates_3d_full"); dumper.SetConnectivity((int *)my_model.getFEM().getMesh().getConnectivity(element_type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(my_model.getDisplacement().values, dim, "displacements"); dumper.AddNodeDataField(my_model.getVelocity().values, dim, "velocity"); dumper.AddNodeDataField(my_model.getResidual().values, dim, "force"); dumper.AddNodeDataField(my_model.getForce().values, dim, "applied_force"); dumper.AddElemDataField(my_model.getMaterial(0).getStrain(element_type).values, dim*dim, "strain"); dumper.AddElemDataField(my_model.getMaterial(0).getStress(element_type).values, dim*dim, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/hertz_3d_full/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream hertz; hertz.open("hertz_3d_full.csv"); hertz << "%id,ftop,fcont,zone" << std::endl; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; if(s % 200 == 0){ my_model.updateCurrentPosition(); my_contact->updateContact(); } if(s <= imposing_steps) { Real current_displacement = max_displacement/(static_cast<Real>(imposing_steps))*s; for(UInt n=0; n<top_nodes->getSize(); ++n) { UInt node = top_nodes_val[n]; displacement[node*dim + 1] = current_displacement; } } my_model.explicitPred(); my_model.updateCurrentPosition(); /// compute the penetration list PenetrationList * my_penetration_list = new PenetrationList(); const_cast<ContactSearch &>(my_contact->getContactSearch()).findPenetration(master, *my_penetration_list); UInt nb_nodes_pen = my_penetration_list->penetrating_nodes.getSize(); Vector<UInt> pen_nodes = my_penetration_list->penetrating_nodes; UInt * pen_nodes_val = pen_nodes.values; my_contact->solveContact(); my_model.updateResidual(false); Real * residual = my_model.getResidual().values; Real top_force = 0.; for(UInt n=0; n<top_nodes->getSize(); ++n) { UInt node = top_nodes_val[n]; top_force += residual[node*dim + 1]; } my_model.updateCurrentPosition(); Real * current_position = my_model.getCurrentPosition().values; Real contact_force = 0.; Real contact_zone = 0.; for (UInt i = 0; i < nb_nodes_pen; ++i) { UInt node = pen_nodes_val[i]; contact_force += residual[node*dim + 1]; contact_zone = std::max(contact_zone, current_position[node*dim]); } delete my_penetration_list; hertz << s << "," << top_force << "," << contact_force << "," << contact_zone << std::endl; my_model.updateAcceleration(); my_model.explicitCorr(); #ifdef AKANTU_USE_IOHELPER if(s % 500 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } hertz.close(); delete my_contact; delete top_nodes; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_tetrahedron_4.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_tetrahedron_4.cc index 8f8e1d5cf..37190acdd 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_tetrahedron_4.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_tetrahedron_4.cc @@ -1,213 +1,227 @@ /** * @file test_contact_rigid_no_friction_tetrahedron_4.cc * @author David Kammer <david.kammer@epfl.ch> * @date Wed Jan 19 12:40:42 2011 * * @brief test rigid contact without friction for 3d case in explicit * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_3d_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 3; const ElementType element_type = _tetrahedron_4; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("cubes.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt max_steps = 3; unsigned int nb_nodes = my_mesh.getNbNodes(); /// dump facet and surface information to paraview #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_mesh.getNodes().values, dim, nb_nodes, "tetrahedron_4_nodes_test-surface-extraction"); dumper.SetConnectivity((int*)my_mesh.getConnectivity(_tetrahedron_4).values, TETRA1, my_mesh.getNbElement(_tetrahedron_4), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); Real * displacement = my_model.getDisplacement().values; my_model.readMaterials("material.dat"); my_model.initMaterials(); my_model.initModel(); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * my_contact = Contact::newContact(my_model, _ct_rigid_no_fric, _cst_3d_expli, _cnst_regular_grid); my_contact->initContact(false); Surface master = 0; Surface impactor = 1; my_contact->addMasterSurface(master); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); const NodesNeighborList & my_neighbor_list = dynamic_cast<const NodesNeighborList &>(my_contact->getContactSearch().getContactNeighborStructure(master).getNeighborList()); UInt nb_nodes_neigh = my_neighbor_list.impactor_nodes.getSize(); Vector<UInt> impact_nodes = my_neighbor_list.impactor_nodes; UInt * impact_nodes_val = impact_nodes.values; /// print impactor nodes std::cout << "we have " << nb_nodes_neigh << " impactor nodes:"; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " " << impact_nodes_val[i]; } std::cout << std::endl; UInt * master_nodes_offset_val = my_neighbor_list.master_nodes_offset.values; UInt * master_nodes_val = my_neighbor_list.master_nodes.values; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " Impactor node: " << impact_nodes_val[i] << " has master nodes:"; for(UInt mn = master_nodes_offset_val[i]; mn < master_nodes_offset_val[i+1]; ++mn) { std::cout << " " << master_nodes_val[mn]; } std::cout << std::endl; } my_contact->initSearch(); // does nothing so far std::cout << std::endl << "epsilon = " << std::numeric_limits<Real>::epsilon() << std::endl; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { std::cout << std::endl << "passing step " << s << "/" << max_steps << std::endl; /// apply a displacement to the slave body if(s == 2) { Real * coord = my_mesh.getNodes().values; for(UInt n = 0; n < nb_nodes; ++n) { if(coord[n*dim + 2] > 1.0) { displacement[n*dim+2] = -0.01; } } /* UInt nb_elements = my_mesh.getNbElement(element_type); UInt nb_nodes_element = my_mesh.getNbNodesPerElement(element_type); Vector<UInt> element_mat = my_model.getElementMaterial(element_type); UInt * element_mat_val = element_mat.values; UInt * connectivity = my_mesh.getConnectivity(element_type).values; for(UInt el = 0; el < nb_elements; ++el) { std::cout << "element: " << el << " with mat: " << element_mat_val[el] << std::endl; if(element_mat_val[el] == impactor) { for(UInt n = 0; n < nb_nodes_element; ++n) { displacement[connectivity[el * nb_nodes_element + n]+2] = -0.2; } } }*/ } /// central difference predictor my_model.explicitPred(); /// update current positions my_model.updateCurrentPosition(); /// compute the penetration list std::cout << "Before solveContact" << std::endl; PenetrationList * my_penetration_list = new PenetrationList(); const_cast<ContactSearch &>(my_contact->getContactSearch()).findPenetration(master, *my_penetration_list); UInt nb_nodes_pen = my_penetration_list->penetrating_nodes.getSize(); Vector<UInt> pen_nodes = my_penetration_list->penetrating_nodes; UInt * pen_nodes_val = pen_nodes.values; std::cout << "we have " << nb_nodes_pen << " penetrating nodes:"; for (UInt i = 0; i < nb_nodes_pen; ++i) std::cout << " " << pen_nodes_val[i]; std::cout << std::endl; delete my_penetration_list; /// solve contact my_contact->solveContact(); /// compute the penetration list std::cout << "After solveContact" << std::endl; PenetrationList * my_penetration_list_2 = new PenetrationList(); const_cast<ContactSearch &>(my_contact->getContactSearch()).findPenetration(master, *my_penetration_list_2); UInt nb_nodes_pen_2 = my_penetration_list_2->penetrating_nodes.getSize(); Vector<UInt> pen_nodes_2 = my_penetration_list_2->penetrating_nodes; UInt * pen_nodes_2_val = pen_nodes_2.values; std::cout << "we have " << nb_nodes_pen_2 << " penetrating nodes:"; for (UInt i = 0; i < nb_nodes_pen_2; ++i) std::cout << " " << pen_nodes_2_val[i]; std::cout << std::endl; delete my_penetration_list_2; /// compute the residual my_model.updateResidual(false); /// compute the acceleration my_model.updateAcceleration(); /// central difference corrector my_model.explicitCorr(); } delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_triangle_3.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_triangle_3.cc index db680c826..154af950f 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_triangle_3.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid_no_friction/test_contact_rigid_no_friction_triangle_3.cc @@ -1,212 +1,226 @@ /** * @file test_contact_rigid_no_friction_triangle_3.cc * @author David Kammer <david.kammer@epfl.ch> * @date Mon Jan 17 11:13:42 2011 * * @brief test contact search for 2d case in explicit * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_3d_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 2; const ElementType element_type = _triangle_3; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("squares.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt max_steps = 3; unsigned int nb_nodes = my_mesh.getNbNodes(); /// dump facet and surface information to paraview #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_mesh.getNodes().values, dim, nb_nodes, "triangle_3_nodes_test-surface-extraction"); dumper.SetConnectivity((int*)my_mesh.getConnectivity(_triangle_3).values, TETRA1, my_mesh.getNbElement(_triangle_3), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); Real * displacement = my_model.getDisplacement().values; my_model.readMaterials("material.dat"); my_model.initMaterials(); my_model.initModel(); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * my_contact = Contact::newContact(my_model, _ct_rigid_no_fric, _cst_3d_expli, _cnst_regular_grid); my_contact->initContact(false); Surface master = 0; Surface impactor = 1; my_contact->addMasterSurface(master); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); const NodesNeighborList & my_neighbor_list = dynamic_cast<const NodesNeighborList &>(my_contact->getContactSearch().getContactNeighborStructure(master).getNeighborList()); UInt nb_nodes_neigh = my_neighbor_list.impactor_nodes.getSize(); Vector<UInt> impact_nodes = my_neighbor_list.impactor_nodes; UInt * impact_nodes_val = impact_nodes.values; /// print impactor nodes std::cout << "we have " << nb_nodes_neigh << " impactor nodes:"; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " " << impact_nodes_val[i]; } std::cout << std::endl; UInt * master_nodes_offset_val = my_neighbor_list.master_nodes_offset.values; UInt * master_nodes_val = my_neighbor_list.master_nodes.values; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " Impactor node: " << impact_nodes_val[i] << " has master nodes:"; for(UInt mn = master_nodes_offset_val[i]; mn < master_nodes_offset_val[i+1]; ++mn) { std::cout << " " << master_nodes_val[mn]; } std::cout << std::endl; } my_contact->initSearch(); // does nothing so far std::cout << std::endl << "epsilon = " << std::numeric_limits<Real>::epsilon() << std::endl; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { std::cout << std::endl << "passing step " << s << "/" << max_steps << std::endl; /// apply a displacement to the slave body if(s == 2) { Real * coord = my_mesh.getNodes().values; for(UInt n = 0; n < nb_nodes; ++n) { if(coord[n*dim + 0] > 1.0) { displacement[n*dim+0] = -0.02; } } /* UInt nb_elements = my_mesh.getNbElement(element_type); UInt nb_nodes_element = my_mesh.getNbNodesPerElement(element_type); Vector<UInt> element_mat = my_model.getElementMaterial(element_type); UInt * element_mat_val = element_mat.values; UInt * connectivity = my_mesh.getConnectivity(element_type).values; for(UInt el = 0; el < nb_elements; ++el) { std::cout << "element: " << el << " with mat: " << element_mat_val[el] << std::endl; if(element_mat_val[el] == impactor) { for(UInt n = 0; n < nb_nodes_element; ++n) { displacement[connectivity[el * nb_nodes_element + n]+2] = -0.2; } } }*/ } /// central difference predictor my_model.explicitPred(); /// update current position my_model.updateCurrentPosition(); /// compute the penetration list std::cout << "Before solveContact" << std::endl; PenetrationList * my_penetration_list = new PenetrationList(); const_cast<ContactSearch &>(my_contact->getContactSearch()).findPenetration(master, *my_penetration_list); UInt nb_nodes_pen = my_penetration_list->penetrating_nodes.getSize(); Vector<UInt> pen_nodes = my_penetration_list->penetrating_nodes; UInt * pen_nodes_val = pen_nodes.values; std::cout << "we have " << nb_nodes_pen << " penetrating nodes:"; for (UInt i = 0; i < nb_nodes_pen; ++i) std::cout << " " << pen_nodes_val[i]; std::cout << std::endl; delete my_penetration_list; /// solve contact my_contact->solveContact(); /// compute the penetration list std::cout << "After solveContact" << std::endl; PenetrationList * my_penetration_list_2 = new PenetrationList(); const_cast<ContactSearch &>(my_contact->getContactSearch()).findPenetration(master, *my_penetration_list_2); UInt nb_nodes_pen_2 = my_penetration_list_2->penetrating_nodes.getSize(); Vector<UInt> pen_nodes_2 = my_penetration_list_2->penetrating_nodes; UInt * pen_nodes_2_val = pen_nodes_2.values; std::cout << "we have " << nb_nodes_pen_2 << " penetrating nodes:"; for (UInt i = 0; i < nb_nodes_pen_2; ++i) std::cout << " " << pen_nodes_2_val[i]; std::cout << std::endl; delete my_penetration_list_2; /// compute the residual my_model.updateResidual(false); /// compute the acceleration my_model.updateAcceleration(); /// central difference corrector my_model.explicitCorr(); } delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/CMakeLists.txt index 29b9b3475..929aef030 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/CMakeLists.txt @@ -1,16 +1,30 @@ #=============================================================================== # @file CMakeLists.txt # @author David Kammer <david.kammer@epfl.ch> # @date Mon Jan 17 11:29:59 2011 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_subdirectory("test_contact_search_3d_explicit") diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/test_contact_search_3d_explicit/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/test_contact_search_3d_explicit/CMakeLists.txt index 2b91361ae..ad35c3dae 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/test_contact_search_3d_explicit/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/test_contact_search_3d_explicit/CMakeLists.txt @@ -1,39 +1,53 @@ #=============================================================================== # @file CMakeLists.txt # @author David Kammer <david.kammer@epfl.ch> # @date Fri Dec 03 12:02:24 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_mesh(test_3d_explicit_mesh_squares squares.geo 2 1) register_test(test_3d_explicit_triangle_3 test_3d_explicit_triangle_3.cc) add_dependencies(test_3d_explicit_triangle_3 test_3d_explicit_mesh_squares) #=============================================================================== add_mesh(test_3d_explicit_mesh cubes.geo 3 1) register_test(test_3d_explicit_tetrahedron_4 test_3d_explicit_tetrahedron_4.cc) add_dependencies(test_3d_explicit_tetrahedron_4 test_3d_explicit_mesh) #=============================================================================== #add_mesh(test_regular_grid_3d_mesh cubes.geo 3 1) #register_test(test_regular_grid_tetrahedron_4_nodes test_regular_grid_tetrahedron_4_nodes.cc) #add_dependencies(test_regular_grid_tetrahedron_4_nodes test_regular_grid_3d_mesh) #=============================================================================== configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/material.dat ${CMAKE_CURRENT_BINARY_DIR}/material.dat COPYONLY ) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/test_contact_search_3d_explicit/test_3d_explicit_tetrahedron_4.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/test_contact_search_3d_explicit/test_3d_explicit_tetrahedron_4.cc index d873d7641..c9da5d31e 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/test_contact_search_3d_explicit/test_3d_explicit_tetrahedron_4.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/test_contact_search_3d_explicit/test_3d_explicit_tetrahedron_4.cc @@ -1,194 +1,208 @@ /** * @file test_3d_explicit_tetrahedron_4.cc * @author David Kammer <david.kammer@epfl.ch> * @date Fri Dec 03 12:11:42 2010 * * @brief test contact search for 3d case in explicit * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_3d_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 3; const ElementType element_type = _tetrahedron_4; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("cubes.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt max_steps = 2; unsigned int nb_nodes = my_mesh.getNbNodes(); /// dump facet and surface information to paraview #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_mesh.getNodes().values, dim, nb_nodes, "tetrahedron_4_nodes_test-surface-extraction"); dumper.SetConnectivity((int*)my_mesh.getConnectivity(_tetrahedron_4).values, TETRA1, my_mesh.getNbElement(_tetrahedron_4), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); Real * displacement = my_model.getDisplacement().values; my_model.readMaterials("material.dat"); my_model.initMaterials(); my_model.initModel(); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * my_contact = Contact::newContact(my_model, _ct_3d_expli, _cst_3d_expli, _cnst_regular_grid); my_contact->initContact(false); Surface master = 0; Surface impactor = 1; my_contact->addMasterSurface(master); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); const NodesNeighborList & my_neighbor_list = dynamic_cast<const NodesNeighborList &>(my_contact->getContactSearch().getContactNeighborStructure(master).getNeighborList()); UInt nb_nodes_neigh = my_neighbor_list.impactor_nodes.getSize(); Vector<UInt> impact_nodes = my_neighbor_list.impactor_nodes; UInt * impact_nodes_val = impact_nodes.values; /// print impactor nodes std::cout << "we have " << nb_nodes_neigh << " impactor nodes:"; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " " << impact_nodes_val[i]; } std::cout << std::endl; UInt * master_nodes_offset_val = my_neighbor_list.master_nodes_offset.values; UInt * master_nodes_val = my_neighbor_list.master_nodes.values; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " Impactor node: " << impact_nodes_val[i] << " has master nodes:"; for(UInt mn = master_nodes_offset_val[i]; mn < master_nodes_offset_val[i+1]; ++mn) { std::cout << " " << master_nodes_val[mn]; } std::cout << std::endl; } my_contact->initSearch(); // does nothing so far std::cout << std::endl << "epsilon = " << std::numeric_limits<Real>::epsilon() << std::endl; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { std::cout << std::endl << "passing step " << s << "/" << max_steps << std::endl; /// apply a displacement to the slave body if(s == 2) { Real * coord = my_mesh.getNodes().values; for(UInt n = 0; n < nb_nodes; ++n) { if(coord[n*dim + 2] > 1.0) { displacement[n*dim+2] = -0.01; } } /* UInt nb_elements = my_mesh.getNbElement(element_type); UInt nb_nodes_element = my_mesh.getNbNodesPerElement(element_type); Vector<UInt> element_mat = my_model.getElementMaterial(element_type); UInt * element_mat_val = element_mat.values; UInt * connectivity = my_mesh.getConnectivity(element_type).values; for(UInt el = 0; el < nb_elements; ++el) { std::cout << "element: " << el << " with mat: " << element_mat_val[el] << std::endl; if(element_mat_val[el] == impactor) { for(UInt n = 0; n < nb_nodes_element; ++n) { displacement[connectivity[el * nb_nodes_element + n]+2] = -0.2; } } }*/ } /// central difference predictor my_model.explicitPred(); /// update current positions my_model.updateCurrentPosition(); /// compute the penetration list PenetrationList * my_penetration_list = new PenetrationList(); const_cast<ContactSearch &>(my_contact->getContactSearch()).findPenetration(master, *my_penetration_list); UInt nb_nodes_pen = my_penetration_list->penetrating_nodes.getSize(); Vector<UInt> pen_nodes = my_penetration_list->penetrating_nodes; UInt * pen_nodes_val = pen_nodes.values; std::cout << "we have " << nb_nodes_pen << " penetrating nodes:"; for (UInt i = 0; i < nb_nodes_pen; ++i) std::cout << " " << pen_nodes_val[i]; std::cout << std::endl; delete my_penetration_list; /// compute the residual my_model.updateResidual(false); /// compute the acceleration my_model.updateAcceleration(); /// central difference corrector my_model.explicitCorr(); } delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/test_contact_search_3d_explicit/test_3d_explicit_triangle_3.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/test_contact_search_3d_explicit/test_3d_explicit_triangle_3.cc index c73cf51ad..41ec41307 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/test_contact_search_3d_explicit/test_3d_explicit_triangle_3.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_search/test_contact_search_3d_explicit/test_3d_explicit_triangle_3.cc @@ -1,194 +1,208 @@ /** * @file test_3d_explicit_triangle_3.cc * @author David Kammer <david.kammer@epfl.ch> * @date Mon Jan 17 11:13:42 2011 * * @brief test contact search for 2d case in explicit * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_3d_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 2; const ElementType element_type = _triangle_3; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("squares.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt max_steps = 2; unsigned int nb_nodes = my_mesh.getNbNodes(); /// dump facet and surface information to paraview #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_mesh.getNodes().values, dim, nb_nodes, "triangle_3_nodes_test-surface-extraction"); dumper.SetConnectivity((int*)my_mesh.getConnectivity(_triangle_3).values, TETRA1, my_mesh.getNbElement(_triangle_3), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); Real * displacement = my_model.getDisplacement().values; my_model.readMaterials("material.dat"); my_model.initMaterials(); my_model.initModel(); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * my_contact = Contact::newContact(my_model, _ct_3d_expli, _cst_3d_expli, _cnst_regular_grid); my_contact->initContact(false); Surface master = 0; Surface impactor = 1; my_contact->addMasterSurface(master); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); const NodesNeighborList & my_neighbor_list = dynamic_cast<const NodesNeighborList &>(my_contact->getContactSearch().getContactNeighborStructure(master).getNeighborList()); UInt nb_nodes_neigh = my_neighbor_list.impactor_nodes.getSize(); Vector<UInt> impact_nodes = my_neighbor_list.impactor_nodes; UInt * impact_nodes_val = impact_nodes.values; /// print impactor nodes std::cout << "we have " << nb_nodes_neigh << " impactor nodes:"; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " " << impact_nodes_val[i]; } std::cout << std::endl; UInt * master_nodes_offset_val = my_neighbor_list.master_nodes_offset.values; UInt * master_nodes_val = my_neighbor_list.master_nodes.values; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " Impactor node: " << impact_nodes_val[i] << " has master nodes:"; for(UInt mn = master_nodes_offset_val[i]; mn < master_nodes_offset_val[i+1]; ++mn) { std::cout << " " << master_nodes_val[mn]; } std::cout << std::endl; } my_contact->initSearch(); // does nothing so far std::cout << std::endl << "epsilon = " << std::numeric_limits<Real>::epsilon() << std::endl; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { std::cout << std::endl << "passing step " << s << "/" << max_steps << std::endl; /// apply a displacement to the slave body if(s == 2) { Real * coord = my_mesh.getNodes().values; for(UInt n = 0; n < nb_nodes; ++n) { if(coord[n*dim + 0] > 1.0) { displacement[n*dim+0] = -0.02; } } /* UInt nb_elements = my_mesh.getNbElement(element_type); UInt nb_nodes_element = my_mesh.getNbNodesPerElement(element_type); Vector<UInt> element_mat = my_model.getElementMaterial(element_type); UInt * element_mat_val = element_mat.values; UInt * connectivity = my_mesh.getConnectivity(element_type).values; for(UInt el = 0; el < nb_elements; ++el) { std::cout << "element: " << el << " with mat: " << element_mat_val[el] << std::endl; if(element_mat_val[el] == impactor) { for(UInt n = 0; n < nb_nodes_element; ++n) { displacement[connectivity[el * nb_nodes_element + n]+2] = -0.2; } } }*/ } /// central difference predictor my_model.explicitPred(); /// update current position my_model.updateCurrentPosition(); /// compute the penetration list PenetrationList * my_penetration_list = new PenetrationList(); const_cast<ContactSearch &>(my_contact->getContactSearch()).findPenetration(master, *my_penetration_list); UInt nb_nodes_pen = my_penetration_list->penetrating_nodes.getSize(); Vector<UInt> pen_nodes = my_penetration_list->penetrating_nodes; UInt * pen_nodes_val = pen_nodes.values; std::cout << "we have " << nb_nodes_pen << " penetrating nodes:"; for (UInt i = 0; i < nb_nodes_pen; ++i) std::cout << " " << pen_nodes_val[i]; std::cout << std::endl; delete my_penetration_list; /// compute the residual my_model.updateResidual(false); /// compute the acceleration my_model.updateAcceleration(); /// central difference corrector my_model.explicitCorr(); } delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/CMakeLists.txt index 8a18c7333..dca6d80f8 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/CMakeLists.txt @@ -1,17 +1,31 @@ #=============================================================================== # @file CMakeLists.txt # @author David Kammer <david.kammer@epfl.ch> # @date Mon Jan 17 11:30:13 2011 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_subdirectory("test_regular_grid_neighbor_structure") add_subdirectory("test_contact_2d_neighbor_structure") \ No newline at end of file diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/CMakeLists.txt index 53c77ab28..0cea93afa 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/CMakeLists.txt @@ -1,18 +1,32 @@ #=============================================================================== # @file CMakeLists.txt # @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> # @date Thu Dec 9 10:19:20 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_mesh(test_contact_2d_neighbor_structure_mesh squares.geo 2 1) register_test(test_contact_2d_neighbor_structure test_contact_2d_neighbor_structure.cc) add_dependencies(test_contact_2d_neighbor_structure test_contact_2d_neighbor_structure_mesh) diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/test_contact_2d_neighbor_structure.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/test_contact_2d_neighbor_structure.cc index c8730f19b..99ec85313 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/test_contact_2d_neighbor_structure.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/test_contact_2d_neighbor_structure.cc @@ -1,239 +1,253 @@ /** * @file test_contact_2d_neighbor_structure.cc * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @date Thu Dec 9 10:07:58 2010 * * @brief Test neighbor structure for 2d with linear triangles * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" using namespace akantu; #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" static void initParaview(Mesh & mesh); static void initParaviewSurface(Mesh & mesh); static void printParaviewSurface(Mesh & mesh, const NeighborList & my_neighbor_list); double * facet_id; double * node_id; DumperParaview dumper_surface; #endif //AKANTU_USE_IOHELPER int main(int argc, char *argv[]) { int spatial_dimension = 2; Real time_factor = 0.2; /// load mesh Mesh mesh(spatial_dimension); MeshIOMSH mesh_io; mesh_io.read("squares.msh", mesh); SolidMechanicsModel * model = new SolidMechanicsModel(mesh); UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); UInt nb_elements = model->getFEM().getMesh().getNbElement(_triangle_3); /// model initialization model->initVectors(); model->readMaterials("materials.dat"); model->initMaterials(); model->initModel(); std::cout << model->getMaterial(0) << std::endl; model->assembleMassLumped(); /// set vectors to zero memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getVelocity().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getAcceleration().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getDisplacement().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getResidual().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getMaterial(0).getStrain(_triangle_3).values, 0, spatial_dimension*spatial_dimension*nb_elements*sizeof(Real)); memset(model->getMaterial(0).getStress(_triangle_3).values, 0, spatial_dimension*spatial_dimension*nb_elements*sizeof(Real)); /// Paraview Helper #ifdef AKANTU_USE_IOHELPER // initParaview(*model); #endif //AKANTU_USE_IOHELPER // /// dump surface information to paraview // #ifdef AKANTU_USE_IOHELPER // DumperParaview dumper; // dumper.SetMode(TEXT); // dumper.SetPoints(mesh.getNodes().values, spatial_dimension, nb_nodes, "triangle_3_test-surface-extraction"); // dumper.SetConnectivity((int*)mesh.getConnectivity(_triangle_3).values, // TRIANGLE1, mesh.getNbElement(_triangle_3), C_MODE); // dumper.SetPrefix("paraview/"); // dumper.Init(); // dumper.Dump(); // #endif //AKANTU_USE_IOHELPER Real time_step = model->getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); /// contact declaration Contact * my_contact = Contact::newContact(*model, _ct_2d_expli, _cst_2d_expli, _cnst_2d_grid); my_contact->initContact(true); my_contact->setFrictionCoefficient(0.); my_contact->initNeighborStructure(); /// get master surfaces with associated neighbor list const std::vector<Surface> & master_surfaces = my_contact->getMasterSurfaces(); std::vector<Surface>::iterator it; // for (it = master_surfaces.begin(); it != master_surfaces.end(); ++it) { #ifdef AKANTU_USE_IOHELPER initParaview(mesh); initParaviewSurface(mesh); #endif //AKANTU_USE_IOHELPER UInt nb_surfaces = mesh.getNbSurfaces(); for (UInt s = 0; s < nb_surfaces; ++s) { const NeighborList & my_neighbor_list = my_contact->getContactSearch().getContactNeighborStructure(s).getNeighborList(); #ifdef AKANTU_USE_IOHELPER printParaviewSurface(mesh, my_neighbor_list); #endif //AKANTU_USE_IOHELPER UInt nb_impactors = my_neighbor_list.impactor_nodes.getSize(); UInt * impactors_val = my_neighbor_list.impactor_nodes.values; UInt * node_facet_off_val = my_neighbor_list.facets_offset[_segment_2]->values; UInt * node_facet_val = my_neighbor_list.facets[_segment_2]->values; /// print impactor nodes std::cout << "Master surface " << s << " has " << nb_impactors << " impactor nodes:" << std::endl; for (UInt i = 0; i < nb_impactors; ++i) { std::cout << " node " << impactors_val[i] << " : "; for (UInt j = node_facet_off_val[i]; j < node_facet_off_val[i+1]; ++j) std::cout << node_facet_val[j] << " "; std::cout << std::endl; } std::cout << std::endl; } // } #ifdef AKANTU_USE_IOHELPER delete [] node_id; delete [] facet_id; #endif //AKANTU_USE_IOHELPER delete my_contact; delete model; finalize(); return EXIT_SUCCESS; } /// Paraview prints #ifdef AKANTU_USE_IOHELPER static void initParaview(Mesh & mesh) { DumperParaview dumper; dumper.SetMode(TEXT); UInt nb_nodes = mesh.getNbNodes(); dumper.SetPoints(mesh.getNodes().values, 2, nb_nodes, "test-2d-neighbor"); dumper.SetConnectivity((int*)mesh.getConnectivity(_triangle_3).values, TRIANGLE1, mesh.getNbElement(_triangle_3), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); } static void initParaviewSurface(Mesh & mesh) { //DumperParaview dumper_surface; dumper_surface.SetMode(TEXT); UInt nb_nodes = mesh.getNbNodes(); dumper_surface.SetPoints(mesh.getNodes().values, 2, nb_nodes, "test-2d-neighbor-surface"); dumper_surface.SetConnectivity((int *)mesh.getConnectivity(_segment_2).values, LINE1, mesh.getNbElement(_segment_2), C_MODE); facet_id = new double [mesh.getConnectivity(_segment_2).getSize()]; memset(facet_id, 0, mesh.getConnectivity(_segment_2).getSize()*sizeof(double)); node_id = new double [nb_nodes]; memset(node_id, 0, nb_nodes*sizeof(double)); dumper_surface.AddElemDataField(facet_id, 1, "master_segments"); dumper_surface.AddNodeDataField(node_id, 1, "slave_nodes"); dumper_surface.SetPrefix("paraview/"); dumper_surface.Init(); dumper_surface.Dump(); // delete [] facet_id; // delete [] node_id; // return dumper_surface; } static void printParaviewSurface(Mesh & mesh, const NeighborList & my_neighbor_list) { UInt nb_impactors = my_neighbor_list.impactor_nodes.getSize(); UInt * impactors_val = my_neighbor_list.impactor_nodes.values; UInt nb_facets = my_neighbor_list.facets[_segment_2]->getSize(); UInt * node_facet_val = my_neighbor_list.facets[_segment_2]->values; // double * node_id = new double [mesh.getNbNodes()]; memset(node_id, 0, mesh.getNbNodes()*sizeof(double)); // double * facet_id = new double [mesh.getConnectivity(_segment_2).getSize()]; memset(facet_id, 0, mesh.getConnectivity(_segment_2).getSize()*sizeof(double)); for (UInt n = 0; n < nb_impactors; ++n) node_id[impactors_val[n]] = 1.; for (UInt el = 0; el < nb_facets; ++el) facet_id[node_facet_val[el]] = 1.; dumper_surface.Dump(); } #endif //AKANTU_USE_IOHELPER diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/CMakeLists.txt index 756082bc0..8d6a298af 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/CMakeLists.txt @@ -1,39 +1,53 @@ #=============================================================================== # @file CMakeLists.txt # @author David Kammer <david.kammer@epfl.ch> # @date Tue Oct 26 16:40:24 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_mesh(test_regular_grid_2d_mesh squares.geo 2 1) register_test(test_regular_grid_triangle_3 test_regular_grid_triangle_3.cc) add_dependencies(test_regular_grid_triangle_3 test_regular_grid_2d_mesh) #=============================================================================== add_mesh(test_regular_grid_3d_mesh cubes.geo 3 1) register_test(test_regular_grid_tetrahedron_4 test_regular_grid_tetrahedron_4.cc) add_dependencies(test_regular_grid_tetrahedron_4 test_regular_grid_3d_mesh) #=============================================================================== #add_mesh(test_regular_grid_3d_mesh cubes.geo 3 1) register_test(test_regular_grid_tetrahedron_4_nodes test_regular_grid_tetrahedron_4_nodes.cc) add_dependencies(test_regular_grid_tetrahedron_4_nodes test_regular_grid_3d_mesh) #=============================================================================== configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/material.dat ${CMAKE_CURRENT_BINARY_DIR}/material.dat COPYONLY ) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_tetrahedron_4.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_tetrahedron_4.cc index e4a51c368..f99b9e04c 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_tetrahedron_4.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_tetrahedron_4.cc @@ -1,146 +1,160 @@ /** * @file test_regular_grid_tetrahedron_4.cc * @author David Kammer <david.kammer@epfl.ch> * @date Tue Oct 26 16:58:42 2010 * * @brief test regular grid neighbor structure for 3d case * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 3; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("cubes.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); unsigned int nb_nodes = my_mesh.getNbNodes(); /// dump facet information to paraview #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_mesh.getNodes().values, dim, nb_nodes, "tetrahedron_4_test-surface-extraction"); dumper.SetConnectivity((int*)my_mesh.getConnectivity(_tetrahedron_4).values, TETRA1, my_mesh.getNbElement(_tetrahedron_4), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, 3*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, 3*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, 3*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, 3*nb_nodes*sizeof(Real)); my_model.readMaterials("material.dat"); my_model.initMaterials(); my_model.initModel(); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * my_contact = Contact::newContact(my_model, _ct_3d_expli, _cst_2d_expli, _cnst_regular_grid); // how to use contact and contact search types for testing the reg grid with normal nl? my_contact->initContact(false); Surface master = 0; my_contact->addMasterSurface(master); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); const NeighborList & my_neighbor_list = my_contact->getContactSearch().getContactNeighborStructure(master).getNeighborList(); UInt nb_nodes_neigh = my_neighbor_list.impactor_nodes.getSize(); Vector<UInt> impact_nodes = my_neighbor_list.impactor_nodes; UInt * impact_nodes_val = impact_nodes.values; UInt * node_to_elem_offset_val = my_neighbor_list.facets_offset[_triangle_3]->values; UInt * node_to_elem_val = my_neighbor_list.facets[_triangle_3]->values; /// print impactor nodes std::cout << "we have " << nb_nodes_neigh << " impactor nodes:" << std::endl; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " node " << impact_nodes_val[i] << " : "; for (UInt j = node_to_elem_offset_val[i]; j < node_to_elem_offset_val[i+1]; ++j) std::cout << node_to_elem_val[j] << " "; std::cout << std::endl; } std::cout << std::endl; #ifdef AKANTU_USE_IOHELPER DumperParaview dumper_neighbor; dumper_neighbor.SetMode(TEXT); dumper_neighbor.SetPoints(my_mesh.getNodes().values, dim, nb_nodes, "tetrahedron_4_test-neighbor-elements"); dumper_neighbor.SetConnectivity((int *)my_mesh.getConnectivity(_triangle_3).values, TRIANGLE1, my_mesh.getNbElement(_triangle_3), C_MODE); double * neigh_elem = new double [my_mesh.getNbElement(_triangle_3)]; for (UInt i = 0; i < my_mesh.getNbElement(_triangle_3); ++i) neigh_elem[i] = 0.0; UInt visualize_node = 7; UInt n = impact_nodes_val[visualize_node]; std::cout << "plot for node: " << n << std::endl; for (UInt i = node_to_elem_offset_val[visualize_node]; i < node_to_elem_offset_val[visualize_node+1]; ++i) neigh_elem[node_to_elem_val[i]] = 1.; dumper_neighbor.AddElemDataField(neigh_elem, 1, "neighbor id"); dumper_neighbor.SetPrefix("paraview/"); dumper_neighbor.Init(); dumper_neighbor.Dump(); delete [] neigh_elem; #endif //AKANTU_USE_IOHELPER delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_tetrahedron_4_nodes.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_tetrahedron_4_nodes.cc index 4199a0d79..bc4e37689 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_tetrahedron_4_nodes.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_tetrahedron_4_nodes.cc @@ -1,127 +1,141 @@ /** * @file test_regular_grid_tetrahedron_4_nodes.cc * @author David Kammer <david.kammer@epfl.ch> * @date Tue Oct 26 16:58:42 2010 * * @brief test regular grid neighbor structure for 3d case * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 3; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("cubes.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); unsigned int nb_nodes = my_mesh.getNbNodes(); /// dump facet and surface information to paraview #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_mesh.getNodes().values, dim, nb_nodes, "tetrahedron_4_nodes_test-surface-extraction"); dumper.SetConnectivity((int*)my_mesh.getConnectivity(_tetrahedron_4).values, TETRA1, my_mesh.getNbElement(_tetrahedron_4), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, 3*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, 3*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, 3*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, 3*nb_nodes*sizeof(Real)); my_model.readMaterials("material.dat"); my_model.initMaterials(); my_model.initModel(); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * my_contact = Contact::newContact(my_model, _ct_3d_expli, _cst_3d_expli, _cnst_regular_grid); my_contact->initContact(false); Surface master = 0; my_contact->addMasterSurface(master); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); const NodesNeighborList & my_neighbor_list = dynamic_cast<const NodesNeighborList &>(my_contact->getContactSearch().getContactNeighborStructure(master).getNeighborList()); UInt nb_nodes_neigh = my_neighbor_list.impactor_nodes.getSize(); Vector<UInt> impact_nodes = my_neighbor_list.impactor_nodes; UInt * impact_nodes_val = impact_nodes.values; /// print impactor nodes std::cout << "we have " << nb_nodes_neigh << " impactor nodes:"; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " " << impact_nodes_val[i]; } std::cout << std::endl; UInt * master_nodes_offset_val = my_neighbor_list.master_nodes_offset.values; UInt * master_nodes_val = my_neighbor_list.master_nodes.values; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " Impactor node: " << impact_nodes_val[i] << " has master nodes:"; for(UInt mn = master_nodes_offset_val[i]; mn < master_nodes_offset_val[i+1]; ++mn) { std::cout << " " << master_nodes_val[mn]; } std::cout << std::endl; } delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_triangle_3.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_triangle_3.cc index 4fe7218ed..1b3e96ba2 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_triangle_3.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_triangle_3.cc @@ -1,142 +1,156 @@ /** * @file test_regular_grid_triangle_3.cc * @author David Kammer <david.kammer@epfl.ch> * @date Tue Oct 26 16:58:42 2010 * * @brief test regular grid neighbor structure for 3d case * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 2; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("squares.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); unsigned int nb_nodes = my_mesh.getNbNodes(); /// dump surface information to paraview #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_mesh.getNodes().values, dim, nb_nodes, "triangle_3_test-surface-extraction"); dumper.SetConnectivity((int*)my_mesh.getConnectivity(_triangle_3).values, TRIANGLE1, my_mesh.getNbElement(_triangle_3), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); /// initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); my_model.readMaterials("material.dat"); my_model.initMaterials(); my_model.initModel(); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * my_contact = Contact::newContact(my_model, _ct_2d_expli, _cst_2d_expli, _cnst_regular_grid); my_contact->initContact(false); Surface master = 0; my_contact->addMasterSurface(master); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); const NeighborList & my_neighbor_list = my_contact->getContactSearch().getContactNeighborStructure(master).getNeighborList(); UInt nb_nodes_neigh = my_neighbor_list.impactor_nodes.getSize(); Vector<UInt> impact_nodes = my_neighbor_list.impactor_nodes; UInt * impact_nodes_val = impact_nodes.values; UInt * node_to_elem_offset_val = my_neighbor_list.facets_offset[_segment_2]->values; UInt * node_to_elem_val = my_neighbor_list.facets[_segment_2]->values; /// print impactor nodes std::cout << "we have " << nb_nodes_neigh << " impactor nodes:" << std::endl; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " node " << impact_nodes_val[i] << " : "; for (UInt j = node_to_elem_offset_val[i]; j < node_to_elem_offset_val[i+1]; ++j) std::cout << node_to_elem_val[j] << " "; std::cout << std::endl; } std::cout << std::endl; #ifdef AKANTU_USE_IOHELPER DumperParaview dumper_neighbor; dumper_neighbor.SetMode(TEXT); dumper_neighbor.SetPoints(my_mesh.getNodes().values, dim, nb_nodes, "triangle_3_test-neighbor-elements"); dumper_neighbor.SetConnectivity((int *)my_mesh.getConnectivity(_segment_2).values, LINE1, my_mesh.getNbElement(_segment_2), C_MODE); double * neigh_elem = new double [my_mesh.getNbElement(_segment_2)]; for (UInt i = 0; i < my_mesh.getNbElement(_segment_2); ++i) neigh_elem[i] = 0.0; UInt visualize_node = 1; UInt n = impact_nodes_val[visualize_node]; std::cout << "plot for node: " << n << std::endl; for (UInt i = node_to_elem_offset_val[visualize_node]; i < node_to_elem_offset_val[visualize_node+1]; ++i) neigh_elem[node_to_elem_val[i]] = 1.; dumper_neighbor.AddElemDataField(neigh_elem, 1, "neighbor id"); dumper_neighbor.SetPrefix("paraview/"); dumper_neighbor.Init(); dumper_neighbor.Dump(); delete [] neigh_elem; #endif //AKANTU_USE_IOHELPER finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt index e828cf660..2042c6759 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_materials/CMakeLists.txt @@ -1,34 +1,48 @@ #=============================================================================== # @file CMakeLists.txt # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== add_mesh(test_local_material_square_mesh triangle.geo 2 2) add_mesh(test_local_material_circle_mesh circle.geo 2 2) add_mesh(test_local_material_bar_mesh bar.geo 2 2) add_mesh(test_local_material_barre_trou_mesh barre_trou.geo 2 2) register_test(test_local_material material_damage.cc test_local_material.cc) add_dependencies(test_local_material test_local_material_square_mesh test_local_material_circle_mesh test_local_material_bar_mesh test_local_material_barre_trou_mesh ) #=============================================================================== configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/material.dat ${CMAKE_CURRENT_BINARY_DIR}/material.dat COPYONLY ) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) \ No newline at end of file diff --git a/test/test_model/test_solid_mechanics_model/test_materials/material_damage.cc b/test/test_model/test_solid_mechanics_model/test_materials/material_damage.cc index 8f064eea1..9f40ad4a3 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/material_damage.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/material_damage.cc @@ -1,143 +1,157 @@ /** * @file material_damage.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 11:53:52 2010 * * @brief Specialization of the material class for the damage material * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "material_damage.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MaterialDamage::MaterialDamage(SolidMechanicsModel & model, const MaterialID & id) : Material(model, id) { AKANTU_DEBUG_IN(); rho = 0; E = 0; nu = 1./2.; Yd = 50; Sd = 5000; for(UInt t = _not_defined; t < _max_element_type; ++t) this->damage[t] = NULL; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialDamage::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); const Mesh::ConnectivityTypeList & type_list = model->getFEM().getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; std::stringstream sstr_damage; sstr_damage << id << ":damage:" << *it; damage[*it] = &(alloc<Real>(sstr_damage.str(), 0, 1, REAL_INIT_VALUE)); } lambda = nu * E / ((1 + nu) * (1 - 2*nu)); mu = E / (2 * (1 + nu)); kpa = lambda + 2./3. * mu; is_init = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialDamage::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real F[3*3]; Real sigma[3*3]; damage[el_type]->resize(FEM::getNbQuadraturePoints(el_type)*element_filter[el_type]->getSize()); Real * dam = damage[el_type]->values; MATERIAL_QUADRATURE_POINT_LOOP_BEGIN; memset(F, 0, 3 * 3 * sizeof(Real)); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) F[3*i + j] = strain_val[spatial_dimension * i + j]; for (UInt i = 0; i < spatial_dimension; ++i) F[i*3 + i] -= 1; computeStress(F, sigma,*dam); ++dam; for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) stress_val[spatial_dimension*i + j] = sigma[3 * i + j]; MATERIAL_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialDamage::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if(ghost_type != _not_ghost) return; Real * epot = potential_energy[el_type]->values; MATERIAL_QUADRATURE_POINT_LOOP_BEGIN; computePotentialEnergy(strain_val, stress_val, epot); epot++; MATERIAL_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialDamage::setParam(const std::string & key, const std::string & value, const MaterialID & id) { std::stringstream sstr(value); if(key == "rho") { sstr >> rho; } else if(key == "E") { sstr >> E; } else if(key == "nu") { sstr >> nu; } else if(key == "Yd") { sstr >> Yd; } else if(key == "Sd") { sstr >> Sd; } else { Material::setParam(key, value, id); } } /* -------------------------------------------------------------------------- */ void MaterialDamage::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Material<_damage> [" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + name : " << name << std::endl; stream << space << " + density : " << rho << std::endl; stream << space << " + Young's modulus : " << E << std::endl; stream << space << " + Poisson's ratio : " << nu << std::endl; stream << space << " + Yd : " << Yd << std::endl; stream << space << " + Sd : " << Sd << std::endl; if(is_init) { stream << space << " + First Lamé coefficient : " << lambda << std::endl; stream << space << " + Second Lamé coefficient : " << mu << std::endl; stream << space << " + Bulk coefficient : " << kpa << std::endl; } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/test/test_model/test_solid_mechanics_model/test_materials/material_damage.hh b/test/test_model/test_solid_mechanics_model/test_materials/material_damage.hh index 762dbfa7c..4049aa1fc 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/material_damage.hh +++ b/test/test_model/test_solid_mechanics_model/test_materials/material_damage.hh @@ -1,117 +1,131 @@ /** * @file material_damage.hh * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Jul 29 15:00:59 2010 * * @brief Material isotropic elastic * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_DAMAGE_HH__ #define __AKANTU_MATERIAL_DAMAGE_HH__ __BEGIN_AKANTU__ class MaterialDamage : public Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialDamage(SolidMechanicsModel & model, const MaterialID & id = ""); virtual ~MaterialDamage() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); void setParam(const std::string & key, const std::string & value, const MaterialID & id); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// constitutive law for a given quadrature point inline void computeStress(Real * F, Real * sigma,Real & damage); /// compute the potential energy for all elements void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the potential energy for on element inline void computePotentialEnergy(Real * F, Real * sigma, Real * epot); /// compute the celerity of wave in the material inline Real celerity(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the stable time step inline Real getStableTimeStep(Real h); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Damage, damage, const Vector<Real> &); private: /// the young modulus Real E; /// Poisson coefficient Real nu; /// First Lamé coefficient Real lambda; /// Second Lamé coefficient (shear modulus) Real mu; /// resistance to damage Real Yd; /// damage threshold Real Sd; /// Bulk modulus Real kpa; /// damage internal variable ByElementTypeReal damage; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_damage_inline_impl.cc" /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const MaterialDamage & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_MATERIAL_DAMAGE_HH__ */ diff --git a/test/test_model/test_solid_mechanics_model/test_materials/material_damage_inline_impl.cc b/test/test_model/test_solid_mechanics_model/test_materials/material_damage_inline_impl.cc index 14c92bc8a..c7517faac 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/material_damage_inline_impl.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/material_damage_inline_impl.cc @@ -1,76 +1,90 @@ /** * @file material_damage_inline_impl.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 11:57:43 2010 * * @brief Implementation of the inline functions of the material damage * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ inline void MaterialDamage::computeStress(Real * F, Real * sigma, Real & dam) { Real trace = F[0] + F[4] + F[8]; /// \F_{11} + \F_{22} + \F_{33} /// \sigma_{ij} = \lamda * \F_{kk} * \delta_{ij} + 2 * \mu * \F_{ij} sigma[0] = lambda * trace + 2*mu*F[0]; sigma[4] = lambda * trace + 2*mu*F[4]; sigma[8] = lambda * trace + 2*mu*F[8]; sigma[1] = sigma[3] = mu * (F[1] + F[3]); sigma[2] = sigma[6] = mu * (F[2] + F[6]); sigma[5] = sigma[7] = mu * (F[5] + F[7]); Real Y = sigma[0]*F[0] + sigma[1]*F[1] + sigma[2]*F[2] + sigma[3]*F[3] + sigma[4]*F[4] + sigma[5]*F[5] + sigma[6]*F[6] + sigma[7]*F[7] + sigma[8]*F[8]; Y *= 0.5; Real Fd = Y - Yd - Sd*dam; if (Fd > 0) dam = (Y - Yd) / Sd; dam = std::min(dam,1.); sigma[0] *= 1-dam; sigma[4] *= 1-dam; sigma[8] *= 1-dam; sigma[1] *= 1-dam; sigma[3] *= 1-dam; sigma[2] *= 1-dam; sigma[6] *= 1-dam; sigma[5] *= 1-dam; sigma[7] *= 1-dam; } /* -------------------------------------------------------------------------- */ inline void MaterialDamage::computePotentialEnergy(Real * F, Real * sigma, Real * epot) { *epot = 0.; for (UInt i = 0, t = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j, ++t) *epot += sigma[t] * (F[t] - (i == j)); *epot *= .5; } /* -------------------------------------------------------------------------- */ inline Real MaterialDamage::celerity() { return sqrt(E/rho); } /* -------------------------------------------------------------------------- */ inline Real MaterialDamage::getStableTimeStep(Real h) { return (h/celerity()); } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc index bd672af20..eb933cf8e 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc @@ -1,142 +1,156 @@ /** * @file test_solid_mechanics_model.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 14:34:13 2010 * * @brief test of the class SolidMechanicsModel * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "fem.hh" #include "material_damage.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; akantu::Real eps = 1e-10; static void trac(__attribute__ ((unused)) double * position,double * stress){ memset(stress, 0, sizeof(Real)*4); if (fabs(position[0] - 10) < eps){ stress[0] = 3e6; stress[3] = 3e6; } } int main(int argc, char *argv[]) { UInt max_steps = 20000; Real epot, ekin; Real bar_height = 4.; const UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); MeshIOMSH mesh_io; // mesh_io.read("bar.msh", mesh); mesh_io.read("barre_trou.msh", mesh); SolidMechanicsModel * model = new SolidMechanicsModel(mesh); /// model initialization model->initVectors(); UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); memset(model->getForce().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getVelocity().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getAcceleration().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getDisplacement().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getResidual().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getMass().values, 1, nb_nodes*sizeof(Real)); model->readCustomMaterial<MaterialDamage>("material.dat","DAMAGE"); model->initMaterials(); model->initModel(); Real time_step = model->getStableTimeStep(); model->setTimeStep(time_step/10.); model->assembleMassLumped(); std::cout << *model << std::endl; /// Dirichlet boundary conditions for (akantu::UInt i = 0; i < nb_nodes; ++i) { if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] <= eps) model->getBoundary().values[spatial_dimension*i] = true; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] <= eps || model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] >= bar_height - eps ) { model->getBoundary().values[spatial_dimension*i + 1] = true; } } FEM & fem_boundary = model->getFEMBoundary(); fem_boundary.initShapeFunctions(); fem_boundary.computeNormalsOnQuadPoints(); model->computeForcesFromFunction(trac, akantu::_bft_stress); #ifdef AKANTU_USE_IOHELPER model->updateResidual(); DumperParaview dumper; dumper.SetMode(BASE64); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, 2, nb_nodes, "coordinates"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(_triangle_6).values, TRIANGLE2, model->getFEM().getMesh().getNbElement(_triangle_6), C_MODE); dumper.AddNodeDataField(model->getDisplacement().values, 2, "displacements"); dumper.AddNodeDataField(model->getVelocity().values, 2, "velocity"); dumper.AddNodeDataField(model->getForce().values, 2, "force"); dumper.AddNodeDataField(model->getMass().values, 1, "Mass"); dumper.AddNodeDataField(model->getResidual().values, 2, "residual"); dumper.AddElemDataField(model->getMaterial(0).getStrain(_triangle_6).values, 4, "strain"); dumper.AddElemDataField(model->getMaterial(0).getStress(_triangle_6).values, 4, "stress"); MaterialDamage & mat = dynamic_cast<MaterialDamage&>(model->getMaterial(0)); Real * dam = mat.getDamage(_triangle_6).values; dumper.AddElemDataField(dam, 1, "damage"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("force", 1); dumper.SetEmbeddedValue("residual", 1); dumper.SetEmbeddedValue("velocity", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER for(UInt s = 0; s < max_steps; ++s) { model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); epot = model->getPotentialEnergy(); ekin = model->getKineticEnergy(); std::cout << s << " " << epot << " " << ekin << " " << epot + ekin << std::endl; #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model.cc index 3961c6bec..b8b2a0123 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model.cc @@ -1,196 +1,210 @@ /** * @file test_solid_mechanics_model.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 14:34:13 2010 * * @brief test of the class SolidMechanicsModel * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "fem.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; void trac(double * position,double * traction){ memset(traction,0,sizeof(Real)*4); traction[0] = 1000; traction[3] = 1000; // if(fabs(position[0])< 1e-4){ // traction[0] = -position[1]; // } } int main(int argc, char *argv[]) { UInt max_steps = 1; Real epot, ekin; Mesh mesh(2); MeshIOMSH mesh_io; mesh_io.read("triangle.msh", mesh); SolidMechanicsModel * model = new SolidMechanicsModel(mesh); /// model initialization model->initVectors(); UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); memset(model->getForce().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getVelocity().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getAcceleration().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getDisplacement().values, 0, 2*nb_nodes*sizeof(Real)); model->readMaterials("material.dat"); model->initMaterials(); model->initModel(); Real time_step = model->getStableTimeStep(); model->setTimeStep(time_step/10.); model->assembleMass(); std::cout << *model << std::endl; /// boundary conditions // Real eps = 1e-16; // for (UInt i = 0; i < nb_nodes; ++i) { // model->getDisplacement().values[2*i] = model->getFEM().getMesh().getNodes().values[2*i] / 100.; // if(model->getFEM().getMesh().getNodes().values[2*i] <= eps) { // model->getBoundary().values[2*i ] = true; // if(model->getFEM().getMesh().getNodes().values[2*i + 1] <= eps) // model->getBoundary().values[2*i + 1] = true; // } // if(model->getFEM().getMesh().getNodes().values[2*i + 1] <= eps) { // model->getBoundary().values[2*i + 1] = true; // } // } FEM & fem_boundary = model->getFEMBoundary(); fem_boundary.initShapeFunctions(); fem_boundary.computeNormalsOnQuadPoints(); model->computeForcesFromFunction(trac,0); // const Mesh::ConnectivityTypeList & type_list = fem_boundary.getMesh().getConnectivityTypeList(); // Mesh::ConnectivityTypeList::const_iterator it; // for(it = type_list.begin(); it != type_list.end(); ++it) { // if(Mesh::getSpatialDimension(*it) != fem_boundary.getElementDimension()) continue; // // ElementType facet_type = Mesh::getFacetElementType(*it); // UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); // UInt nb_quad = FEM::getNbQuadraturePoints(*it); // UInt nb_element; // const Vector<Real> * shapes; // Vector<Real> quad_coords(0,2,"quad_coords"); // const Vector<Real> * normals_on_quad; // nb_element = fem_boundary.getMesh().getNbElement(*it); // fem_boundary.interpolateOnQuadraturePoints(mesh.getNodes(), quad_coords, 2, _segment_2); // normals_on_quad = &(fem_boundary.getNormalsOnQuadPoints(*it)); // shapes = &(fem_boundary.getShapes(*it)); // Vector<Real> * sigma_funct = new Vector<Real>(nb_element, 4*nb_quad, "myfunction"); // Vector<Real> * funct = new Vector<Real>(nb_element, 2*nb_quad, "myfunction"); // Real * sigma_funct_val = sigma_funct->values; // Real * shapes_val = shapes->values; // /// compute t * \phi_i for each nodes of each element // for (UInt el = 0; el < nb_element; ++el) { // for (UInt q = 0; q < nb_quad; ++q) { // trac(quad_coords.values+el*nb_quad*2+q,sigma_funct_val); // sigma_funct_val += 4; // } // } // Math::matrix_vector(2,2,*sigma_funct,*normals_on_quad,*funct); // funct->extendComponentsInterlaced(nb_nodes_per_element,2); // Real * funct_val = funct->values; // for (UInt el = 0; el < nb_element; ++el) { // for (UInt q = 0; q < nb_quad; ++q) { // for (UInt n = 0; n < nb_nodes_per_element; ++n) { // *funct_val++ *= *shapes_val; // *funct_val++ *= *shapes_val++; // } // } // } // Vector<Real> * int_funct = new Vector<Real>(nb_element, 2*nb_nodes_per_element, // "inte_funct"); // fem_boundary.integrate(*funct, *int_funct, 2*nb_nodes_per_element, *it); // delete funct; // fem_boundary.assembleVector(*int_funct,model->getForce(), 2, *it); // delete int_funct; // } // model->getDisplacement().values[1] = 0.1; #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, 2, nb_nodes, "coordinates"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(_triangle_3).values, TRIANGLE1, model->getFEM().getMesh().getNbElement(_triangle_3), C_MODE); dumper.AddNodeDataField(model->getDisplacement().values, 2, "displacements"); dumper.AddNodeDataField(model->getVelocity().values, 2, "velocity"); dumper.AddNodeDataField(model->getForce().values, 2, "force"); dumper.AddNodeDataField(model->getResidual().values, 2, "residual"); dumper.AddElemDataField(model->getMaterial(0).getStrain(_triangle_3).values, 4, "strain"); dumper.AddElemDataField(model->getMaterial(0).getStress(_triangle_3).values, 4, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("force", 1); dumper.SetPrefix("paraview/"); dumper.Init(); #endif //AKANTU_USE_IOHELPER model->setPotentialEnergyFlagOn(); for(UInt s = 0; s < max_steps; ++s) { model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); epot = model->getPotentialEnergy(); ekin = model->getKineticEnergy(); std::cout << s << " " << epot << " " << ekin << " " << epot + ekin << std::endl; #ifdef AKANTU_USE_IOHELPER if(s % 10 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.cc index 25f21b832..684548eae 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.cc @@ -1,221 +1,235 @@ /** * @file test_solid_mechanics_model.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 14:34:13 2010 * * @brief test of the class SolidMechanicsModel * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER //#define CHECK_STRESS int main(int argc, char *argv[]) { #ifdef AKANTU_USE_IOHELPER akantu::ElementType type = akantu::_triangle_6; akantu::UInt paraview_type = TRIANGLE2; #endif //AKANTU_USE_IOHELPER akantu::UInt spatial_dimension = 2; akantu::UInt max_steps = 10000; akantu::Real time_factor = 0.2; // akantu::Real epot, ekin; akantu::Mesh mesh(spatial_dimension); akantu::MeshIOMSH mesh_io; mesh_io.read("bar2.msh", mesh); akantu::SolidMechanicsModel * model = new akantu::SolidMechanicsModel(mesh); akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); #ifdef AKANTU_USE_IOHELPER akantu::UInt nb_element = model->getFEM().getMesh().getNbElement(type); #endif //AKANTU_USE_IOHELPER /// model initialization model->initVectors(); /// set vectors to 0 memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getVelocity().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getAcceleration().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getDisplacement().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); model->readMaterials("material.dat"); model->initMaterials(); model->initModel(); std::cout << model->getMaterial(0) << std::endl; model->assembleMassLumped(); #ifdef AKANTU_USE_IOHELPER /// set to 0 only for the first paraview dump memset(model->getResidual().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getMaterial(0).getStrain(type).values, 0, spatial_dimension*spatial_dimension*nb_element*sizeof(akantu::Real)); memset(model->getMaterial(0).getStress(type).values, 0, spatial_dimension*spatial_dimension*nb_element*sizeof(akantu::Real)); #endif //AKANTU_USE_IOHELPER /// boundary conditions akantu::Real eps = 1e-16; for (akantu::UInt i = 0; i < nb_nodes; ++i) { if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] >= 9) model->getDisplacement().values[spatial_dimension*i] = (model->getFEM().getMesh().getNodes().values[spatial_dimension*i] - 9) / 100. ; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] <= eps) model->getBoundary().values[spatial_dimension*i] = true; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] <= eps || model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] >= 1 - eps ) { model->getBoundary().values[spatial_dimension*i + 1] = true; } } /// set the time step akantu::Real time_step = model->getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, "coordinates"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(model->getDisplacement().values, spatial_dimension, "displacements"); dumper.AddNodeDataField(model->getVelocity().values, spatial_dimension, "velocity"); dumper.AddNodeDataField(model->getResidual().values, spatial_dimension, "force"); dumper.AddNodeDataField(model->getForce().values, spatial_dimension, "applied_force"); dumper.AddElemDataField(model->getMaterial(0).getStrain(type).values, spatial_dimension*spatial_dimension, "strain"); dumper.AddElemDataField(model->getMaterial(0).getStress(type).values, spatial_dimension*spatial_dimension, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER #ifdef CHECK_STRESS std::ofstream outfile; outfile.open("stress"); #endif // CHECK_STRESS std::ofstream energy; energy.open("energy.csv"); energy << "id,epot,ekin,tot" << std::endl; for(akantu::UInt s = 1; s <= max_steps; ++s) { model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); akantu::Real epot = model->getPotentialEnergy(); akantu::Real ekin = model->getKineticEnergy(); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; #ifdef CHECK_STRESS /// search the position of the maximum of stress to determine the wave speed akantu::Real max_stress = std::numeric_limits<akantu::Real>::min(); akantu::Real * stress = model->getMaterial(0).getStress(type).values; for (akantu::UInt i = 0; i < nb_element; ++i) { if(max_stress < stress[i*spatial_dimension*spatial_dimension]) { max_stress = stress[i*spatial_dimension*spatial_dimension]; } } akantu::Real * coord = model->getFEM().getMesh().getNodes().values; akantu::Real * disp_val = model->getDisplacement().values; akantu::UInt * conn = model->getFEM().getMesh().getConnectivity(type).values; akantu::UInt nb_nodes_per_element = model->getFEM().getMesh().getNbNodesPerElement(type); akantu::Real * coords = new akantu::Real[spatial_dimension]; akantu::Real min_x = std::numeric_limits<akantu::Real>::max(); akantu::Real max_x = std::numeric_limits<akantu::Real>::min(); akantu::Real stress_range = 5e7; for (akantu::UInt el = 0; el < nb_element; ++el) { if(stress[el*spatial_dimension*spatial_dimension] > max_stress - stress_range) { akantu::UInt el_offset = el * nb_nodes_per_element; memset(coords, 0, spatial_dimension*sizeof(akantu::Real)); for (akantu::UInt n = 0; n < nb_nodes_per_element; ++n) { for (akantu::UInt i = 0; i < spatial_dimension; ++i) { akantu::UInt node = conn[el_offset + n] * spatial_dimension; coords[i] += (coord[node + i] + disp_val[node + i]) / ((akantu::Real) nb_nodes_per_element); } } min_x = min_x < coords[0] ? min_x : coords[0]; max_x = max_x > coords[0] ? max_x : coords[0]; } } outfile << s << " " << .5 * (min_x + max_x) << " " << min_x << " " << max_x << " " << max_x - min_x << " " << max_stress << std::endl; delete [] coords; #endif // CHECK_STRESS #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } energy.close(); #ifdef CHECK_STRESS outfile.close(); #endif // CHECK_STRESS delete model; akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.cc index 9141b6a82..17a1e8833 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.cc @@ -1,221 +1,235 @@ /** * @file test_solid_mechanics_model.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 14:34:13 2010 * * @brief test of the class SolidMechanicsModel * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "static_communicator.hh" #include "communicator.hh" #include "mesh_partition_scotch.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER int main(int argc, char *argv[]) { #ifdef AKANTU_USE_IOHELPER akantu::ElementType type = akantu::_triangle_6; #endif //AKANTU_USE_IOHELPER akantu::UInt spatial_dimension = 2; akantu::UInt max_steps = 5000; akantu::Real time_factor = 0.8; akantu::initialize(&argc, &argv); akantu::debug::setDebugLevel(akantu::dblWarning); // akantu::Real epot, ekin; akantu::Mesh mesh(spatial_dimension); akantu::StaticCommunicator * comm = akantu::StaticCommunicator::getStaticCommunicator(); akantu::Int psize = comm->getNbProc(); akantu::Int prank = comm->whoAmI(); /* ------------------------------------------------------------------------ */ /* Parallel initialization */ /* ------------------------------------------------------------------------ */ akantu::Communicator * communicator; if(prank == 0) { akantu::MeshIOMSH mesh_io; mesh_io.read("bar2.msh", mesh); akantu::MeshPartition * partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); communicator = akantu::Communicator::createCommunicatorDistributeMesh(mesh, partition); delete partition; } else { communicator = akantu::Communicator::createCommunicatorDistributeMesh(mesh, NULL); } akantu::SolidMechanicsModel * model = new akantu::SolidMechanicsModel(mesh); akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); #ifdef AKANTU_USE_IOHELPER akantu::UInt nb_element = model->getFEM().getMesh().getNbElement(type); #endif //AKANTU_USE_IOHELPER /* ------------------------------------------------------------------------ */ /* Initialization */ /* ------------------------------------------------------------------------ */ /// model initialization model->initVectors(); /// set vectors to 0 memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getResidual().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getVelocity().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getAcceleration().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getDisplacement().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); model->readMaterials("material.dat"); model->initMaterials(); model->registerSynchronizer(*communicator); model->initModel(); if(prank == 0) std::cout << model->getMaterial(0) << std::endl; model->assembleMassLumped(); /* ------------------------------------------------------------------------ */ /* Boundary + initial conditions */ /* ------------------------------------------------------------------------ */ akantu::Real eps = 1e-16; for (akantu::UInt i = 0; i < nb_nodes; ++i) { // model->getDisplacement().values[spatial_dimension*i] // = model->getFEM().getMesh().getNodes().values[spatial_dimension*i] / 100.; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] >= 9) model->getDisplacement().values[spatial_dimension*i] = (model->getFEM().getMesh().getNodes().values[spatial_dimension*i] - 9) / 100.; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] <= eps) model->getBoundary().values[spatial_dimension*i] = true; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] <= eps || model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] >= 1 - eps ) { model->getBoundary().values[spatial_dimension*i + 1] = true; } } model->synchronizeBoundaries(); #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetParallelContext(prank, psize); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, "bar2d_para"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type).values, TRIANGLE2, nb_element, C_MODE); dumper.AddNodeDataField(model->getDisplacement().values, spatial_dimension, "displacements"); dumper.AddNodeDataField(model->getMass().values, 1, "mass"); dumper.AddNodeDataField(model->getVelocity().values, spatial_dimension, "velocity"); dumper.AddNodeDataField(model->getResidual().values, spatial_dimension, "force"); dumper.AddNodeDataField(model->getAcceleration().values, spatial_dimension, "acceleration"); dumper.AddElemDataField(model->getMaterial(0).getStrain(type).values, spatial_dimension*spatial_dimension, "strain"); dumper.AddElemDataField(model->getMaterial(0).getStress(type).values, spatial_dimension*spatial_dimension, "stress"); akantu::UInt nb_quadrature_points = akantu::FEM::getNbQuadraturePoints(type); double * part = new double[nb_element*nb_quadrature_points]; for (unsigned int i = 0; i < nb_element; ++i) for (unsigned int q = 0; q < nb_quadrature_points; ++q) part[i*nb_quadrature_points + q] = prank; dumper.AddElemDataField(part, 1, "partitions"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream energy; if(prank == 0) { energy.open("energy.csv"); energy << "id,epot,ekin,tot" << std::endl; } double total_time = 0.; /// Setting time step akantu::Real time_step = model->getStableTimeStep() * time_factor; if(prank == 0) std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(akantu::UInt s = 1; s <= max_steps; ++s) { double start = MPI_Wtime(); model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); double end = MPI_Wtime(); akantu::Real epot = model->getPotentialEnergy(); akantu::Real ekin = model->getKineticEnergy(); total_time += end - start; if(prank == 0 && (s % 10 == 0)) { std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; } #ifdef AKANTU_USE_IOHELPER if(s % 10 == 0) { dumper.Dump(); } #endif //AKANTU_USE_IOHELPER } if(prank == 0) std::cout << "Time : " << psize << " " << total_time / max_steps << " " << total_time << std::endl; #ifdef AKANTU_USE_IOHELPER delete [] part; #endif //AKANTU_USE_IOHELPER delete model; akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured.cc index b4652c2bd..e8501dfe8 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_structured.cc @@ -1,112 +1,126 @@ /** * @file test_solid_mechanics_model.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 14:34:13 2010 * * @brief test of the class SolidMechanicsModel * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER int main(int argc, char *argv[]) { akantu::UInt spatial_dimension = 2; akantu::UInt max_steps = 10000; akantu::Real time_factor = 0.2; akantu::Real epot, ekin; akantu::Mesh mesh(spatial_dimension); akantu::MeshIOMSH mesh_io; mesh_io.read("bar_structured1.msh", mesh); akantu::SolidMechanicsModel * model = new akantu::SolidMechanicsModel(mesh); /// model initialization model->initVectors(); /// set vectors to 0 akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getVelocity().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getAcceleration().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getDisplacement().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); model->readMaterials("material.dat"); model->initMaterials(); model->initModel(); std::cout << model->getMaterial(0) << std::endl; model->assembleMassLumped(); /// boundary conditions akantu::Real eps = 1e-16; for (akantu::UInt i = 0; i < nb_nodes; ++i) { if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] >= 9) model->getDisplacement().values[spatial_dimension*i] = (model->getFEM().getMesh().getNodes().values[spatial_dimension*i] - 9) / 100. ; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] <= eps) model->getBoundary().values[spatial_dimension*i] = true; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] <= eps || model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] >= 1 - eps ) { model->getBoundary().values[spatial_dimension*i + 1] = true; } } akantu::Real time_step = model->getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); std::ofstream energy; energy.open("energy.csv"); energy << "id,epot,ekin,tot" << std::endl; for(akantu::UInt s = 1; s <= max_steps; ++s) { model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); epot = model->getPotentialEnergy(); ekin = model->getKineticEnergy(); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; } energy.close(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_circle_2.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_circle_2.cc index 0d7d419ab..8b5c8a563 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_circle_2.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_circle_2.cc @@ -1,117 +1,131 @@ /** * @file test_solid_mechanics_model.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 14:34:13 2010 * * @brief test of the class SolidMechanicsModel * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "fem.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; static void trac(__attribute__ ((unused)) double * position,double * stress){ memset(stress,0,sizeof(Real)*4); stress[0] = 1000; stress[3] = 1000; } int main(int argc, char *argv[]) { UInt max_steps = 10000; Real epot, ekin; Mesh mesh(2); MeshIOMSH mesh_io; mesh_io.read("circle2.msh", mesh); SolidMechanicsModel * model = new SolidMechanicsModel(mesh); /// model initialization model->initVectors(); UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); memset(model->getForce().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getVelocity().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getAcceleration().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getDisplacement().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getResidual().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getMass().values, 1, nb_nodes*sizeof(Real)); model->readMaterials("material.dat"); model->initMaterials(); model->initModel(); Real time_step = model->getStableTimeStep(); model->setTimeStep(time_step/10.); model->assembleMassLumped(); std::cout << *model << std::endl; FEM & fem_boundary = model->getFEMBoundary(); fem_boundary.initShapeFunctions(); fem_boundary.computeNormalsOnQuadPoints(); model->computeForcesFromFunction(trac, akantu::_bft_stress); #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(BASE64); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, 2, nb_nodes, "coordinates"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(_triangle_6).values, TRIANGLE2, model->getFEM().getMesh().getNbElement(_triangle_6), C_MODE); dumper.AddNodeDataField(model->getDisplacement().values, 2, "displacements"); dumper.AddNodeDataField(model->getVelocity().values, 2, "velocity"); dumper.AddNodeDataField(model->getForce().values, 2, "force"); dumper.AddNodeDataField(model->getMass().values, 1, "Mass"); dumper.AddNodeDataField(model->getResidual().values, 2, "residual"); dumper.AddElemDataField(model->getMaterial(0).getStrain(_triangle_6).values, 4, "strain"); dumper.AddElemDataField(model->getMaterial(0).getStress(_triangle_6).values, 4, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("force", 1); dumper.SetEmbeddedValue("residual", 1); dumper.SetEmbeddedValue("velocity", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER for(UInt s = 0; s < max_steps; ++s) { model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); epot = model->getPotentialEnergy(); ekin = model->getKineticEnergy(); std::cout << s << " " << epot << " " << ekin << " " << epot + ekin << std::endl; #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d.cc index 4c880a7e3..ac30da207 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d.cc @@ -1,126 +1,140 @@ /** * @file test_solid_mechanics_model_cube3d.cc * @author Guillaume ANCIAUX <anciaux@lsmscluster1.epfl.ch> * @date Tue Aug 17 11:31:22 2010 * * @brief test of the class SolidMechanicsModel on the 3d cube * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER int main(int argc, char *argv[]) { akantu::UInt max_steps = 10000; akantu::Real epot, ekin; #ifdef AKANTU_USE_IOHELPER akantu::ElementType type = akantu::_tetrahedron_4; akantu::UInt paratype = TETRA1; #endif //AKANTU_USE_IOHELPER akantu::Mesh mesh(3); akantu::MeshIOMSH mesh_io; mesh_io.read("cube1.msh", mesh); akantu::SolidMechanicsModel * model = new akantu::SolidMechanicsModel(mesh); /// model initialization model->initVectors(); /// initialize the vectors akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); memset(model->getForce().values, 0, 3*nb_nodes*sizeof(akantu::Real)); memset(model->getVelocity().values, 0, 3*nb_nodes*sizeof(akantu::Real)); memset(model->getAcceleration().values, 0, 3*nb_nodes*sizeof(akantu::Real)); memset(model->getDisplacement().values, 0, 3*nb_nodes*sizeof(akantu::Real)); model->readMaterials("material.dat"); model->initMaterials(); model->initModel(); akantu::Real time_step = model->getStableTimeStep(); model->setTimeStep(time_step/10.); model->assembleMassLumped(); std::cout << *model << std::endl; /// boundary conditions akantu::Real eps = 1e-16; for (akantu::UInt i = 0; i < nb_nodes; ++i) { model->getDisplacement().values[3*i] = model->getFEM().getMesh().getNodes().values[3*i] / 100.; if(model->getFEM().getMesh().getNodes().values[3*i] <= eps) { model->getBoundary().values[3*i ] = true; } if(model->getFEM().getMesh().getNodes().values[3*i + 1] <= eps) { model->getBoundary().values[3*i + 1] = true; } } // model->getDisplacement().values[1] = 0.1; #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; // dumper.SetMode(TEXT); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, 3, nb_nodes, "coordinates"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type).values, paratype, model->getFEM().getMesh().getNbElement(type), C_MODE); dumper.AddNodeDataField(model->getDisplacement().values, 3, "displacements"); dumper.AddNodeDataField(model->getVelocity().values, 3, "velocity"); dumper.AddNodeDataField(model->getMass().values, 1, "mass"); dumper.AddNodeDataField(model->getResidual().values, 3, "force"); dumper.AddElemDataField(model->getMaterial(0).getStrain(type).values, 9, "strain"); dumper.AddElemDataField(model->getMaterial(0).getStress(type).values, 9, "stress"); dumper.SetPrefix("paraview/"); dumper.Init(); #endif //AKANTU_USE_IOHELPER std::ofstream energy; energy.open("energy.csv"); energy << "id,epot,ekin,tot" << std::endl; for(akantu::UInt s = 0; s < max_steps; ++s) { model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); epot = model->getPotentialEnergy(); ekin = model->getKineticEnergy(); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; #ifdef AKANTU_USE_IOHELPER if(s % 10 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } energy.close(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_tetra10.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_tetra10.cc index 360844cbf..1f624f91a 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_tetra10.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_cube3d_tetra10.cc @@ -1,125 +1,139 @@ /** * @file test_solid_mechanics_model_cube3d.cc * @author Guillaume ANCIAUX <anciaux@lsmscluster1.epfl.ch> * @date Tue Aug 17 11:31:22 2010 * * @brief test of the class SolidMechanicsModel on the 3d cube * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER int main(int argc, char *argv[]) { akantu::UInt max_steps = 1000; akantu::Real epot, ekin; #ifdef AKANTU_USE_IOHELPER akantu::ElementType type = akantu::_tetrahedron_10; akantu::UInt paratype = TETRA2; #endif //AKANTU_USE_IOHELPER akantu::Mesh mesh(3); akantu::MeshIOMSH mesh_io; mesh_io.read("cube2.msh", mesh); akantu::SolidMechanicsModel * model = new akantu::SolidMechanicsModel(mesh); /// model initialization model->initVectors(); /// initialize the vectors akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); memset(model->getForce().values, 0, 3*nb_nodes*sizeof(akantu::Real)); memset(model->getVelocity().values, 0, 3*nb_nodes*sizeof(akantu::Real)); memset(model->getAcceleration().values, 0, 3*nb_nodes*sizeof(akantu::Real)); memset(model->getDisplacement().values, 0, 3*nb_nodes*sizeof(akantu::Real)); model->readMaterials("material.dat"); model->initMaterials(); model->initModel(); akantu::Real time_step = model->getStableTimeStep(); model->setTimeStep(time_step/10.); model->assembleMassLumped(); std::cout << *model << std::endl; /// boundary conditions akantu::Real eps = 1e-2; for (akantu::UInt i = 0; i < nb_nodes; ++i) { model->getDisplacement().values[3*i] = model->getFEM().getMesh().getNodes().values[3*i] / 100.; if(model->getFEM().getMesh().getNodes().values[3*i] <= eps) { model->getBoundary().values[3*i ] = true; } if(model->getFEM().getMesh().getNodes().values[3*i + 1] <= eps) { model->getBoundary().values[3*i + 1] = true; } } // model->getDisplacement().values[1] = 0.1; #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; // dumper.SetMode(TEXT); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, 3, nb_nodes, "coordinates2"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type).values, paratype, model->getFEM().getMesh().getNbElement(type), C_MODE); dumper.AddNodeDataField(model->getDisplacement().values, 3, "displacements"); dumper.AddNodeDataField(model->getVelocity().values, 3, "velocity"); dumper.AddNodeDataField(model->getMass().values, 1, "mass"); dumper.AddNodeDataField(model->getResidual().values, 3, "force"); dumper.AddElemDataField(model->getMaterial(0).getStrain(type).values, 9, "strain"); dumper.AddElemDataField(model->getMaterial(0).getStress(type).values, 9, "stress"); dumper.SetPrefix("paraview/"); dumper.Init(); #endif //AKANTU_USE_IOHELPER std::ofstream energy; energy.open("energy.csv"); energy << "id,epot,ekin,tot" << std::endl; for(akantu::UInt s = 0; s < max_steps; ++s) { model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); epot = model->getPotentialEnergy(); ekin = model->getKineticEnergy(); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; #ifdef AKANTU_USE_IOHELPER if(s % 10 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } energy.close(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_segment_parallel.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_segment_parallel.cc index 34b757751..5629ece37 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_segment_parallel.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_segment_parallel.cc @@ -1,183 +1,197 @@ /** * @file test_solid_mechanics_model_segment_parallel.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 14:34:13 2010 * * @brief test of the class SolidMechanicsModel * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <limits> #include <fstream> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "static_communicator.hh" #include "communicator.hh" #include "mesh_partition_scotch.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER #define CHECK_STRESS int main(int argc, char *argv[]) { akantu::UInt spatial_dimension = 1; #ifdef AKANTU_USE_IOHELPER akantu::ElementType type = akantu::_segment_3; #endif //AKANTU_USE_IOHELPER akantu::UInt max_steps = 10000; akantu::Real time_factor = 0.2; akantu::initialize(&argc, &argv); // akantu::debug::setDebugLevel(akantu::dblDump); // akantu::Real epot, ekin; akantu::Mesh mesh(spatial_dimension); akantu::StaticCommunicator * comm = akantu::StaticCommunicator::getStaticCommunicator(); akantu::Int psize = comm->getNbProc(); akantu::Int prank = comm->whoAmI(); akantu::Communicator * communicator; if(prank == 0) { akantu::MeshIOMSH mesh_io; mesh_io.read("segment.msh", mesh); akantu::MeshPartition * partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); communicator = akantu::Communicator::createCommunicatorDistributeMesh(mesh, partition); delete partition; } else { communicator = akantu::Communicator::createCommunicatorDistributeMesh(mesh, NULL); } // std::cout << mesh << std::endl; akantu::SolidMechanicsModel * model = new akantu::SolidMechanicsModel(mesh); akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); #ifdef AKANTU_USE_IOHELPER akantu::UInt nb_element = model->getFEM().getMesh().getNbElement(type); #endif //AKANTU_USE_IOHELPER /// model initialization model->initVectors(); /// set vectors to 0 memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getVelocity().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getAcceleration().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getDisplacement().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); model->readMaterials("material.dat"); model->initMaterials(); model->registerSynchronizer(*communicator); model->initModel(); std::cout << model->getMaterial(0) << std::endl; model->assembleMassLumped(); #ifdef AKANTU_USE_IOHELPER /// set to 0 only for the first paraview dump memset(model->getResidual().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); #endif //AKANTU_USE_IOHELPER /// boundary conditions for (akantu::UInt i = 0; i < nb_nodes; ++i) { model->getDisplacement().values[spatial_dimension*i] = model->getFEM().getMesh().getNodes().values[i] / 100. ; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] <= 1e-15) model->getBoundary().values[i] = true; } memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); // model->synchronizeBoundaries(); akantu::Real time_step = model->getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetParallelContext(prank, psize); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, "line_para"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type).values, LINE2, nb_element, C_MODE); dumper.AddNodeDataField(model->getDisplacement().values, spatial_dimension, "displacements"); dumper.AddNodeDataField(model->getVelocity().values, spatial_dimension, "velocity"); dumper.AddNodeDataField(model->getResidual().values, spatial_dimension, "force"); dumper.AddNodeDataField(model->getAcceleration().values, spatial_dimension, "acceleration"); dumper.AddNodeDataField(model->getMass().values, spatial_dimension, "mass"); double * part = new double[nb_element]; for (unsigned int i = 0; i < nb_element; ++i) part[i] = prank; dumper.AddElemDataField(part, 1, "partitions"); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER for(akantu::UInt s = 1; s <= max_steps; ++s) { model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); akantu::Real epot = model->getPotentialEnergy(); akantu::Real ekin = model->getKineticEnergy(); if(prank == 0) { std::cout << s << " " << epot << " " << ekin << " " << epot + ekin << std::endl; } #ifdef AKANTU_USE_IOHELPER // if(s % 100 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER if(s % 10 == 0) std::cerr << "passing step " << s << "/" << max_steps << std::endl; } #ifdef AKANTU_USE_IOHELPER delete [] part; #endif //AKANTU_USE_IOHELPER akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_square.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_square.cc index fc3fb6955..f65fdb5b8 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_square.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_square.cc @@ -1,213 +1,227 @@ /** * @file test_solid_mechanics_model.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jul 27 14:34:13 2010 * * @brief test of the class SolidMechanicsModel * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "fem.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; static void trac(__attribute__ ((unused)) double * position,double * traction){ memset(traction,0,sizeof(Real)*4); traction[0] = 1000; traction[3] = 1000; // if(fabs(position[0])< 1e-4){ // traction[0] = -position[1]; // } } int main(int argc, char *argv[]) { UInt max_steps = 1000; Real epot, ekin; ElementType type = _triangle_3; ElementType ftype = Mesh::getFacetElementType(type); #ifdef AKANTU_USE_IOHELPER UInt para_type = TRIANGLE1; #endif //AKANTU_USE_IOHELPER Mesh mesh(2); MeshIOMSH mesh_io; mesh_io.read("square.msh", mesh); SolidMechanicsModel model(mesh); /// model initialization model.initVectors(); UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); memset(model.getForce().values, 0, 2*nb_nodes*sizeof(Real)); memset(model.getVelocity().values, 0, 2*nb_nodes*sizeof(Real)); memset(model.getAcceleration().values, 0, 2*nb_nodes*sizeof(Real)); memset(model.getDisplacement().values, 0, 2*nb_nodes*sizeof(Real)); memset(model.getResidual().values, 0, 2*nb_nodes*sizeof(Real)); memset(model.getMass().values, 1, nb_nodes*sizeof(Real)); model.readMaterials("material.dat"); model.initMaterials(); model.initModel(); Real time_step = model.getStableTimeStep(); model.setTimeStep(time_step/10.); model.assembleMassLumped(); std::cout << model << std::endl; /// boundary conditions // Real eps = 1e-16; // for (UInt i = 0; i < nb_nodes; ++i) { // model.getDisplacement().values[2*i] = model.getFEM().getMesh().getNodes().values[2*i] / 100.; // if(model.getFEM().getMesh().getNodes().values[2*i] <= eps) { // model.getBoundary().values[2*i ] = true; // if(model.getFEM().getMesh().getNodes().values[2*i + 1] <= eps) // model.getBoundary().values[2*i + 1] = true; // } // if(model.getFEM().getMesh().getNodes().values[2*i + 1] <= eps) { // model.getBoundary().values[2*i + 1] = true; // } // } FEM & fem_boundary = model.getFEMBoundary(); fem_boundary.initShapeFunctions(); fem_boundary.computeNormalsOnQuadPoints(); const Mesh::ConnectivityTypeList & type_list = fem_boundary.getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != fem_boundary.getElementDimension()) continue; // ElementType facet_type = Mesh::getFacetElementType(*it); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); UInt nb_quad = FEM::getNbQuadraturePoints(*it); UInt nb_element; const Vector<Real> * shapes; Vector<Real> quad_coords(0,2,"quad_coords"); const Vector<Real> * normals_on_quad; nb_element = fem_boundary.getMesh().getNbElement(*it); fem_boundary.interpolateOnQuadraturePoints(mesh.getNodes(), quad_coords, 2, ftype); normals_on_quad = &(fem_boundary.getNormalsOnQuadPoints(*it)); shapes = &(fem_boundary.getShapes(*it)); Vector<Real> * sigma_funct = new Vector<Real>(nb_element, 4*nb_quad, "myfunction"); Vector<Real> * funct = new Vector<Real>(nb_element, 2*nb_quad, "myfunction"); Real * sigma_funct_val = sigma_funct->values; Real * shapes_val = shapes->values; /// compute t * \phi_i for each nodes of each element for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quad; ++q) { trac(quad_coords.values+el*nb_quad*2+q,sigma_funct_val); sigma_funct_val += 4; } } Math::matrix_vector(2,2,*sigma_funct,*normals_on_quad,*funct); funct->extendComponentsInterlaced(nb_nodes_per_element,2); Real * funct_val = funct->values; for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quad; ++q) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { *funct_val++ *= *shapes_val; *funct_val++ *= *shapes_val++; } } } Vector<Real> * int_funct = new Vector<Real>(nb_element, 2*nb_nodes_per_element, "inte_funct"); fem_boundary.integrate(*funct, *int_funct, 2*nb_nodes_per_element, *it); delete funct; fem_boundary.assembleVector(*int_funct,const_cast<Vector<Real> &>(model.getForce()), 2, *it); delete int_funct; } // model.getDisplacement().values[1] = 0.1; #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(BASE64); dumper.SetPoints(model.getFEM().getMesh().getNodes().values, 2, nb_nodes, "coordinates"); dumper.SetConnectivity((int *)model.getFEM().getMesh().getConnectivity(type).values, para_type, model.getFEM().getMesh().getNbElement(type), C_MODE); dumper.AddNodeDataField(model.getDisplacement().values, 2, "displacements"); dumper.AddNodeDataField(model.getVelocity().values, 2, "velocity"); dumper.AddNodeDataField(model.getForce().values, 2, "force"); dumper.AddNodeDataField(model.getMass().values, 1, "Mass"); dumper.AddNodeDataField(model.getResidual().values, 2, "residual"); dumper.AddElemDataField(model.getMaterial(0).getStrain(type).values, 4, "strain"); dumper.AddElemDataField(model.getMaterial(0).getStress(type).values, 4, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("force", 1); dumper.SetEmbeddedValue("residual", 1); dumper.SetEmbeddedValue("velocity", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream energy; energy.open("energy.csv"); energy << "id,epot,ekin,tot" << std::endl; for(UInt s = 0; s < max_steps; ++s) { model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); epot = model.getPotentialEnergy(); ekin = model.getKineticEnergy(); std::cerr << "passing step " << s << "/" << max_steps << std::endl; energy << s << "," << epot << "," << ekin << "," << epot + ekin << std::endl; #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } energy.close(); finalize(); return EXIT_SUCCESS; } diff --git a/test/test_solver/CMakeLists.txt b/test/test_solver/CMakeLists.txt index 9fe83fdbf..985949fc5 100644 --- a/test/test_solver/CMakeLists.txt +++ b/test/test_solver/CMakeLists.txt @@ -1,22 +1,36 @@ #=============================================================================== # @file CMakeLists.txt # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== add_mesh(test_solver_mesh triangle.geo 2 1) register_test(test_sparse_matrix_profile test_sparse_matrix_profile.cc) add_dependencies(test_sparse_matrix_profile test_solver_mesh) register_test(test_sparse_matrix_assemble test_sparse_matrix_assemble.cc) add_dependencies(test_sparse_matrix_assemble test_solver_mesh) register_test(test_solver_mumps test_solver_mumps.cc) \ No newline at end of file diff --git a/test/test_solver/test_solver_mumps.cc b/test/test_solver/test_solver_mumps.cc index 680449fc7..15d1c6cd6 100644 --- a/test/test_solver/test_solver_mumps.cc +++ b/test/test_solver/test_solver_mumps.cc @@ -1,56 +1,70 @@ /** * @file test_solver_mumps.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Sun Dec 12 20:20:32 2010 * * @brief simple test of the mumps solver interface * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "solver_mumps.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); akantu::debug::setDebugLevel(akantu::dblDump); akantu::StaticCommunicator * comm = akantu::StaticCommunicator::getStaticCommunicator(); akantu::UInt n = 10 * comm->getNbProc(); akantu::SparseMatrix * sparse_matrix = new akantu::SparseMatrix(n, akantu::_symmetric, 1, "hand"); akantu::Solver * solver = new akantu::SolverMumps(*sparse_matrix); akantu::UInt i_start = comm->whoAmI() * 10; for(akantu::UInt i = i_start; i < i_start + 10; ++i) { sparse_matrix->addToProfile(i,i); sparse_matrix->addToMatrix(i, i, 1./(i+1)); } if(comm->whoAmI() == 0) for(akantu::UInt i = 0; i < n; ++i) { solver->getRHS().values[i] = 1.; } // sparse_matrix->saveMatrix("solver_matrix.mtx"); solver->initialize(); solver->solve(); if(comm->whoAmI() == 0) { std::cout << solver->getRHS() << std::endl; } delete solver; akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_solver/test_sparse_matrix_assemble.cc b/test/test_solver/test_sparse_matrix_assemble.cc index 61fcea39e..7da265261 100644 --- a/test/test_solver/test_sparse_matrix_assemble.cc +++ b/test/test_solver/test_sparse_matrix_assemble.cc @@ -1,61 +1,75 @@ /** * @file test_sparse_matrix_assemble.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Nov 5 11:13:33 2010 * * @brief test the assembling method of the SparseMatrix class * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); akantu::UInt spatial_dimension = 2; akantu::Mesh mesh(spatial_dimension); akantu::MeshIOMSH mesh_io; mesh_io.read("triangle.msh", mesh); akantu::SparseMatrix sparse_matrix(mesh, akantu::_symmetric, spatial_dimension); sparse_matrix.buildProfile(); const akantu::Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); akantu::Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(mesh.getSpatialDimension(*it) != spatial_dimension) continue; akantu::UInt nb_element = mesh.getNbElement(*it); akantu::UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*it); akantu::Element element(*it); akantu::UInt m = nb_nodes_per_element * spatial_dimension; akantu::Vector<akantu::Real> local_mat(m, m, 1, "local_mat"); for(akantu::UInt e = 0; e < nb_element; ++e) { element.element = e; sparse_matrix.addToMatrix(local_mat, element); } } sparse_matrix.saveMatrix("matrix.mtx"); akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_solver/test_sparse_matrix_profile.cc b/test/test_solver/test_sparse_matrix_profile.cc index c67dcf9aa..2dc41898b 100644 --- a/test/test_solver/test_sparse_matrix_profile.cc +++ b/test/test_solver/test_sparse_matrix_profile.cc @@ -1,56 +1,70 @@ /** * @file test_sparse_matrix_profile.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Nov 5 11:13:33 2010 * * @brief test the profile generation of the SparseMatrix class * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); akantu::UInt spatial_dimension = 2; akantu::Mesh mesh(spatial_dimension); akantu::MeshIOMSH mesh_io; mesh_io.read("triangle.msh", mesh); akantu::SparseMatrix sparse_matrix_hand(10, akantu::_symmetric, 1, "hand"); for(akantu::UInt i = 0; i < 10; ++i) { sparse_matrix_hand.addToProfile(i, i); } sparse_matrix_hand.addToProfile(0,9); for(akantu::UInt i = 0; i < 10; ++i) { sparse_matrix_hand.addToMatrix(i, i, i*10); } sparse_matrix_hand.addToMatrix(0,9, 100); sparse_matrix_hand.saveProfile("profile_hand.mtx"); sparse_matrix_hand.saveMatrix("matrix_hand.mtx"); akantu::SparseMatrix sparse_matrix(mesh, akantu::_symmetric, 2, "mesh"); sparse_matrix.buildProfile(); sparse_matrix.saveProfile("profile.mtx"); akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_static_memory/CMakeLists.txt b/test/test_static_memory/CMakeLists.txt index 3b6961da1..0b6e9d685 100644 --- a/test/test_static_memory/CMakeLists.txt +++ b/test/test_static_memory/CMakeLists.txt @@ -1,14 +1,28 @@ #=============================================================================== # @file CMakeLists.txt # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== REGISTER_TEST(test_static_memory test_static_memory.cc) diff --git a/test/test_static_memory/test_static_memory.cc b/test/test_static_memory/test_static_memory.cc index fd26af79a..a2fd0e4bc 100644 --- a/test/test_static_memory/test_static_memory.cc +++ b/test/test_static_memory/test_static_memory.cc @@ -1,36 +1,54 @@ /** * @file test_static_memory.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Fri Jun 11 11:55:54 2010 * * @brief unit test for the StaticMemory class * + * @section LICENSE + * + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. + * */ /* -------------------------------------------------------------------------- */ #include <iostream> /* -------------------------------------------------------------------------- */ #include "aka_static_memory.hh" #include "aka_vector.hh" /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); akantu::StaticMemory * st_mem = akantu::StaticMemory::getStaticMemory(); akantu::Vector<int> & test_int = st_mem->smalloc<int>(0, "test_int", 1000, 3); test_int.resize(1050); test_int.resize(2000); std::cout << *st_mem << std::endl; st_mem->sfree(0, "test_int"); akantu::finalize(); exit(EXIT_SUCCESS); } diff --git a/test/test_surface_extraction/CMakeLists.txt b/test/test_surface_extraction/CMakeLists.txt index f20e924e1..9daebb83f 100644 --- a/test/test_surface_extraction/CMakeLists.txt +++ b/test/test_surface_extraction/CMakeLists.txt @@ -1,24 +1,38 @@ #=============================================================================== # @file CMakeLists.txt # @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> # @date Mon Oct 25 09:40:24 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_mesh(test_surface_extraction_2d_mesh squares.geo 2 1) register_test(test_surface_extraction_triangle_3 test_surface_extraction_triangle_3.cc) add_dependencies(test_surface_extraction_triangle_3 test_surface_extraction_2d_mesh) #=============================================================================== add_mesh(test_surface_extraction_3d_mesh cubes.geo 3 1) register_test(test_surface_extraction_tetrahedron_4 test_surface_extraction_tetrahedron_4.cc) add_dependencies(test_surface_extraction_tetrahedron_4 test_surface_extraction_3d_mesh) \ No newline at end of file diff --git a/test/test_surface_extraction/test_surface_extraction_tetrahedron_4.cc b/test/test_surface_extraction/test_surface_extraction_tetrahedron_4.cc index 8277f94be..15073d257 100644 --- a/test/test_surface_extraction/test_surface_extraction_tetrahedron_4.cc +++ b/test/test_surface_extraction/test_surface_extraction_tetrahedron_4.cc @@ -1,73 +1,87 @@ /** * @file test_surface_extraction_3d.cc * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @date Mon Oct 25 11:40:12 2010 * * @brief * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 3; Mesh mesh(dim); MeshIOMSH mesh_io; mesh_io.read("cubes.msh", mesh); MeshUtils::buildFacets(mesh,1,0); MeshUtils::buildSurfaceID(mesh); unsigned int nb_nodes = mesh.getNbNodes(); #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-surface-extraction"); dumper.SetConnectivity((int*)mesh.getConnectivity(_tetrahedron_4).values, TETRA1, mesh.getNbElement(_tetrahedron_4), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); DumperParaview dumper_surface; dumper_surface.SetMode(TEXT); dumper_surface.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-surface-extraction_boundary"); dumper_surface.SetConnectivity((int *)mesh.getConnectivity(_triangle_3).values, TRIANGLE1, mesh.getNbElement(_triangle_3), C_MODE); double * surf_id = new double [mesh.getSurfaceId(_triangle_3).getSize()]; for (UInt i = 0; i < mesh.getSurfaceId(_triangle_3).getSize(); ++i) surf_id[i] = (double)mesh.getSurfaceId(_triangle_3).values[i]; dumper_surface.AddElemDataField(surf_id, 1, "surface_id"); delete [] surf_id; dumper_surface.SetPrefix("paraview/"); dumper_surface.Init(); dumper_surface.Dump(); #endif //AKANTU_USE_IOHELPER finalize(); return EXIT_SUCCESS; } diff --git a/test/test_surface_extraction/test_surface_extraction_triangle_3.cc b/test/test_surface_extraction/test_surface_extraction_triangle_3.cc index 23de4376b..5bf60b7c2 100644 --- a/test/test_surface_extraction/test_surface_extraction_triangle_3.cc +++ b/test/test_surface_extraction/test_surface_extraction_triangle_3.cc @@ -1,73 +1,87 @@ /** * @file test_surface_extraction_2d.cc * @author Leonardo Snozzi <leonardo.snozzi@epfl.ch> * @date Mon Oct 25 09:47:15 2010 * * @brief * * @section LICENSE * - * <insert license here> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 2; Mesh mesh(dim); MeshIOMSH mesh_io; mesh_io.read("squares.msh", mesh); MeshUtils::buildFacets(mesh,1,0); MeshUtils::buildSurfaceID(mesh); unsigned int nb_nodes = mesh.getNbNodes(); #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-surface-extraction"); dumper.SetConnectivity((int*)mesh.getConnectivity(_triangle_3).values, TRIANGLE1, mesh.getNbElement(_triangle_3), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); DumperParaview dumper_surface; dumper_surface.SetMode(TEXT); dumper_surface.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-surface-extraction_boundary"); dumper_surface.SetConnectivity((int *)mesh.getConnectivity(_segment_2).values, LINE1, mesh.getNbElement(_segment_2), C_MODE); double * surf_id = new double [mesh.getSurfaceId(_segment_2).getSize()]; for (UInt i = 0; i < mesh.getSurfaceId(_segment_2).getSize(); ++i) surf_id[i] = (double)mesh.getSurfaceId(_segment_2).values[i]; dumper_surface.AddElemDataField(surf_id, 1, "surface_id"); delete [] surf_id; dumper_surface.SetPrefix("paraview/"); dumper_surface.Init(); dumper_surface.Dump(); #endif //AKANTU_USE_IOHELPER finalize(); return EXIT_SUCCESS; } diff --git a/test/test_synchronizer/CMakeLists.txt b/test/test_synchronizer/CMakeLists.txt index 39cf86629..db5d5b997 100644 --- a/test/test_synchronizer/CMakeLists.txt +++ b/test/test_synchronizer/CMakeLists.txt @@ -1,28 +1,42 @@ #=============================================================================== # @file CMakeLists.txt # @author Nicolas Richart <nicolas.richart@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== add_mesh(test_synchronizer_communication_mesh triangle.geo 2 1) register_test(test_synchronizer_communication test_synchronizer_communication.cc) add_dependencies(test_synchronizer_communication test_synchronizer_communication_mesh) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/test_synchronizer_communication.sh ${CMAKE_CURRENT_BINARY_DIR}/test_synchronizer_communication.sh COPYONLY ) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) \ No newline at end of file diff --git a/test/test_synchronizer/test_synchronizer_communication.cc b/test/test_synchronizer/test_synchronizer_communication.cc index f35d28180..cac0c3400 100644 --- a/test/test_synchronizer/test_synchronizer_communication.cc +++ b/test/test_synchronizer/test_synchronizer_communication.cc @@ -1,240 +1,254 @@ /** * @file test_synchronizer_communication.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Thu Aug 19 13:05:27 2010 * * @brief test to synchronize barycenters * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "static_communicator.hh" #include "communicator.hh" #include "ghost_synchronizer.hh" #include "mesh.hh" #include "mesh_io_msh.hh" #include "mesh_partition_scotch.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER class TestSynchronizer : public akantu::GhostSynchronizer { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: TestSynchronizer(const akantu::Mesh & mesh); ~TestSynchronizer(); AKANTU_GET_MACRO_BY_ELEMENT_TYPE(GhostBarycenter, ghost_barycenter, const akantu::Vector<akantu::Real>); /* ------------------------------------------------------------------------ */ /* Ghost Synchronizer inherited members */ /* ------------------------------------------------------------------------ */ protected: virtual akantu::UInt getNbDataToPack(const akantu::Element & element, akantu::GhostSynchronizationTag tag) const; virtual akantu::UInt getNbDataToUnpack(const akantu::Element & element, akantu::GhostSynchronizationTag tag) const; virtual void packData(akantu::Real ** buffer, const akantu::Element & element, akantu::GhostSynchronizationTag tag) const; virtual void unpackData(akantu::Real ** buffer, const akantu::Element & element, akantu::GhostSynchronizationTag tag) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: std::string id; akantu::ByElementTypeReal ghost_barycenter; const akantu::Mesh & mesh; }; /* -------------------------------------------------------------------------- */ /* TestSynchronizer implementation */ /* -------------------------------------------------------------------------- */ TestSynchronizer::TestSynchronizer(const akantu::Mesh & mesh) : mesh(mesh) { akantu::UInt spatial_dimension = mesh.getSpatialDimension(); id = "test_synchronizer"; akantu::Mesh::ConnectivityTypeList::const_iterator it; const akantu::Mesh::ConnectivityTypeList & ghost_type_list = mesh.getConnectivityTypeList(akantu::_ghost); for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { if(akantu::Mesh::getSpatialDimension(*it) != spatial_dimension) continue; akantu::UInt nb_ghost_element = mesh.getNbGhostElement(*it); ghost_barycenter[*it] = new akantu::Vector<akantu::Real>(nb_ghost_element, spatial_dimension, std::numeric_limits<akantu::Real>::quiet_NaN(), "ghost_barycenter"); } } TestSynchronizer::~TestSynchronizer() { akantu::UInt spatial_dimension = mesh.getSpatialDimension(); akantu::Mesh::ConnectivityTypeList::const_iterator it; const akantu::Mesh::ConnectivityTypeList & ghost_type_list = mesh.getConnectivityTypeList(akantu::_ghost); for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { if(akantu::Mesh::getSpatialDimension(*it) != spatial_dimension) continue; delete ghost_barycenter[*it]; } } akantu::UInt TestSynchronizer::getNbDataToPack(const akantu::Element & element, __attribute__ ((unused)) akantu::GhostSynchronizationTag tag) const { return akantu::Mesh::getSpatialDimension(element.type); } akantu::UInt TestSynchronizer::getNbDataToUnpack(const akantu::Element & element, __attribute__ ((unused)) akantu::GhostSynchronizationTag tag) const { return akantu::Mesh::getSpatialDimension(element.type); } void TestSynchronizer::packData(akantu::Real ** buffer, const akantu::Element & element, __attribute__ ((unused)) akantu::GhostSynchronizationTag tag) const { akantu::UInt spatial_dimension = akantu::Mesh::getSpatialDimension(element.type); mesh.getBarycenter(element.element, element.type, *buffer); *buffer += spatial_dimension; } void TestSynchronizer::unpackData(akantu::Real ** buffer, const akantu::Element & element, __attribute__ ((unused)) akantu::GhostSynchronizationTag tag) const { akantu::UInt spatial_dimension = akantu::Mesh::getSpatialDimension(element.type); memcpy(ghost_barycenter[element.type]->values + element.element * spatial_dimension, *buffer, spatial_dimension * sizeof(akantu::Real)); *buffer += spatial_dimension; } /* -------------------------------------------------------------------------- */ /* Main */ /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); int dim = 2; #ifdef AKANTU_USE_IOHELPER akantu::ElementType type = akantu::_triangle_3; #endif //AKANTU_USE_IOHELPER akantu::Mesh mesh(dim); akantu::StaticCommunicator * comm = akantu::StaticCommunicator::getStaticCommunicator(); akantu::Int psize = comm->getNbProc(); akantu::Int prank = comm->whoAmI(); akantu::Communicator * communicator; if(prank == 0) { akantu::MeshIOMSH mesh_io; mesh_io.read("triangle.msh", mesh); akantu::MeshPartition * partition = new akantu::MeshPartitionScotch(mesh, dim); partition->partitionate(psize); communicator = akantu::Communicator::createCommunicatorDistributeMesh(mesh, partition); delete partition; } else { communicator = akantu::Communicator::createCommunicatorDistributeMesh(mesh, NULL); } comm->barrier(); AKANTU_DEBUG_INFO("Creating TestSynchronizer"); TestSynchronizer test_synchronizer(mesh); test_synchronizer.registerSynchronizer(*communicator); AKANTU_DEBUG_INFO("Registering tag"); test_synchronizer.registerTag(akantu::_gst_test, "barycenter"); AKANTU_DEBUG_INFO("Synchronizing tag"); test_synchronizer.synchronize(akantu::_gst_test); akantu::Mesh::ConnectivityTypeList::const_iterator it; const akantu::Mesh::ConnectivityTypeList & ghost_type_list = mesh.getConnectivityTypeList(akantu::_ghost); for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { if(akantu::Mesh::getSpatialDimension(*it) != mesh.getSpatialDimension()) continue; akantu::UInt spatial_dimension = akantu::Mesh::getSpatialDimension(*it); akantu::UInt nb_ghost_element = mesh.getNbGhostElement(*it); for (akantu::UInt el = 0; el < nb_ghost_element; ++el) { akantu::Real barycenter[spatial_dimension]; mesh.getBarycenter(el, *it, barycenter, akantu::_ghost); for (akantu::UInt i = 0; i < spatial_dimension; ++i) { if(fabs(barycenter[i] - test_synchronizer.getGhostBarycenter(*it).values[el * spatial_dimension + i]) > std::numeric_limits<akantu::Real>::epsilon()) AKANTU_DEBUG_ERROR("The barycenter of ghost element " << el << " on proc " << prank << " does not match the one get during synchronisation" ); } } } #ifdef AKANTU_USE_IOHELPER unsigned int nb_nodes = mesh.getNbNodes(); unsigned int nb_element = mesh.getNbElement(type); DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetParallelContext(prank, psize); dumper.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-scotch-partition"); dumper.SetConnectivity((int*) mesh.getConnectivity(type).values, TRIANGLE1, nb_element, C_MODE); double * part = new double[nb_element]; for (unsigned int i = 0; i < nb_element; ++i) part[i] = prank; dumper.AddElemDataField(part, 1, "partitions"); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); delete [] part; unsigned int nb_ghost_element = mesh.getNbGhostElement(type); DumperParaview dumper_ghost; dumper_ghost.SetMode(TEXT); dumper_ghost.SetParallelContext(prank, psize); dumper_ghost.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-scotch-partition_ghost"); dumper_ghost.SetConnectivity((int*) mesh.getGhostConnectivity(type).values, TRIANGLE1, nb_ghost_element, C_MODE); part = new double[nb_ghost_element]; for (unsigned int i = 0; i < nb_ghost_element; ++i) part[i] = prank; dumper_ghost.AddElemDataField(part, 1, "partitions"); dumper_ghost.SetPrefix("paraview/"); dumper_ghost.Init(); dumper_ghost.Dump(); delete [] part; #endif //AKANTU_USE_IOHELPER akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_vector/CMakeLists.txt b/test/test_vector/CMakeLists.txt index 707707d40..2dd2fecfe 100644 --- a/test/test_vector/CMakeLists.txt +++ b/test/test_vector/CMakeLists.txt @@ -1,14 +1,28 @@ #=============================================================================== # @file CMakeLists.txt # @author Guillaume Anciaux <guillaume.anciaux@epfl.ch> # @date Fri Jun 11 09:46:59 2010 # # @section LICENSE # -# <insert lisence here> +# Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) +# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) +# +# Akantu is free software: you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version. +# +# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Akantu. If not, see <http://www.gnu.org/licenses/>. # # @section DESCRIPTION # #=============================================================================== REGISTER_TEST(test_vector test_vector.cc) diff --git a/test/test_vector/test_vector.cc b/test/test_vector/test_vector.cc index a1b81e1fb..e4e1b1be2 100644 --- a/test/test_vector/test_vector.cc +++ b/test/test_vector/test_vector.cc @@ -1,55 +1,69 @@ /** * @file test_vector.cc * @author Nicolas Richart <nicolas.richart@epfl.ch> * @date Tue Jun 29 17:32:23 2010 * * @brief test of the vector class * * @section LICENSE * - * \<insert license here\> + * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see <http://www.gnu.org/licenses/>. * */ /* -------------------------------------------------------------------------- */ #include <cstdlib> /* -------------------------------------------------------------------------- */ #include "aka_vector.hh" /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { int def_value[3]; def_value[0] = 10; def_value[1] = 20; def_value[2] = 30; akantu::Vector<int> int_vect(10, 3, def_value, "test1"); for (unsigned int i = 5; i < int_vect.getSize(); ++i) { for (unsigned int j = 0; j < int_vect.getNbComponent(); ++j) { int_vect.values[i*int_vect.getNbComponent() + j] = def_value[j]*10; } } std::cerr << int_vect; int new_elem[3]; new_elem[0] = 1; new_elem[1] = 2; new_elem[2] = 3; int_vect.push_back(new_elem); int_vect.push_back(200); int_vect.erase(0); std::cerr << int_vect; akantu::Vector<int> int_vect0(0, 3, def_value, "test2"); std::cerr << int_vect0; int_vect0.push_back(new_elem); std::cerr << int_vect0; return EXIT_SUCCESS; }