diff --git a/.clang-tidy b/.clang-tidy index 59ad5a5e7..b044a7204 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,12 +1,15 @@ Checks: " - modernize-use-*, -modernize-use-trailing-return-type*, - performance-*, - mpi-*, - openmp-*, - bugprone-*, - readability-*, -readability-magic-numbers, -readability-redundant-access-specifiers, - -clang-analyzer-* + -*, + + modernize-use-*, + -modernize-use-trailing-return-type*, + + readability-*, + -readability-magic-numbers, + -readability-redundant-access-specifiers, + -readability-convert-member-functions-to-static, + -readability-isolate-declaration, " AnalyzeTemporaryDtors: false HeaderFilterRegex: 'src/.*' FormatStyle: file diff --git a/.codeclimate.yml b/.codeclimate.yml index bd3c67280..ed1c1d15c 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,11 +1,55 @@ +checks: + duplicate: + enabled: true + exclude_patterns: + - "test/" + - "examples/" + structure: + enabled: true + exclude_patterns: + - "test/" + plugins: editorconfig: enabled: false - pylint: + config: + editorconfig: .editorconfig + exclude_patterns: + - ".clangd/" + - ".cache/" + pep8: enabled: true + exclude_patterns: + - "test/test_fe_engine/py_engine/py_engine.py" cppcheck: - enabled: true + enabled: false project: compile_commands.json language: c++ check: warning, style, performance stds: [c++14] + fixme: + enabled: true + exclude_patterns: + - "doc/" + clang-tidy: + enabled: false + checks: + extra-arg: + - -std=c++14 + - -Ithird-party/akantu_iterators/include + - -Ithird-party/iohelper/src + - -Itest/ci/includes_for_ci + - -Isrc/mesh + checks: + - '-*' + - 'modernize-*' + exclude_patterns: + - test/ + - cmake/ + - examples/ + - extra_packages/ + - .clangd/ + +exclude_patterns: +- "third-party/" +- "build*/" diff --git a/.editorconfig b/.editorconfig index 70f49cc88..ea74e14a8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,23 +1,23 @@ # EditorConfig is awesome: https://EditorConfig.org # top-most EditorConfig file root = true [*] end_of_line = lf insert_final_newline = true max_line_length = 80 [*.{py,cc,hh,cmake,tcc}] charset = utf-8 indent_style = space indent_size = 4 [CMakeLists.txt] charset = utf-8 indent_style = space -indent_size = 4 +indent_size = 2 [*.tcc] file_type_emacs = c++ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f9cf30c31..86df32a91 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,298 +1,348 @@ stages: - configure - build - check-warnings - test - deploy .docker_build: image: 'docker:19.03.11' stage: .pre services: - docker:19.03.11-dind variables: # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled DOCKER_HOST: tcp://docker:2376 DOCKER_TLS_CERTDIR: "/certs" before_script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY script: - cd test/ci/${IMAGE_NAME}/ - docker build -t registry.gitlab.com/akantu/akantu/${IMAGE_NAME} . - docker push registry.gitlab.com/akantu/akantu/${IMAGE_NAME} docker build:debian-testing: variables: IMAGE_NAME: debian:testing extends: .docker_build rules: - changes: - test/ci/debian:testing/Dockerfile docker build:ubuntu-lts: variables: IMAGE_NAME: ubuntu:lts extends: .docker_build rules: - changes: - test/ci/ubuntu:lts/Dockerfile .configure: stage: configure except: - tags variables: BLA_VENDOR: 'Generic' script: - cmake -E make_directory build - cd build - cmake -DAKANTU_COHESIVE_ELEMENT:BOOL=TRUE -DAKANTU_IMPLICIT:BOOL=TRUE -DAKANTU_PARALLEL:BOOL=TRUE -DAKANTU_STRUCTURAL_MECHANICS:BOOL=TRUE -DAKANTU_HEAT_TRANSFER:BOOL=TRUE -DAKANTU_DAMAGE_NON_LOCAL:BOOL=TRUE -DAKANTU_PYTHON_INTERFACE:BOOL=TRUE -DAKANTU_EXAMPLES:BOOL=TRUE -DAKANTU_BUILD_ALL_EXAMPLES:BOOL=TRUE -DAKANTU_TEST_EXAMPLES:BOOL=FALSE -DAKANTU_TESTS:BOOL=TRUE -DAKANTU_RUN_IN_DOCKER:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Coverage .. + - cp compile_commmands.json .. artifacts: when: on_success paths: - build + - compile_commands.json expire_in: 10h .build: stage: build script: - cmake --build build/src > >(tee -a ${output}-out.log) 2> >(tee -a ${output}-err.log >&2) - cmake --build build/python > >(tee -a ${output}-out.log) 2> >(tee -a ${output}-err.log >&2) - cmake --build build/test/ > >(tee -a ${output}-out.log) 2> >(tee -a ${output}-err.log >&2) - cmake --build build/examples > >(tee -a ${output}-out.log) 2> >(tee -a ${output}-err.log >&2) artifacts: when: on_success paths: - build/ #- ${output}-out.log - ${output}-err.log + - compile_commands.json expire_in: 10h .tests: stage: test script: - cd build - ctest -T test --no-compress-output --timeout 1800 after_script: - cd build - tag=$(head -n 1 < Testing/TAG) - if [ -e Testing/${tag}/Test.xml ]; then - xsltproc -o ./juint.xml ${CI_PROJECT_DIR}/test/ci/ctest2junit.xsl Testing/${tag}/Test.xml; - fi - gcovr --xml + --gcov-executable "${GCOV_EXECUTABLE}" --output coverage.xml --object-directory ${CI_PROJECT_DIR}/build --root ${CI_PROJECT_DIR} -s || true artifacts: when: always paths: - build/juint.xml - build/coverage.xml reports: junit: - build/juint.xml cobertura: - build/coverage.xml .analyse_build: stage: check-warnings script: - if [[ $(cat ${output}-err.log | grep warning -i) ]]; then - cat ${output}-err.log; - exit 1; - fi allow_failure: true artifacts: when: on_failure paths: - "$output-err.log" # ------------------------------------------------------------------------------ .cache_build: variables: CCACHE_BASEDIRE: ${CI_PROJECT_DIR}/build CCACHE_DIR: ${CI_PROJECT_DIR}/.ccache CCACHE_NOHASHDIR: 1 CCACHE_COMPILERCHECK: content cache: key: ${output} policy: pull-push paths: - .ccache/ - third-party/google-test - third-party/pybind11 before_script: - ccache --zero-stats || true after_script: - ccache --show-stats || true # ------------------------------------------------------------------------------ .image_debian_testing: image: registry.gitlab.com/akantu/akantu/debian:testing .image_ubuntu_lts: image: registry.gitlab.com/akantu/akantu/ubuntu:lts # ------------------------------------------------------------------------------ .compiler_gcc: variables: CC: /usr/lib/ccache/gcc CXX: /usr/lib/ccache/g++ FC: gfortran + GCOV_EXECUTABLE: gcov .compiler_clang: variables: CC: /usr/lib/ccache/clang CXX: /usr/lib/ccache/clang++ FC: gfortran + GCOV_EXECUTABLE: llvm-cov gcov # ------------------------------------------------------------------------------ .debian_testing_gcc: variables: output: debian_testing_gcc extends: - .compiler_gcc - .image_debian_testing - .cache_build .debian_testing_clang: variables: output: debian_testing_clang extends: - .compiler_clang - .image_debian_testing - .cache_build .ubuntu_lts_gcc: variables: output: ubuntu_lts_gcc extends: - .compiler_gcc - .image_ubuntu_lts - .cache_build # ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------ configure:debian_testing_gcc: extends: - .debian_testing_gcc - .configure cache: policy: pull-push build:debian_testing_gcc: extends: - .debian_testing_gcc - .build dependencies: - configure:debian_testing_gcc test:debian_testing_gcc: extends: - .debian_testing_gcc - .tests dependencies: - build:debian_testing_gcc analyse_build:debian_testing_gcc: extends: - .debian_testing_gcc - .analyse_build dependencies: - build:debian_testing_gcc # ------------------------------------------------------------------------------ configure:debian_testing_clang: extends: - .debian_testing_clang - .configure cache: policy: pull-push build:debian_testing_clang: extends: - .debian_testing_clang - .build dependencies: - configure:debian_testing_clang test:debian_testing_clang: extends: - .debian_testing_clang - .tests dependencies: - build:debian_testing_clang analyse_build:debian_testing_clang: extends: - .debian_testing_clang - .analyse_build dependencies: - build:debian_testing_clang # ------------------------------------------------------------------------------ configure:ubuntu_lts_gcc: extends: - .ubuntu_lts_gcc - .configure cache: policy: pull-push build:ubuntu_lts_gcc: extends: - .ubuntu_lts_gcc - .build dependencies: - configure:ubuntu_lts_gcc analyse_build:ubuntu_lts_gcc: extends: - .ubuntu_lts_gcc - .analyse_build dependencies: - build:ubuntu_lts_gcc test:ubuntu_lts_gcc: extends: - .ubuntu_lts_gcc - .tests dependencies: - build:ubuntu_lts_gcc # ------------------------------------------------------------------------------ -include: - - template: Code-Quality.gitlab-ci.yml - code_quality: + stage: test + image: docker:19.03.12 + allow_failure: true + services: + - docker:19.03.12-dind + variables: + DOCKER_DRIVER: overlay2 + DOCKER_HOST: tcp://docker:2376 + DOCKER_TLS_CERTDIR: "/certs" + CODECLIMATE_DEV: 1 + CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.22" + needs: [] + script: + - export SOURCE_CODE=$PWD + - | # this is required to avoid undesirable reset of Docker image ENV variables being set on build stage + function propagate_env_vars() { + CURRENT_ENV=$(printenv) + for VAR_NAME; do + echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME " + done + } + - docker pull --quiet "$CODE_QUALITY_IMAGE" + - | + - docker build -t codeclimate/codeclimate-clang-tidy test/ci/codeclimate/codeclimate-clang-tidy + - | + docker run \ + $(propagate_env_vars \ + SOURCE_CODE \ + TIMEOUT_SECONDS \ + CODECLIMATE_DEBUG \ + CODECLIMATE_DEV \ + REPORT_STDOUT \ + REPORT_FORMAT \ + ENGINE_MEMORY_LIMIT_BYTES \ + ) \ + --volume "$PWD":/code \ + --volume /var/run/docker.sock:/var/run/docker.sock \ + "$CODE_QUALITY_IMAGE" /code artifacts: - paths: [gl-code-quality-report.json] + paths: + - gl-code-quality-report.json + reports: + codequality: gl-code-quality-report.json + expire_in: 1 week + dependencies: [] + rules: + - if: '$CODE_QUALITY_DISABLED' + when: never + - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH' # ------------------------------------------------------------------------------ pages: stage: deploy extends: - .debian_testing_gcc script: - cd build - cmake -DAKANTU_DOCUMENTATION_DEVELOPER_MANUAL=ON .. - cmake --build . -t sphinx-doc - mv doc/dev-doc/html ../public dependencies: - build:debian_testing_gcc artifacts: paths: - public only: - features/doc diff --git a/cmake/AkantuCleaning.cmake b/cmake/AkantuCleaning.cmake index 8fd50e667..d852abf84 100644 --- a/cmake/AkantuCleaning.cmake +++ b/cmake/AkantuCleaning.cmake @@ -1,82 +1,103 @@ #=============================================================================== # @file AkantuCleaning.cmake # # @author Nicolas Richart # # @date creation: Thu Jun 1, 2017 # # @brief set of tools to clean the code # # @section LICENSE # # Copyright (©) 2010-2012, 2014, 2015 EPFL (Ecole Polytechnique Fédérale de # Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des # Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . #=============================================================================== # Adding clang-format target if executable is found -find_program(CLANG_FORMAT "clang-format") -mark_as_advanced(CLANG_FORMAT) -macro(register_code_to_format) - if(CLANG_FORMAT) - add_custom_target( - clang-format-all - COMMAND ${CLANG_FORMAT} - -i - -style=file - ${ARGN} - ) - endif() -endmacro() - +find_program(CLANG_FORMAT_EXECUTABLE "clang-format") # Adding clang-tidy target if executable is found -find_program(CLANG_TIDY "clang-tidy") -mark_as_advanced(CLANG_TIDY) -macro(register_target_to_tidy target) - if(CLANG_TIDY) - option(AKANTU_CLANG_TIDY_AUTOFIX OFF) - mark_as_advanced(AKANTU_CLANG_TIDY_AUTOFIX) +find_program(CLANG_TIDY_EXECUTABLE "clang-tidy") +find_program(RUN_CLANG_TIDY_EXECUTABLE "run-clang-tidy") - set(_autofix_option) - if(AKANTU_CLANG_TIDY_AUTOFIX) - set(_autofix_option -fix) - endif() - get_target_property(_sources ${target} SOURCES) +mark_as_advanced( + CLANG_FORMAT_EXECUTABLE + CLANG_TIDY_EXECUTABLE + RUN_CLANG_TIDY_EXECUTABLE + ) - file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/clang-tidy) +function(register_code_to_format) + if(NOT CLANG_FORMAT_EXECUTABLE) + endif() + + add_custom_target( + clang-format-all + COMMAND ${CLANG_FORMAT_EXECUTABLE} + -style=file + --output-replacements-xml + ${ARGN} || /bin/true + ) +endfunction() + +function(register_tidy_all directory) + if(NOT RUN_CLANG_TIDY_EXECUTABLE) + return() + endif() - set(_depends) + add_custom_target( + clang-tidy-all + COMMAND ${RUN_CLANG_TIDY_EXECUTABLE} + ${ARGN} + ) +endfunction() - foreach(_src ${_sources}) - get_filename_component(_src_dir ${_src} DIRECTORY) - file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/clang-tidy/${_src_dir}) +function(register_target_to_tidy target) + if(NOT CLANG_TIDY_EXECUTABLE) + return() + endif() - add_custom_command( - OUTPUT ${PROJECT_BINARY_DIR}/clang-tidy/${_src}.yaml - COMMAND ${CLANG_TIDY} - -p=${PROJECT_BINARY_DIR} - -export-fixes=${PROJECT_BINARY_DIR}/clang-tidy/${_src}.yaml - ${_autofix_option} - ${_src} - COMMENT "Tidying ${_src}" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) + option(AKANTU_CLANG_TIDY_AUTOFIX OFF) + mark_as_advanced(AKANTU_CLANG_TIDY_AUTOFIX) - list(APPEND _depends ${PROJECT_BINARY_DIR}/clang-tidy/${_src}.yaml) - endforeach() - add_custom_target(clang-tidy DEPENDS ${_depends}) + set(_autofix_option) + if(AKANTU_CLANG_TIDY_AUTOFIX) + set(_autofix_option -fix) endif() -endmacro() + get_target_property(_sources ${target} SOURCES) + + file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/clang-tidy) + + set(_depends) + + foreach(_src ${_sources}) + get_filename_component(_src_dir ${_src} DIRECTORY) + file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/clang-tidy/${_src_dir}) + + add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/clang-tidy/${_src}.yaml + COMMAND ${CLANG_TIDY_EXECUTABLE} + -p=${PROJECT_BINARY_DIR} + -export-fixes=${PROJECT_BINARY_DIR}/clang-tidy/${_src}.yaml + ${_autofix_option} + ${_src} + COMMENT "Tidying ${_src}" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + + list(APPEND _depends ${PROJECT_BINARY_DIR}/clang-tidy/${_src}.yaml) + endforeach() + add_custom_target(clang-tidy DEPENDS ${_depends}) +endfunction() diff --git a/cmake/AkantuExtraCompilationProfiles.cmake b/cmake/AkantuExtraCompilationProfiles.cmake index fd0fb5ae4..95b8f4b03 100644 --- a/cmake/AkantuExtraCompilationProfiles.cmake +++ b/cmake/AkantuExtraCompilationProfiles.cmake @@ -1,87 +1,89 @@ #Profiling set(_profiling "-g -ggdb3 -pg -DNDEBUG -DAKANTU_NDEBUG -O2") set(CMAKE_CXX_FLAGS_PROFILING ${_profiling} CACHE STRING "Flags used by the compiler during profiling builds") set(CMAKE_C_FLAGS_PROFILING ${_profiling} CACHE STRING "Flags used by the compiler during profiling builds") set(CMAKE_Fortran_FLAGS_PROFILING ${_profiling} CACHE STRING "Flags used by the compiler during profiling builds") set(CMAKE_EXE_LINKER_FLAGS_PROFILING "-pg" CACHE STRING "Flags used by the linker during profiling builds") set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-pg" CACHE STRING "Flags used by the linker during profiling builds") mark_as_advanced( CMAKE_CXX_FLAGS_PROFILING CMAKE_C_FLAGS_PROFILING CMAKE_Fortran_FLAGS_PROFILING CMAKE_EXE_LINKER_FLAGS_PROFILING CMAKE_SHARED_LINKER_FLAGS_PROFILING ) +set(_coverage "-g -ggdb3 -DNDEBUG -DAKANTU_NDEBUG -O2 --coverage") +set(CMAKE_CXX_FLAGS_COVERAGE ${_coverage} + CACHE STRING "Flags used by the compiler during profiling builds" FORCE) +set(CMAKE_C_FLAGS_COVERAGE ${_coverage} + CACHE STRING "Flags used by the compiler during profiling builds" FORCE) +set(CMAKE_Fortran_FLAGS_COVERAGE ${_coverage} + CACHE STRING "Flags used by the compiler during profiling builds" FORCE) +set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE ${_coverage} + CACHE STRING "Flags used by the compiler during profiling builds" FORCE) +set(CMAKE_EXE_LINKER_FLAGS_COVERAGE ${_coverage} + CACHE STRING "Flags used by the linker during sanitizing builds" FORCE) + +mark_as_advanced( + CMAKE_CXX_FLAGS_COVERAGE + CMAKE_C_FLAGS_COVERAGE + CMAKE_Fortran_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_SANITIZEMEMORY + CMAKE_EXE_LINKER_FLAGS_SANITIZEMEMORY + ) + # Sanitize the code if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "5.2") OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") set(_sanitize "-g -ggdb3 -O2 -fsanitize=address -fsanitize=leak -fsanitize=undefined -fno-omit-frame-pointer -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/cmake/sanitize-blacklist.txt") set(CMAKE_CXX_FLAGS_SANITIZE ${_sanitize} CACHE STRING "Flags used by the compiler during sanitizing builds") set(CMAKE_C_FLAGS_SANITIZE ${_sanitize} CACHE STRING "Flags used by the compiler during sanitizing builds") set(CMAKE_Fortran_FLAGS_SANITIZE ${_sanitize} CACHE STRING "Flags used by the compiler during sanitizing builds") set(CMAKE_EXE_LINKER_FLAGS_SANITIZE ${_sanitize} CACHE STRING "Flags used by the linker during sanitizing builds") set(CMAKE_SHARED_LINKER_FLAGS_SANITIZE ${_sanitize} CACHE STRING "Flags used by the linker during sanitizing builds") mark_as_advanced( CMAKE_CXX_FLAGS_SANITIZE CMAKE_C_FLAGS_SANITIZE CMAKE_Fortran_FLAGS_SANITIZE CMAKE_SHARED_LINKER_FLAGS_SANITIZE CMAKE_EXE_LINKER_FLAGS_SANITIZE ) endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - set(_sanitize "-g -ggdb3 -O2 -fPIE -fsanitize=memory -fsanitize-memory-track-origins -fsanitize-recover=all -fno-omit-frame-pointer -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/cmake/sanitize-blacklist.txt") set(CMAKE_CXX_FLAGS_SANITIZEMEMORY ${_sanitize} CACHE STRING "Flags used by the compiler during sanitizing builds") set(CMAKE_C_FLAGS_SANITIZEMEMORY ${_sanitize} CACHE STRING "Flags used by the compiler during sanitizing builds") set(CMAKE_Fortran_FLAGS_SANITIZEMEMORY ${_sanitize} CACHE STRING "Flags used by the compiler during sanitizing builds") set(CMAKE_EXE_LINKER_FLAGS_SANITIZEMEMORY ${_sanitize} CACHE STRING "Flags used by the linker during sanitizing builds") set(CMAKE_SHARED_LINKER_FLAGS_SANITIZEMEMORY ${_sanitize} CACHE STRING "Flags used by the linker during sanitizing builds") mark_as_advanced( CMAKE_CXX_FLAGS_SANITIZEMEMORY CMAKE_C_FLAGS_SANITIZEMEMORY CMAKE_Fortran_FLAGS_SANITIZEMEMORY CMAKE_SHARED_LINKER_FLAGS_SANITIZEMEMORY CMAKE_EXE_LINKER_FLAGS_SANITIZEMEMORY ) endif() - -find_program(GCOV_EXECUTABLE gcov) -if (GCOV_EXECUTABLE) - set(_coverage "-g -ggdb3 -DNDEBUG -DAKANTU_NDEBUG -O2 -fprofile-arcs -ftest-coverage") - set(CMAKE_CXX_FLAGS_COVERAGE ${_coverage} - CACHE STRING "Flags used by the compiler during profiling builds") - set(CMAKE_C_FLAGS_COVERAGE ${_coverage} - CACHE STRING "Flags used by the compiler during profiling builds") - set(CMAKE_Fortran_FLAGS_COVERAGE ${_coverage} - CACHE STRING "Flags used by the compiler during profiling builds") - - mark_as_advanced( - CMAKE_CXX_FLAGS_COVERAGE - CMAKE_C_FLAGS_COVERAGE - CMAKE_Fortran_FLAGS_COVERAGE - ) -endif() diff --git a/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc b/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc index fd81db9fe..abdd6fb08 100644 --- a/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc +++ b/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc @@ -1,149 +1,149 @@ /** * @file cohesive_extrinsic_ig_tg.cc * * @author Seyedeh Mohadeseh Taheri Mousavi * @author Marco Vocialta * * @date creation: Mon Jan 18 2016 * * @brief Test for considering different cohesive properties for intergranular * (IG) and * transgranular (TG) fractures in extrinsic cohesive elements * * * Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory * (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model_cohesive.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ class Velocity : public BC::Dirichlet::DirichletFunctor { public: explicit Velocity(SolidMechanicsModel & model, Real vel, BC::Axis ax = _x) : DirichletFunctor(ax), model(model), vel(vel) { disp = vel * model.getTimeStep(); } public: inline void operator()(UInt node, Vector & /*flags*/, Vector & disp, const Vector & coord) const { Real sign = std::signbit(coord(axis)) ? -1. : 1.; disp(axis) += sign * this->disp; model.getVelocity()(node, axis) = sign * vel; } private: SolidMechanicsModel & model; Real vel, disp; }; /* -------------------------------------------------------------------------- */ int main(int argc, char * argv[]) { initialize("material.dat", argc, argv); const UInt spatial_dimension = 2; const UInt max_steps = 1000; Mesh mesh(spatial_dimension); mesh.read("square.msh"); SolidMechanicsModelCohesive model(mesh); - MaterialCohesiveRules rules{{{"top", "bottom"}, "tg_cohesive"}, - {{"top", "top"}, "ig_cohesive"}, - {{"bottom", "bottom"}, "ig_cohesive"}}; + MaterialCohesiveRules rules{{{"btop", "bbottom"}, "tg_cohesive"}, + {{"btop", "btop"}, "ig_cohesive"}, + {{"bbottom", "bbottom"}, "ig_cohesive"}}; /// model initialization auto material_selector = std::make_shared(model, rules); auto && current_selector = model.getMaterialSelector(); material_selector->setFallback(current_selector); current_selector.setFallback( std::make_shared>("physical_names", model)); model.setMaterialSelector(material_selector); model.initFull(_analysis_method = _explicit_lumped_mass, _is_extrinsic = true); Real time_step = model.getStableTimeStep() * 0.05; model.setTimeStep(time_step); std::cout << "Time step: " << time_step << std::endl; model.assembleMassLumped(); auto & position = mesh.getNodes(); auto & velocity = model.getVelocity(); model.applyBC(BC::Dirichlet::FlagOnly(_y), "top"); model.applyBC(BC::Dirichlet::FlagOnly(_y), "bottom"); model.applyBC(BC::Dirichlet::FlagOnly(_x), "left"); model.applyBC(BC::Dirichlet::FlagOnly(_x), "right"); model.setBaseName("extrinsic"); model.addDumpFieldVector("displacement"); model.addDumpField("velocity"); model.addDumpField("acceleration"); model.addDumpField("internal_force"); model.addDumpField("stress"); model.addDumpField("grad_u"); model.addDumpField("material_index"); model.dump(); /// initial conditions Real loading_rate = 0.1; // bar_height = 2 Real VI = loading_rate * 2 * 0.5; for (auto && data : zip(make_view(position, spatial_dimension), make_view(velocity, spatial_dimension))) { std::get<1>(data) = loading_rate * std::get<0>(data); } model.dump(); Velocity vely(model, VI, _y); Velocity velx(model, VI, _x); /// Main loop for (UInt s = 1; s <= max_steps; ++s) { model.applyBC(vely, "top"); model.applyBC(vely, "bottom"); model.applyBC(velx, "left"); model.applyBC(velx, "right"); model.checkCohesiveStress(); model.solveStep(); if (s % 10 == 0) { model.dump(); std::cout << "passing step " << s << "/" << max_steps << std::endl; } } return 0; } diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index e383b46a2..5ac5d0380 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,102 +1,109 @@ #=============================================================================== # @file CMakeLists.txt # # @author Nicolas Richart # # @date creation: Fri Dec 12 2014 # @date last modification: Mon Jan 18 2016 # # @brief CMake file for the python wrapping of akantu # # @section LICENSE # # Copyright (©) 2015 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory # (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # #=============================================================================== package_get_all_include_directories( AKANTU_LIBRARY_INCLUDE_DIRS ) package_get_all_external_informations( PRIVATE_INCLUDE AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR INTERFACE_INCLUDE AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR LIBRARIES AKANTU_EXTERNAL_LIBRARIES ) set(PYAKANTU_SRCS py_aka_common.cc py_aka_error.cc py_akantu.cc py_boundary_conditions.cc py_fe_engine.cc py_group_manager.cc py_mesh.cc py_model.cc py_parser.cc ) package_is_activated(iohelper _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_dumpable.cc ) endif() package_is_activated(solid_mechanics _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_solid_mechanics_model.cc py_material.cc ) endif() package_is_activated(cohesive_element _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_solid_mechanics_model_cohesive.cc ) endif() package_is_activated(heat_transfer _is_activated) if (_is_activated) list(APPEND PYAKANTU_SRCS py_heat_transfer_model.cc ) endif() pybind11_add_module(py11_akantu ${PYAKANTU_SRCS}) +# to avoid compilation warnings from pybind11 +target_include_directories(py11_akantu + SYSTEM BEFORE + PRIVATE ${PYBIND11_INCLUDE_DIR} + PRIVATE ${pybind11_INCLUDE_DIR} + PRIVATE ${PYTHON_INCLUDE_DIRS}) + target_link_libraries(py11_akantu PUBLIC akantu) set_target_properties(py11_akantu PROPERTIES DEBUG_POSTFIX "") set(_python_install_dir ${CMAKE_INSTALL_LIBDIR}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages) install(TARGETS py11_akantu LIBRARY DESTINATION ${_python_install_dir}) install(DIRECTORY akantu DESTINATION ${_python_install_dir} FILES_MATCHING PATTERN "*.py") configure_file(setup.py.in "${CMAKE_CURRENT_BINARY_DIR}/setup.py" @ONLY) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c5829f302..1e52131e6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,258 +1,264 @@ #=============================================================================== # @file CMakeLists.txt # # @author Guillaume Anciaux # @author Nicolas Richart # # @date creation: Mon Jun 14 2010 # @date last modification: Tue Feb 13 2018 # # @brief CMake file for the library # # @section LICENSE # # Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) # Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) # # Akantu is free software: you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # Akantu is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with Akantu. If not, see . # #=============================================================================== #=============================================================================== # Package Management #=============================================================================== package_get_all_source_files( AKANTU_LIBRARY_SRCS AKANTU_LIBRARY_PUBLIC_HDRS AKANTU_LIBRARY_PRIVATE_HDRS ) package_get_all_include_directories( AKANTU_LIBRARY_INCLUDE_DIRS ) package_get_all_external_informations( PRIVATE_INCLUDE AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR INTERFACE_INCLUDE AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR LIBRARIES AKANTU_EXTERNAL_LIBRARIES ) package_get_all_compilation_flags(CXX _cxx_flags) set(AKANTU_EXTRA_CXX_FLAGS "${_cxx_flags}" CACHE STRING "Extra flags defined by loaded packages" FORCE) mark_as_advanced(AKANTU_EXTRA_CXX_FLAGS) foreach(src_ ${AKANTU_SPIRIT_SOURCES}) set_property(SOURCE ${src_} PROPERTY COMPILE_FLAGS "-g0 -Werror") endforeach() #=========================================================================== # header for blas/lapack (any other fortran libraries) #=========================================================================== package_is_activated(BLAS _blas_activated) package_is_activated(LAPACK _lapack_activated) if(_blas_activated OR _lapack_activated) if(CMAKE_Fortran_COMPILER) # ugly hack set(CMAKE_Fortran_COMPILER_LOADED TRUE) endif() include(FortranCInterface) FortranCInterface_HEADER( "${CMAKE_CURRENT_BINARY_DIR}/aka_fortran_mangling.hh" MACRO_NAMESPACE "AKA_FC_") mark_as_advanced(CDEFS) list(APPEND AKANTU_LIBRARY_PUBLIC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/aka_fortran_mangling.hh" ) endif() list(APPEND AKANTU_LIBRARY_INCLUDE_DIRS "${CMAKE_CURRENT_BINARY_DIR}") set(AKANTU_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} ${AKANTU_LIBRARY_INCLUDE_DIRS} CACHE INTERNAL "Internal include directories to link with Akantu as a subproject") #=========================================================================== # configurations #=========================================================================== package_get_all_material_includes(AKANTU_MATERIAL_INCLUDES) package_get_all_material_lists(AKANTU_MATERIAL_LISTS) configure_file(model/solid_mechanics/material_list.hh.in "${CMAKE_CURRENT_BINARY_DIR}/material_list.hh" @ONLY) package_get_element_lists() configure_file(common/aka_element_classes_info.hh.in "${CMAKE_CURRENT_BINARY_DIR}/aka_element_classes_info.hh" @ONLY) configure_file(common/aka_config.hh.in "${CMAKE_CURRENT_BINARY_DIR}/aka_config.hh" @ONLY) list(APPEND AKANTU_LIBRARY_PUBLIC_HDRS "${CMAKE_CURRENT_BINARY_DIR}/material_list.hh" "${CMAKE_CURRENT_BINARY_DIR}/aka_element_classes_info.hh" "${CMAKE_CURRENT_BINARY_DIR}/aka_config.hh") #=============================================================================== # Debug infos #=============================================================================== set(AKANTU_GDB_DIR ${PROJECT_SOURCE_DIR}/cmake) if(UNIX AND NOT APPLE) string(TOUPPER "${CMAKE_BUILD_TYPE}" _u_build_type) if(_u_build_type STREQUAL "DEBUG" OR _u_build_type STREQUAL "RELWITHDEBINFO") configure_file(${PROJECT_SOURCE_DIR}/cmake/libakantu-gdb.py.in "${PROJECT_BINARY_DIR}/libakantu-gdb.py" @ONLY) configure_file(${PROJECT_SOURCE_DIR}/cmake/akantu-debug.cc.in "${PROJECT_BINARY_DIR}/akantu-debug.cc" @ONLY) list(APPEND AKANTU_LIBRARY_SRCS ${PROJECT_BINARY_DIR}/akantu-debug.cc) endif() else() find_program(GDB_EXECUTABLE gdb) if(GDB_EXECUTABLE) execute_process(COMMAND ${GDB_EXECUTABLE} --batch -x "${PROJECT_SOURCE_DIR}/cmake/gdb_python_path" OUTPUT_VARIABLE AKANTU_PYTHON_GDB_DIR ERROR_QUIET RESULT_VARIABLE _res) if(_res EQUAL 0 AND UNIX) set(GDB_USER_CONFIG $ENV{HOME}/.gdb/auto-load) file(MAKE_DIRECTORY ${GDB_USER_CONFIG}) configure_file(${PROJECT_SOURCE_DIR}/cmake/libakantu-gdb.py.in "${GDB_USER_CONFIG}/${CMAKE_SHARED_LIBRARY_PREFIX}akantu${CMAKE_SHARED_LIBRARY_SUFFIX}.${AKANTU_VERSION}-gdb.py" @ONLY) endif() endif() endif() #=============================================================================== # GIT info #=============================================================================== #include(AkantuBuildOptions) #git_version_info(akantu_git_info ALL # OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/akantu_git_info.hh # ) #list(APPEND AKANTU_LIBRARY_SRCS ${CMAKE_CURRENT_BINARY_DIR}/akantu_git_info.hh) #=============================================================================== # Library generation #=============================================================================== add_library(akantu ${AKANTU_LIBRARY_SRCS}) target_include_directories(akantu PRIVATE $ INTERFACE $ ) # small trick for build includes in public set_property(TARGET akantu APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES $) target_include_directories(akantu SYSTEM PUBLIC ${AKANTU_INTERFACE_EXTERNAL_INCLUDE_DIR} ) target_include_directories(akantu SYSTEM PRIVATE ${AKANTU_PRIVATE_EXTERNAL_INCLUDE_DIR} ) target_link_libraries(akantu PUBLIC ${AKANTU_EXTERNAL_LIBRARIES}) set_target_properties(akantu PROPERTIES ${AKANTU_LIBRARY_PROPERTIES} # this contains the version COMPILE_FLAGS "${_cxx_flags}" #PRIVATE_HEADER ${AKANTU_LIBRARY_PRIVATE_HDRS} ) if(AKANTU_LIBRARY_PUBLIC_HDRS) set_property(TARGET akantu PROPERTY PUBLIC_HEADER ${AKANTU_LIBRARY_PUBLIC_HDRS}) endif() if(AKANTU_LIBRARY_PRIVATE_HDRS) set_property(TARGET akantu PROPERTY PRIVATE_HEADER ${AKANTU_LIBRARY_PRIVATE_HDRS}) endif() if(NOT CMAKE_VERSION VERSION_LESS 3.1) package_get_all_features_public(_PUBLIC_features) package_get_all_features_private(_PRIVATE_features) foreach(_type PRIVATE PUBLIC) if(_${_type}_features) target_compile_features(akantu ${_type} ${_${_type}_features}) endif() endforeach() else() set_target_properties(akantu PROPERTIES CXX_STANDARD 14 ) endif() package_get_all_extra_dependencies(_extra_target_dependencies) if(_extra_target_dependencies) # This only adding todo: find a solution for when a dependency was add the is removed... add_dependencies(akantu ${_extra_target_dependencies}) endif() package_get_all_export_list(AKANTU_EXPORT_LIST) list(APPEND AKANTU_EXPORT_LIST akantu) # TODO separate public from private headers install(TARGETS akantu EXPORT ${AKANTU_TARGETS_EXPORT} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT Akantu_runtime # NAMELINK_ONLY # LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # COMPONENT Akantu_development # NAMELINK_SKIP Akantu_development ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT Akantu_runtime RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Akantu_runtime PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/akantu/ COMPONENT Akantu_development ) if("${AKANTU_TARGETS_EXPORT}" STREQUAL "AkantuTargets") install(EXPORT AkantuTargets DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME} COMPONENT dev) #Export for build tree export(EXPORT AkantuTargets FILE "${CMAKE_BINARY_DIR}/AkantuTargets.cmake") export(PACKAGE Akantu) endif() #=============================================================================== # Adding module names for debug package_get_all_packages(_pkg_list) foreach(_pkg ${_pkg_list}) _package_get_real_name(${_pkg} _pkg_name) _package_get_source_files(${_pkg} _srcs _public_hdrs _private_hdrs) string(TOLOWER "${_pkg_name}" _l_package_name) set_property(SOURCE ${_srcs} ${_public_hdrs} ${_private_hdrs} APPEND PROPERTY COMPILE_DEFINITIONS AKANTU_MODULE=${_l_package_name}) endforeach() # print out the list of materials generate_material_list() register_target_to_tidy(akantu) +register_tidy_all(${AKANTU_LIBRARY_SRCS}) +register_code_to_format( + ${AKANTU_LIBRARY_SRCS} + ${AKANTU_LIBRARY_PUBLIC_HDRS} + ${AKANTU_LIBRARY_PRIVATE_HDRS} + ) diff --git a/src/common/aka_common.hh b/src/common/aka_common.hh index 2ed3abb16..48184d82b 100644 --- a/src/common/aka_common.hh +++ b/src/common/aka_common.hh @@ -1,654 +1,654 @@ /** * @file aka_common.hh * * @author Guillaume Anciaux * @author Nicolas Richart * * @date creation: Mon Jun 14 2010 * @date last modification: Mon Feb 12 2018 * * @brief common type descriptions for akantu * * * Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef AKANTU_COMMON_HH_ #define AKANTU_COMMON_HH_ #include "aka_compatibilty_with_cpp_standard.hh" /* -------------------------------------------------------------------------- */ #if defined(WIN32) #define __attribute__(x) #endif /* -------------------------------------------------------------------------- */ #include "aka_config.hh" #include "aka_error.hh" #include "aka_safe_enum.hh" /* -------------------------------------------------------------------------- */ #include #include #include #include #include #include #include /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ /* Constants */ /* -------------------------------------------------------------------------- */ namespace { [[gnu::unused]] constexpr UInt _all_dimensions{ std::numeric_limits::max()}; #ifdef AKANTU_NDEBUG [[gnu::unused]] constexpr Real REAL_INIT_VALUE{0.}; #else [[gnu::unused]] constexpr Real REAL_INIT_VALUE{ std::numeric_limits::quiet_NaN()}; #endif } // namespace /* -------------------------------------------------------------------------- */ /* Common types */ /* -------------------------------------------------------------------------- */ using ID = std::string; using MemoryID = UInt; } // namespace akantu /* -------------------------------------------------------------------------- */ #include "aka_enum_macros.hh" /* -------------------------------------------------------------------------- */ #include "aka_element_classes_info.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ /* Mesh/FEM/Model types */ /* -------------------------------------------------------------------------- */ /// small help to use names for directions enum SpatialDirection { _x = 0, _y = 1, _z = 2 }; /// enum MeshIOType type of mesh reader/writer enum MeshIOType { _miot_auto, ///< Auto guess of the reader to use based on the extension _miot_gmsh, ///< Gmsh files _miot_gmsh_struct, ///< Gsmh reader with reintpretation of elements has /// structures elements _miot_diana, ///< TNO Diana mesh format _miot_abaqus ///< Abaqus mesh format }; /// enum MeshEventHandlerPriority defines relative order of execution of /// events enum EventHandlerPriority { _ehp_highest = 0, _ehp_mesh = 5, _ehp_fe_engine = 9, _ehp_synchronizer = 10, _ehp_dof_manager = 20, _ehp_model = 94, _ehp_non_local_manager = 100, _ehp_lowest = 100 }; #if !defined(DOXYGEN) // clang-format off #define AKANTU_MODEL_TYPES \ (model) \ (solid_mechanics_model) \ (solid_mechanics_model_cohesive) \ (heat_transfer_model) \ (structural_mechanics_model) \ (embedded_model) // clang-format on /// enum ModelType defines which type of physics is solved AKANTU_CLASS_ENUM_DECLARE(ModelType, AKANTU_MODEL_TYPES) AKANTU_CLASS_ENUM_OUTPUT_STREAM(ModelType, AKANTU_MODEL_TYPES) AKANTU_CLASS_ENUM_INPUT_STREAM(ModelType, AKANTU_MODEL_TYPES) #else enum class ModelType { model, solid_mechanics_model, solid_mechanics_model_cohesive, heat_transfer_model, structural_mechanics_model, embedded_model, }; #endif /// enum AnalysisMethod type of solving method used to solve the equation of /// motion enum AnalysisMethod { _static = 0, _implicit_dynamic = 1, _explicit_lumped_mass = 2, _explicit_lumped_capacity = 2, _explicit_consistent_mass = 3 }; /// enum DOFSupportType defines which kind of dof that can exists enum DOFSupportType { _dst_nodal, _dst_generic }; #if !defined(DOXYGEN) // clang-format off #define AKANTU_NON_LINEAR_SOLVER_TYPES \ (linear) \ (newton_raphson) \ (newton_raphson_modified) \ (lumped) \ (gmres) \ (bfgs) \ (cg) \ (auto) // clang-format on AKANTU_CLASS_ENUM_DECLARE(NonLinearSolverType, AKANTU_NON_LINEAR_SOLVER_TYPES) AKANTU_CLASS_ENUM_OUTPUT_STREAM(NonLinearSolverType, AKANTU_NON_LINEAR_SOLVER_TYPES) AKANTU_CLASS_ENUM_INPUT_STREAM(NonLinearSolverType, AKANTU_NON_LINEAR_SOLVER_TYPES) #else /// Type of non linear resolution available in akantu enum class NonLinearSolverType { _linear, ///< No non linear convergence loop _newton_raphson, ///< Regular Newton-Raphson _newton_raphson_modified, ///< Newton-Raphson with initial tangent _lumped, ///< Case of lumped mass or equivalent matrix _gmres, _bfgs, _cg, _auto ///< This will take a default value that make sense in case of /// model::getNewSolver }; #endif #if !defined(DOXYGEN) // clang-format off #define AKANTU_TIME_STEP_SOLVER_TYPE \ (static) \ (dynamic) \ (dynamic_lumped) \ (not_defined) // clang-format on AKANTU_CLASS_ENUM_DECLARE(TimeStepSolverType, AKANTU_TIME_STEP_SOLVER_TYPE) AKANTU_CLASS_ENUM_OUTPUT_STREAM(TimeStepSolverType, AKANTU_TIME_STEP_SOLVER_TYPE) AKANTU_CLASS_ENUM_INPUT_STREAM(TimeStepSolverType, AKANTU_TIME_STEP_SOLVER_TYPE) #else /// Type of time stepping solver enum class TimeStepSolverType { _static, ///< Static solution _dynamic, ///< Dynamic solver _dynamic_lumped, ///< Dynamic solver with lumped mass _not_defined, ///< For not defined cases }; #endif #if !defined(DOXYGEN) // clang-format off #define AKANTU_INTEGRATION_SCHEME_TYPE \ (pseudo_time) \ (forward_euler) \ (trapezoidal_rule_1) \ (backward_euler) \ (central_difference) \ (fox_goodwin) \ (trapezoidal_rule_2) \ (linear_acceleration) \ (newmark_beta) \ (generalized_trapezoidal) // clang-format on AKANTU_CLASS_ENUM_DECLARE(IntegrationSchemeType, AKANTU_INTEGRATION_SCHEME_TYPE) AKANTU_CLASS_ENUM_OUTPUT_STREAM(IntegrationSchemeType, AKANTU_INTEGRATION_SCHEME_TYPE) AKANTU_CLASS_ENUM_INPUT_STREAM(IntegrationSchemeType, AKANTU_INTEGRATION_SCHEME_TYPE) #else /// Type of integration scheme enum class IntegrationSchemeType { _pseudo_time, ///< Pseudo Time _forward_euler, ///< GeneralizedTrapezoidal(0) _trapezoidal_rule_1, ///< GeneralizedTrapezoidal(1/2) _backward_euler, ///< GeneralizedTrapezoidal(1) _central_difference, ///< NewmarkBeta(0, 1/2) _fox_goodwin, ///< NewmarkBeta(1/6, 1/2) _trapezoidal_rule_2, ///< NewmarkBeta(1/2, 1/2) _linear_acceleration, ///< NewmarkBeta(1/3, 1/2) _newmark_beta, ///< generic NewmarkBeta with user defined /// alpha and beta _generalized_trapezoidal ///< generic GeneralizedTrapezoidal with user /// defined alpha }; #endif #if !defined(DOXYGEN) // clang-format off #define AKANTU_SOLVE_CONVERGENCE_CRITERIA \ (residual) \ (solution) \ (residual_mass_wgh) // clang-format on AKANTU_CLASS_ENUM_DECLARE(SolveConvergenceCriteria, AKANTU_SOLVE_CONVERGENCE_CRITERIA) AKANTU_CLASS_ENUM_OUTPUT_STREAM(SolveConvergenceCriteria, AKANTU_SOLVE_CONVERGENCE_CRITERIA) AKANTU_CLASS_ENUM_INPUT_STREAM(SolveConvergenceCriteria, AKANTU_SOLVE_CONVERGENCE_CRITERIA) #else /// enum SolveConvergenceCriteria different convergence criteria enum class SolveConvergenceCriteria { _residual, ///< Use residual to test the convergence _solution, ///< Use solution to test the convergence _residual_mass_wgh ///< Use residual weighted by inv. nodal mass to ///< testb }; #endif /// enum CohesiveMethod type of insertion of cohesive elements enum CohesiveMethod { _intrinsic, _extrinsic }; /// @enum MatrixType type of sparse matrix used enum MatrixType { _unsymmetric, _symmetric, _mt_not_defined }; /* -------------------------------------------------------------------------- */ /* Ghosts handling */ /* -------------------------------------------------------------------------- */ /// @enum CommunicatorType type of communication method to use enum CommunicatorType { _communicator_mpi, _communicator_dummy }; #if !defined(DOXYGEN) // clang-format off #define AKANTU_SYNCHRONIZATION_TAG \ (whatever) \ (update) \ (ask_nodes) \ (size) \ (smm_mass) \ (smm_for_gradu) \ (smm_boundary) \ (smm_uv) \ (smm_res) \ (smm_init_mat) \ (smm_stress) \ (smmc_facets) \ (smmc_facets_conn) \ (smmc_facets_stress) \ (smmc_damage) \ (giu_global_conn) \ (ce_groups) \ (ce_insertion_order) \ (gm_clusters) \ (htm_temperature) \ (htm_gradient_temperature) \ (htm_phi) \ (htm_gradient_phi) \ (mnl_for_average) \ (mnl_weight) \ (nh_criterion) \ (test) \ (user_1) \ (user_2) \ (material_id) \ (for_dump) \ (cf_nodal) \ (cf_incr) \ (solver_solution) // clang-format on AKANTU_CLASS_ENUM_DECLARE(SynchronizationTag, AKANTU_SYNCHRONIZATION_TAG) AKANTU_CLASS_ENUM_OUTPUT_STREAM(SynchronizationTag, AKANTU_SYNCHRONIZATION_TAG) #else /// @enum SynchronizationTag type of synchronizations enum class SynchronizationTag { //--- Generic tags --- _whatever, _update, _ask_nodes, _size, //--- SolidMechanicsModel tags --- _smm_mass, ///< synchronization of the SolidMechanicsModel.mass _smm_for_gradu, ///< synchronization of the /// SolidMechanicsModel.displacement _smm_boundary, ///< synchronization of the boundary, forces, velocities /// and displacement _smm_uv, ///< synchronization of the nodal velocities and displacement _smm_res, ///< synchronization of the nodal residual _smm_init_mat, ///< synchronization of the data to initialize materials _smm_stress, ///< synchronization of the stresses to compute the ///< internal /// forces _smmc_facets, ///< synchronization of facet data to setup facet synch _smmc_facets_conn, ///< synchronization of facet global connectivity _smmc_facets_stress, ///< synchronization of facets' stress to setup ///< facet /// synch _smmc_damage, ///< synchronization of damage // --- GlobalIdsUpdater tags --- _giu_global_conn, ///< synchronization of global connectivities // --- CohesiveElementInserter tags --- _ce_groups, ///< synchronization of cohesive element insertion depending /// on facet groups _ce_insertion_order, ///< synchronization of the order of insertion of - ///cohesive elements + /// cohesive elements // --- GroupManager tags --- _gm_clusters, ///< synchronization of clusters // --- HeatTransfer tags --- _htm_temperature, ///< synchronization of the nodal temperature _htm_gradient_temperature, ///< synchronization of the element gradient /// temperature // --- LevelSet tags --- _htm_phi, ///< synchronization of the nodal level set value phi _htm_gradient_phi, ///< synchronization of the element gradient phi //--- Material non local --- _mnl_for_average, ///< synchronization of data to average in non local /// material _mnl_weight, ///< synchronization of data for the weight computations // --- NeighborhoodSynchronization tags --- _nh_criterion, // --- General tags --- _test, ///< Test tag _user_1, ///< tag for user simulations _user_2, ///< tag for user simulations _material_id, ///< synchronization of the material ids _for_dump, ///< everything that needs to be synch before dump // --- Contact & Friction --- _cf_nodal, ///< synchronization of disp, velo, and current position _cf_incr, ///< synchronization of increment // --- Solver tags --- _solver_solution ///< synchronization of the solution obained with the /// PETSc solver }; #endif /// @enum GhostType type of ghost enum GhostType { _not_ghost = 0, _ghost = 1, _casper // not used but a real cute ghost }; /// Define the flag that can be set to a node enum class NodeFlag : std::uint8_t { _normal = 0x00, _distributed = 0x01, _master = 0x03, _slave = 0x05, _pure_ghost = 0x09, _shared_mask = 0x0F, _periodic = 0x10, _periodic_master = 0x30, _periodic_slave = 0x50, _periodic_mask = 0xF0, _local_master_mask = 0xCC, // ~(_master & _periodic_mask) }; inline NodeFlag operator&(const NodeFlag & a, const NodeFlag & b) { using under = std::underlying_type_t; return NodeFlag(under(a) & under(b)); } inline NodeFlag operator|(const NodeFlag & a, const NodeFlag & b) { using under = std::underlying_type_t; return NodeFlag(under(a) | under(b)); } inline NodeFlag & operator|=(NodeFlag & a, const NodeFlag & b) { a = a | b; return a; } inline NodeFlag & operator&=(NodeFlag & a, const NodeFlag & b) { a = a & b; return a; } inline NodeFlag operator~(const NodeFlag & a) { using under = std::underlying_type_t; return NodeFlag(~under(a)); } std::ostream & operator<<(std::ostream & stream, NodeFlag flag); } // namespace akantu AKANTU_ENUM_HASH(GhostType) namespace akantu { /* -------------------------------------------------------------------------- */ struct GhostType_def { using type = GhostType; static const type _begin_ = _not_ghost; static const type _end_ = _casper; }; using ghost_type_t = safe_enum; namespace { constexpr ghost_type_t ghost_types{_casper}; } /// standard output stream operator for GhostType // inline std::ostream & operator<<(std::ostream & stream, GhostType type); /* -------------------------------------------------------------------------- */ /* Global defines */ /* -------------------------------------------------------------------------- */ #define AKANTU_MIN_ALLOCATION 2000 #define AKANTU_INDENT ' ' #define AKANTU_INCLUDE_INLINE_IMPL /* -------------------------------------------------------------------------- */ #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_DEREF_PTR(name, ptr) \ inline const auto & get##name() const { \ if (not(ptr)) { \ AKANTU_EXCEPTION("The member " << #ptr << " is not initialized"); \ } \ return (*(ptr)); \ } #define AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(name, ptr) \ inline auto & get##name() { \ if (not(ptr)) { \ AKANTU_EXCEPTION("The member " << #ptr << " is not initialized"); \ } \ return (*(ptr)); \ } #define AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, support, con) \ inline con Array & get##name(const support & el_type, \ GhostType ghost_type = _not_ghost) \ con { /* NOLINT */ \ return variable(el_type, ghost_type); \ } // NOLINT #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType, ) #define AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, ElementType, const) #define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType, ) #define AKANTU_GET_MACRO_BY_GEOMETRIE_TYPE_CONST(name, variable, type) \ AKANTU_GET_MACRO_BY_SUPPORT_TYPE(name, variable, type, GeometricalType, const) /* -------------------------------------------------------------------------- */ /// initialize the static part of akantu void initialize(int & argc, char **& argv); /// initialize the static part of akantu and read the global input_file void initialize(const std::string & input_file, int & argc, char **& argv); /* -------------------------------------------------------------------------- */ /// finilize correctly akantu and clean the memory void finalize(); /* -------------------------------------------------------------------------- */ /// Read an new input file void readInputFile(const std::string & input_file); /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /* string manipulation */ /* -------------------------------------------------------------------------- */ inline std::string to_lower(const std::string & str); /* -------------------------------------------------------------------------- */ inline std::string trim(const std::string & to_trim); inline std::string trim(const std::string & to_trim, char c); /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ /// give a string representation of the a human readable size in bit template std::string printMemorySize(UInt size); /* -------------------------------------------------------------------------- */ struct TensorTrait {}; struct TensorProxyTrait {}; } // namespace akantu /* -------------------------------------------------------------------------- */ /* Type traits */ /* -------------------------------------------------------------------------- */ namespace aka { /* ------------------------------------------------------------------------ */ template using is_tensor = std::is_base_of; template using is_tensor_proxy = std::is_base_of; /* ------------------------------------------------------------------------ */ template using is_scalar = std::is_arithmetic; /* ------------------------------------------------------------------------ */ template ::value> * = nullptr> bool is_of_type(T && t) { return ( dynamic_cast>::value, std::add_const_t, R>>>(&t) != nullptr); } /* -------------------------------------------------------------------------- */ template bool is_of_type(std::unique_ptr & t) { return ( dynamic_cast::value, std::add_const_t, R>>>( t.get()) != nullptr); } /* ------------------------------------------------------------------------ */ template ::value> * = nullptr> decltype(auto) as_type(T && t) { static_assert( disjunction< std::is_base_of, std::decay_t>, // down-cast std::is_base_of, std::decay_t> // up-cast >::value, "Type T and R are not valid for a as_type conversion"); return dynamic_cast>::value, std::add_const_t, R>>>(t); } /* -------------------------------------------------------------------------- */ template ::value> * = nullptr> decltype(auto) as_type(T && t) { return &as_type(*t); } /* -------------------------------------------------------------------------- */ template decltype(auto) as_type(const std::shared_ptr & t) { return std::dynamic_pointer_cast(t); } } // namespace aka #include "aka_common_inline_impl.hh" #include "aka_fwd.hh" namespace akantu { /// get access to the internal argument parser cppargparse::ArgumentParser & getStaticArgumentParser(); /// get access to the internal input file parser Parser & getStaticParser(); /// get access to the user part of the internal input file parser const ParserSection & getUserParser(); #define AKANTU_CURRENT_FUNCTION \ (std::string(__func__) + "():" + std::to_string(__LINE__)) } // namespace akantu /* -------------------------------------------------------------------------- */ #if AKANTU_INTEGER_SIZE == 4 #define AKANTU_HASH_COMBINE_MAGIC_NUMBER 0x9e3779b9 #elif AKANTU_INTEGER_SIZE == 8 #define AKANTU_HASH_COMBINE_MAGIC_NUMBER 0x9e3779b97f4a7c13LL #endif namespace std { /** * Hashing function for pairs based on hash_combine from boost The magic * number is coming from the golden number @f[\phi = \frac{1 + \sqrt5}{2}@f] * @f[\frac{2^32}{\phi} = 0x9e3779b9@f] * http://stackoverflow.com/questions/4948780/magic-number-in-boosthash-combine * http://burtleburtle.net/bob/hash/doobs.html */ template struct hash> { hash() = default; size_t operator()(const std::pair & p) const { size_t seed = ah(p.first); return bh(p.second) + AKANTU_HASH_COMBINE_MAGIC_NUMBER + (seed << 6) + (seed >> 2); } private: const hash ah{}; const hash bh{}; }; } // namespace std #endif // AKANTU_COMMON_HH_ diff --git a/src/common/aka_common_inline_impl.hh b/src/common/aka_common_inline_impl.hh index 64616aa1a..31a34b97f 100644 --- a/src/common/aka_common_inline_impl.hh +++ b/src/common/aka_common_inline_impl.hh @@ -1,150 +1,129 @@ /** * @file aka_common_inline_impl.hh * * @author Guillaume Anciaux * @author Nicolas Richart * * @date creation: Fri Jun 18 2010 * @date last modification: Tue Feb 20 2018 * * @brief inline implementations of common akantu type descriptions * * * Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #include #include #include #include #include +#include /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ /// standard output stream operator for GhostType inline std::ostream & operator<<(std::ostream & stream, GhostType type) { switch (type) { case _not_ghost: stream << "not_ghost"; break; case _ghost: stream << "ghost"; break; case _casper: stream << "Casper the friendly ghost"; break; } return stream; } /* -------------------------------------------------------------------------- */ inline std::string to_lower(const std::string & str) { std::string lstr = str; std::transform(lstr.begin(), lstr.end(), lstr.begin(), (int (*)(int))tolower); return lstr; } namespace { template inline std::string trim_p(const std::string & to_trim, pred && p) { std::string trimed = to_trim; auto && not_ = [&](auto && a) { return not p(a); }; // left trim trimed.erase(trimed.begin(), std::find_if(trimed.begin(), trimed.end(), not_)); // right trim trimed.erase(std::find_if(trimed.rbegin(), trimed.rend(), not_).base(), trimed.end()); return trimed; } } // namespace /* -------------------------------------------------------------------------- */ inline std::string trim(const std::string & to_trim) { return trim_p(to_trim, [&](auto && a) { return std::isspace(a); }); } inline std::string trim(const std::string & to_trim, char c) { return trim_p(to_trim, [&c](auto && a) { return (a == c); }); } /* -------------------------------------------------------------------------- */ template std::string printMemorySize(UInt size) { Real real_size = size * sizeof(T); UInt mult = 0; if (real_size != 0) { mult = (std::log(real_size) / std::log(2)) / 10; } std::stringstream sstr; real_size /= Real(1 << (10 * mult)); sstr << std::setprecision(2) << std::fixed << real_size; std::string size_prefix; - switch (mult) { - case 0: - sstr << ""; - break; - case 1: - sstr << "Ki"; - break; - case 2: - sstr << "Mi"; - break; - case 3: - sstr << "Gi"; - break; // I started on this type of machines - // (32bit computers) (Nicolas) - case 4: - sstr << "Ti"; - break; - case 5: - sstr << "Pi"; - break; - case 6: - sstr << "Ei"; - break; // theoritical limit of RAM of the current - // computers in 2014 (64bit computers) (Nicolas) - case 7: - sstr << "Zi"; - break; - case 8: - sstr << "Yi"; - break; - default: + std::array ratio = { + "", "Ki", "Mi", + "Gi", // I started on this type of machines (32bit computers) (Nicolas) + "Ti", "Pi", + "Ei", // theoritical limit of RAM of the current computers in 2014 (64bit + // computers) (Nicolas) + "Zi", "Yi"}; + + if (mult >= ratio.size()) { AKANTU_ERROR( "The programmer in 2014 didn't thought so far (even wikipedia does not " "go further)." << " You have at least 1024 times more than a yobibit of RAM!!!" - << " Just add the prefix corresponding in this switch case."); + << " Just add the prefix corresponding in the ratio array."); } - sstr << "Byte"; + sstr << ratio[mult] << "Byte"; return sstr.str(); } } // namespace akantu diff --git a/src/common/aka_error.hh b/src/common/aka_error.hh index 269a7400b..e048320f9 100644 --- a/src/common/aka_error.hh +++ b/src/common/aka_error.hh @@ -1,418 +1,419 @@ /** * @file aka_error.hh * * @author Nicolas Richart * * @date creation: Mon Jun 14 2010 * @date last modification: Tue Feb 20 2018 * * @brief error management and internal exceptions * * * Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include #include #include #include #include /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #ifndef AKANTU_ERROR_HH_ #define AKANTU_ERROR_HH_ namespace 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, dblDebug = 42, dbl100 = 100, dblDump = 100, dblTest = 1337 }; /* -------------------------------------------------------------------------- */ #define AKANTU_LOCATION \ "(" << std::string(__func__) << "(): " << std::string(__FILE__) << ":" \ << std::to_string(__LINE__) \ << ")" // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay) /* -------------------------------------------------------------------------- */ namespace debug { void setDebugLevel(const DebugLevel & level); const DebugLevel & getDebugLevel(); void initSignalHandler(); std::string demangle(const char * symbol); template std::string demangle() { return demangle(typeid(T).name()); } template std::string demangle(const T & t) { return demangle(typeid(t).name()); } auto exec(const std::string & cmd) -> std::string; auto getBacktrace() -> std::vector; void printBacktrace(const std::vector & backtrace = getBacktrace()); void exit(int status) __attribute__((noreturn)); /* ------------------------------------------------------------------------ */ /// exception class that can be thrown by akantu class Exception : public std::exception { /* ---------------------------------------------------------------------- */ /* Constructors/Destructors */ /* ---------------------------------------------------------------------- */ protected: - explicit Exception(std::string info = "") : _info(std::move(info)) {} + explicit Exception(const std::string & info = "") : _info(info) {} public: //! full constructor - Exception(std::string info, std::string file, unsigned int line) - : _info(std::move(info)), _file(std::move(file)), _line(line) {} + Exception(const std::string & info, const std::string & file, + unsigned int line) + : _info(info), _file(file), _line(line) {} /* ---------------------------------------------------------------------- */ /* Methods */ /* ---------------------------------------------------------------------- */ public: const char * what() const noexcept override { return _info.c_str(); } virtual std::string info() const noexcept { std::stringstream stream; stream << debug::demangle(typeid(*this).name()) << " : " << _info << " [" << _file << ":" << _line << "]"; return stream.str(); } public: void setInfo(const std::string & info) { _info = info; } void setFile(const std::string & file) { _file = file; } void setLine(unsigned int line) { _line = line; } void setModule(const std::string & module) { _module = module; } void setBacktrace(const std::vector & backtrace) { backtrace_ = backtrace; } decltype(auto) backtrace() const { return backtrace_; } /* ---------------------------------------------------------------------- */ /* Class Members */ /* ---------------------------------------------------------------------- */ protected: /// exception description and additionals std::string _info; private: /// file it is thrown from std::string _file; /// line it is thrown from unsigned int _line{0}; /// module in which exception was raised std::string _module{"core"}; std::vector backtrace_; }; class CriticalError : public Exception {}; class AssertException : public Exception {}; class NotImplementedException : public Exception {}; /// standard output stream operator inline std::ostream & operator<<(std::ostream & stream, const Exception & _this) { stream << _this.what(); return stream; } /* -------------------------------------------------------------------------- */ class Debugger { public: Debugger() noexcept; virtual ~Debugger(); Debugger(const Debugger &) = default; Debugger & operator=(const Debugger &) = default; Debugger(Debugger &&) noexcept = default; Debugger & operator=(Debugger &&) noexcept = default; static void exit(int status) __attribute__((noreturn)); void throwException(const std::string & info, const std::string & file, unsigned int line, bool /*silent*/, const std::string & /*location*/, const std::string & module) const noexcept(false) __attribute__((noreturn)); /*----------------------------------------------------------------------- */ template void throwCustomException(Except ex, const std::string & info, const std::string & file, unsigned int line, const std::string & module) const noexcept(false) __attribute__((noreturn)); /*----------------------------------------------------------------------- */ template void throwCustomException(Except ex, const std::string & file, unsigned int line, const std::string & module_) const noexcept(false) __attribute__((noreturn)); void printMessage(const std::string & prefix, const DebugLevel & level, const std::string & info, const std::string & module_) const; void setOutStream(std::ostream & out) { cout = &out; } std::ostream & getOutStream() { return *cout; } public: void setParallelContext(int rank, int size); void setDebugLevel(const DebugLevel & level); const DebugLevel & getDebugLevel() const; void setLogFile(const std::string & filename); std::ostream & getOutputStream(); inline bool testLevel(const DebugLevel & level, const std::string & module = "core") const { auto level_reached = (this->level >= (level)); auto correct_module = (level <= dblCritical) or (modules_to_debug.empty()) or (modules_to_debug.find(module) != modules_to_debug.end()); return level_reached and correct_module; } void printBacktrace(bool on_off) { this->print_backtrace = on_off; } bool printBacktrace() const { return this->print_backtrace; } void addModuleToDebug(const std::string & id) { - modules_to_debug.insert(id); + this->modules_to_debug.insert(id); } void removeModuleToDebug(const std::string & id) { - auto it = modules_to_debug.find(id); - if (it != modules_to_debug.end()) { - modules_to_debug.erase(it); + auto it = this->modules_to_debug.find(id); + if (it != this->modules_to_debug.end()) { + this->modules_to_debug.erase(it); } } void listModules() { for (const auto & module_ : modules_to_debug) { (*cout) << module_ << std::endl; } } private: std::string parallel_context; std::ostream * cout; bool file_open; DebugLevel level; bool print_backtrace; std::set modules_to_debug; }; extern Debugger debugger; // NOLINT } // namespace debug /* -------------------------------------------------------------------------- */ #define AKANTU_STRINGIZE_(str) #str #define AKANTU_STRINGIZE(str) AKANTU_STRINGIZE_(str) /* -------------------------------------------------------------------------- */ #define AKANTU_DEBUG_MODULE AKANTU_STRINGIZE(AKANTU_MODULE) /* -------------------------------------------------------------------------- */ #define AKANTU_STRINGSTREAM_IN(_str, _sstr) \ ; \ do { \ std::stringstream _dbg_s_info; \ _dbg_s_info << _sstr; /* NOLINT */ \ (_str) = _dbg_s_info.str(); \ } while (false) /* -------------------------------------------------------------------------- */ #define AKANTU_EXCEPTION(info) AKANTU_EXCEPTION_(info, false) #define AKANTU_SILENT_EXCEPTION(info) AKANTU_EXCEPTION_(info, true) #define AKANTU_EXCEPTION_(info, silent) \ do { \ std::stringstream _dbg_str; \ _dbg_str << info; /* NOLINT */ \ std::stringstream _dbg_loc; \ _dbg_loc << AKANTU_LOCATION; \ ::akantu::debug::debugger.throwException(_dbg_str.str(), __FILE__, \ __LINE__, silent, _dbg_loc.str(), \ AKANTU_DEBUG_MODULE); \ } while (false) #define AKANTU_CUSTOM_EXCEPTION_INFO(ex, info) \ do { \ std::stringstream _dbg_str; \ _dbg_str << info; /* NOLINT */ \ ::akantu::debug::debugger.throwCustomException( \ ex, _dbg_str.str(), __FILE__, __LINE__, AKANTU_DEBUG_MODULE); \ } while (false) #define AKANTU_CUSTOM_EXCEPTION(ex) \ do { \ ::akantu::debug::debugger.throwCustomException(ex, __FILE__, __LINE__, \ AKANTU_DEBUG_MODULE); \ } while (false) /* -------------------------------------------------------------------------- */ #ifdef AKANTU_NDEBUG #define AKANTU_DEBUG_TEST(level) (false) #define AKANTU_DEBUG_LEVEL_IS_TEST() \ (::akantu::debug::debugger.testLevel(dblTest, AKANTU_DEBUG_MODULE)) #define AKANTU_DEBUG(level, info) #define AKANTU_DEBUG_(pref, 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_ERROR(info) \ AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::CriticalError(), info) /* -------------------------------------------------------------------------- */ #else #define AKANTU_DEBUG(level, info) AKANTU_DEBUG_(" ", level, info) #define AKANTU_DEBUG_(pref, level, info) \ do { \ std::string _dbg_str; \ AKANTU_STRINGSTREAM_IN(_dbg_str, \ info << " " << AKANTU_LOCATION); /* NOLINT */ \ ::akantu::debug::debugger.printMessage(pref, level, _dbg_str, \ AKANTU_DEBUG_MODULE); \ } while (false) #define AKANTU_DEBUG_TEST(level) \ (::akantu::debug::debugger.testLevel(level, AKANTU_DEBUG_MODULE)) #define AKANTU_DEBUG_LEVEL_IS_TEST() \ (::akantu::debug::debugger.testLevel(dblTest)) #define AKANTU_DEBUG_IN() \ AKANTU_DEBUG_( \ "==>", ::akantu::dblIn, \ __func__ \ << "()") // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay, // bugprone-lambda-function-name) #define AKANTU_DEBUG_OUT() \ AKANTU_DEBUG_( \ "<==", ::akantu::dblOut, \ __func__ \ << "()") // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay, // bugprone-lambda-function-name) #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 (not(test)) \ AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::AssertException(), \ "assert [" << #test << "] " \ << info); /* NOLINT */ \ } while (false) #define AKANTU_ERROR(info) \ do { \ AKANTU_DEBUG_("!!! ", ::akantu::dblError, info); \ AKANTU_CUSTOM_EXCEPTION_INFO(::akantu::debug::CriticalError(), \ info); /* NOLINT */ \ } while (false) #endif // AKANTU_NDEBUG #define AKANTU_TO_IMPLEMENT() \ AKANTU_CUSTOM_EXCEPTION_INFO( \ ::akantu::debug::NotImplementedException(), \ __func__ \ << " : not implemented yet !") // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay, // bugprone-lambda-function-name) /* -------------------------------------------------------------------------- */ namespace debug { /* ------------------------------------------------------------------------ */ template - void - Debugger::throwCustomException(Except ex, const std::string & info, - const std::string & file, unsigned int line, - const std::string & module_) const + void Debugger::throwCustomException(Except ex, const std::string & info, + const std::string & file, + unsigned int line, + const std::string & module_) const noexcept(false) { ex.setInfo(info); ex.setFile(file); ex.setLine(line); ex.setModule(module_); if (::akantu::debug::debugger.printBacktrace()) { ex.setBacktrace(::akantu::debug::getBacktrace()); } throw ex; } /* ------------------------------------------------------------------------ */ template void Debugger::throwCustomException(Except ex, const std::string & file, unsigned int line, const std::string & module_) const noexcept(false) { ex.setFile(file); ex.setLine(line); ex.setModule(module_); if (::akantu::debug::debugger.printBacktrace()) { ex.setBacktrace(::akantu::debug::getBacktrace()); } throw ex; } } // namespace debug } // namespace akantu #endif /* AKANTU_ERROR_HH_ */ diff --git a/src/common/aka_event_handler_manager.hh b/src/common/aka_event_handler_manager.hh index 258f1f94f..33b5f1544 100644 --- a/src/common/aka_event_handler_manager.hh +++ b/src/common/aka_event_handler_manager.hh @@ -1,126 +1,126 @@ /** * @file aka_event_handler_manager.hh * * @author Nicolas Richart * * @date creation: Fri Jun 18 2010 * @date last modification: Sun Dec 03 2017 * * @brief Base of Event Handler classes * * * Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #ifndef AKANTU_AKA_EVENT_HANDLER_MANAGER_HH_ #define AKANTU_AKA_EVENT_HANDLER_MANAGER_HH_ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ namespace akantu { template class EventHandlerManager { private: using priority_value = std::pair; using priority_list = std::list; struct KeyComp { bool operator()(const priority_value & a, const priority_value & b) const { return (a.first < b.first); } bool operator()(const priority_value & a, UInt b) const { return (a.first < b); } }; /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - virtual ~EventHandlerManager() { event_handlers.clear(); } + virtual ~EventHandlerManager() = default; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// register a new EventHandler to the Manager. The register object /// will then be informed about the events the manager observes. void registerEventHandler(EventHandler & event_handler, EventHandlerPriority priority = _ehp_highest) { auto it = this->searchEventHandler(event_handler); if (it != this->event_handlers.end()) { AKANTU_EXCEPTION("This event handler was already registered (priority: " << priority << ")"); } auto pos = std::lower_bound(this->event_handlers.begin(), this->event_handlers.end(), priority, KeyComp()); this->event_handlers.insert(pos, std::make_pair(priority, &event_handler)); } /// unregister a EventHandler object. This object will not be /// notified anymore about the events this manager observes. void unregisterEventHandler(EventHandler & event_handler) { auto it = this->searchEventHandler(event_handler); if (it == this->event_handlers.end()) { AKANTU_EXCEPTION("This event handler is not registered"); } this->event_handlers.erase(it); } /// Notify all the registered EventHandlers about the event that just occured. template void sendEvent(const Event & event) { for (auto & pair : this->event_handlers) { pair.second->sendEvent(event); } } private: typename priority_list::iterator searchEventHandler(EventHandler & handler) { auto it = this->event_handlers.begin(); auto end = this->event_handlers.end(); for (; it != end && it->second != &handler; ++it) { ; } return it; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// list of the event handlers priority_list event_handlers; }; } // namespace akantu #endif /* AKANTU_AKA_EVENT_HANDLER_MANAGER_HH_ */ diff --git a/src/common/aka_grid_dynamic.hh b/src/common/aka_grid_dynamic.hh index 1de09d280..7f4c74c7d 100644 --- a/src/common/aka_grid_dynamic.hh +++ b/src/common/aka_grid_dynamic.hh @@ -1,529 +1,526 @@ /** * @file aka_grid_dynamic.hh * * @author Aurelia Isabel Cuba Ramos * @author Nicolas Richart * * @date creation: Thu Feb 21 2013 * @date last modification: Wed Nov 08 2017 * * @brief Grid that is auto balanced * * * Copyright (©) 2014-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_array.hh" #include "aka_common.hh" #include "aka_types.hh" #include "mesh_accessor.hh" #include /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef AKANTU_AKA_GRID_DYNAMIC_HH_ #define AKANTU_AKA_GRID_DYNAMIC_HH_ namespace akantu { class Mesh; template class SpatialGrid { public: explicit SpatialGrid(UInt dimension) : dimension(dimension), spacing(dimension), center(dimension), lower(dimension), upper(dimension), empty_cell() {} SpatialGrid(UInt dimension, const Vector & spacing, const Vector & center) : dimension(dimension), spacing(spacing), center(center), lower(dimension), upper(dimension), empty_cell() { for (UInt i = 0; i < dimension; ++i) { lower(i) = std::numeric_limits::max(); upper(i) = -std::numeric_limits::max(); } } virtual ~SpatialGrid() = default; class neighbor_cells_iterator; class cells_iterator; class CellID { public: CellID() = default; explicit CellID(UInt dimention) : ids(dimention) {} void setID(UInt dir, Int id) { ids(dir) = id; } Int getID(UInt dir) const { return ids(dir); } bool operator<(const CellID & id) const { return std::lexicographical_compare( ids.storage(), ids.storage() + ids.size(), id.ids.storage(), id.ids.storage() + id.ids.size()); } bool operator==(const CellID & id) const { return std::equal(ids.storage(), ids.storage() + ids.size(), id.ids.storage()); } bool operator!=(const CellID & id) const { return !(operator==(id)); } class neighbor_cells_iterator : private std::iterator { public: neighbor_cells_iterator(const CellID & cell_id, bool end) : cell_id(cell_id), position(cell_id.ids.size(), end ? 1 : -1) { this->updateIt(); if (end) { this->it++; } } neighbor_cells_iterator & operator++() { UInt i = 0; for (; i < position.size() && position(i) == 1; ++i) { ; } if (i == position.size()) { ++it; return *this; } for (UInt j = 0; j < i; ++j) { position(j) = -1; } position(i)++; updateIt(); return *this; } neighbor_cells_iterator operator++(int) { neighbor_cells_iterator tmp(*this); operator++(); return tmp; }; bool operator==(const neighbor_cells_iterator & rhs) const { return cell_id == rhs.cell_id && it == rhs.it; }; bool operator!=(const neighbor_cells_iterator & rhs) const { return !operator==(rhs); }; CellID operator*() const { CellID cur_cell_id(cell_id); cur_cell_id.ids += position; return cur_cell_id; }; private: void updateIt() { it = 0; for (UInt i = 0; i < position.size(); ++i) { it = it * 3 + (position(i) + 1); } } private: /// central cell id const CellID & cell_id; // number representing the current neighbor in base 3; UInt it; // current cell shift Vector position; }; class Neighbors { public: explicit Neighbors(const CellID & cell_id) : cell_id(cell_id) {} decltype(auto) begin() { return neighbor_cells_iterator(cell_id, false); } decltype(auto) end() { return neighbor_cells_iterator(cell_id, true); } private: const CellID & cell_id; }; decltype(auto) neighbors() { return Neighbors(*this); } private: friend class cells_iterator; Vector ids; }; /* ------------------------------------------------------------------------ */ class Cell { public: using iterator = typename std::vector::iterator; using const_iterator = typename std::vector::const_iterator; Cell() : id(), data() {} explicit Cell(const CellID & cell_id) : id(cell_id), data() {} bool operator==(const Cell & cell) const { return id == cell.id; } bool operator!=(const Cell & cell) const { return id != cell.id; } Cell & add(const T & d) { data.push_back(d); return *this; } iterator begin() { return data.begin(); } const_iterator begin() const { return data.begin(); } iterator end() { return data.end(); } const_iterator end() const { return data.end(); } private: CellID id; std::vector data; }; private: using cells_container = std::map; public: const Cell & getCell(const CellID & cell_id) const { auto it = cells.find(cell_id); if (it != cells.end()) { return it->second; } return empty_cell; } decltype(auto) beginCell(const CellID & cell_id) { auto it = cells.find(cell_id); if (it != cells.end()) { return it->second.begin(); } return empty_cell.begin(); } decltype(auto) endCell(const CellID & cell_id) { auto it = cells.find(cell_id); if (it != cells.end()) { return it->second.end(); } return empty_cell.end(); } decltype(auto) beginCell(const CellID & cell_id) const { auto it = cells.find(cell_id); if (it != cells.end()) { return it->second.begin(); } return empty_cell.begin(); } decltype(auto) endCell(const CellID & cell_id) const { auto it = cells.find(cell_id); if (it != cells.end()) { return it->second.end(); } return empty_cell.end(); } /* ------------------------------------------------------------------------ */ class cells_iterator : private std::iterator { public: explicit cells_iterator(typename std::map::const_iterator it) : it(it) {} cells_iterator & operator++() { this->it++; return *this; } - cells_iterator operator++(int) { + cells_iterator operator++(int /*unused*/) { cells_iterator tmp(*this); operator++(); return tmp; }; bool operator==(const cells_iterator & rhs) const { return it == rhs.it; }; bool operator!=(const cells_iterator & rhs) const { return !operator==(rhs); }; CellID operator*() const { CellID cur_cell_id(this->it->first); return cur_cell_id; }; private: /// map iterator typename std::map::const_iterator it; }; public: template Cell & insert(const T & d, const vector_type & position) { auto && cell_id = getCellID(position); auto && it = cells.find(cell_id); if (it == cells.end()) { Cell cell(cell_id); auto & tmp = (cells[cell_id] = cell).add(d); for (UInt i = 0; i < dimension; ++i) { Real posl = center(i) + cell_id.getID(i) * spacing(i); Real posu = posl + spacing(i); if (posl < lower(i)) { lower(i) = posl; } if (posu > upper(i)) { upper(i) = posu; } } return tmp; } return it->second.add(d); } /* ------------------------------------------------------------------------ */ inline decltype(auto) begin() const { auto begin = this->cells.begin(); return cells_iterator(begin); } inline decltype(auto) end() const { auto end = this->cells.end(); return cells_iterator(end); } template CellID getCellID(const vector_type & position) const { CellID cell_id(dimension); for (UInt i = 0; i < dimension; ++i) { cell_id.setID(i, getCellID(position(i), i)); } return cell_id; } void printself(std::ostream & stream, int indent = 0) const { - std::string space; - for (Int i = 0; i < indent; i++, space += AKANTU_INDENT) { - ; - } + std::string space(indent, AKANTU_INDENT); std::streamsize prec = stream.precision(); std::ios_base::fmtflags ff = stream.flags(); stream.setf(std::ios_base::showbase); stream.precision(5); stream << space << "SpatialGrid<" << debug::demangle(typeid(T).name()) << "> [" << std::endl; stream << space << " + dimension : " << this->dimension << std::endl; stream << space << " + lower bounds : {"; for (UInt i = 0; i < lower.size(); ++i) { if (i != 0) { stream << ", "; } stream << lower(i); }; stream << "}" << std::endl; stream << space << " + upper bounds : {"; for (UInt i = 0; i < upper.size(); ++i) { if (i != 0) { stream << ", "; } stream << upper(i); }; stream << "}" << std::endl; stream << space << " + spacing : {"; for (UInt i = 0; i < spacing.size(); ++i) { if (i != 0) { stream << ", "; } stream << spacing(i); }; stream << "}" << std::endl; stream << space << " + center : {"; for (UInt i = 0; i < center.size(); ++i) { if (i != 0) { stream << ", "; } stream << center(i); }; stream << "}" << std::endl; stream << space << " + nb_cells : " << this->cells.size() << "/"; Vector dist(this->dimension); dist = upper; dist -= lower; for (UInt i = 0; i < this->dimension; ++i) { dist(i) /= spacing(i); } UInt nb_cells = std::ceil(dist(0)); for (UInt i = 1; i < this->dimension; ++i) { nb_cells *= std::ceil(dist(i)); } stream << nb_cells << std::endl; stream << space << "]" << std::endl; stream.precision(prec); stream.flags(ff); } void saveAsMesh(Mesh & mesh) const; private: /* -------------------------------------------------------------------------- */ inline UInt getCellID(Real position, UInt direction) const { AKANTU_DEBUG_ASSERT(direction < center.size(), "The direction asked (" << direction << ") is out of range " << center.size()); Real dist_center = position - center(direction); Int id = std::floor(dist_center / spacing(direction)); // if(dist_center < 0) id--; return id; } friend class GridSynchronizer; public: AKANTU_GET_MACRO(LowerBounds, lower, const Vector &); AKANTU_GET_MACRO(UpperBounds, upper, const Vector &); AKANTU_GET_MACRO(Spacing, spacing, const Vector &); protected: UInt dimension; cells_container cells; Vector spacing; Vector center; Vector lower; Vector upper; Cell empty_cell; }; /// standard output stream operator template inline std::ostream & operator<<(std::ostream & stream, const SpatialGrid & _this) { _this.printself(stream); return stream; } } // namespace akantu #include "mesh.hh" namespace akantu { /* -------------------------------------------------------------------------- */ template void SpatialGrid::saveAsMesh(Mesh & mesh) const { ElementType type = _not_defined; switch (dimension) { case 1: type = _segment_2; break; case 2: type = _quadrangle_4; break; case 3: type = _hexahedron_8; break; } MeshAccessor mesh_accessor(mesh); auto & connectivity = mesh_accessor.getConnectivity(type); auto & nodes = mesh_accessor.getNodes(); auto & uint_data = mesh.getDataPointer("tag_1", type); Vector pos(dimension); UInt global_id = 0; for (auto & cell_pair : cells) { UInt cur_node = nodes.size(); UInt cur_elem = connectivity.size(); const CellID & cell_id = cell_pair.first; for (UInt i = 0; i < dimension; ++i) { pos(i) = center(i) + cell_id.getID(i) * spacing(i); } nodes.push_back(pos); for (UInt i = 0; i < dimension; ++i) { pos(i) += spacing(i); } nodes.push_back(pos); connectivity.push_back(cur_node); switch (dimension) { case 1: connectivity(cur_elem, 1) = cur_node + 1; break; case 2: pos(0) -= spacing(0); nodes.push_back(pos); pos(0) += spacing(0); pos(1) -= spacing(1); nodes.push_back(pos); connectivity(cur_elem, 1) = cur_node + 3; connectivity(cur_elem, 2) = cur_node + 1; connectivity(cur_elem, 3) = cur_node + 2; break; case 3: pos(1) -= spacing(1); pos(2) -= spacing(2); nodes.push_back(pos); pos(1) += spacing(1); nodes.push_back(pos); pos(0) -= spacing(0); nodes.push_back(pos); pos(1) -= spacing(1); pos(2) += spacing(2); nodes.push_back(pos); pos(0) += spacing(0); nodes.push_back(pos); pos(0) -= spacing(0); pos(1) += spacing(1); nodes.push_back(pos); connectivity(cur_elem, 1) = cur_node + 2; connectivity(cur_elem, 2) = cur_node + 3; connectivity(cur_elem, 3) = cur_node + 4; connectivity(cur_elem, 4) = cur_node + 5; connectivity(cur_elem, 5) = cur_node + 6; connectivity(cur_elem, 6) = cur_node + 1; connectivity(cur_elem, 7) = cur_node + 7; break; } uint_data.push_back(global_id); ++global_id; } } } // namespace akantu #endif /* AKANTU_AKA_GRID_DYNAMIC_HH_ */ diff --git a/src/common/aka_math.hh b/src/common/aka_math.hh index 7180ad15a..4fc404a9b 100644 --- a/src/common/aka_math.hh +++ b/src/common/aka_math.hh @@ -1,283 +1,283 @@ /** * @file aka_math.hh * * @author Ramin Aghababaei * @author Guillaume Anciaux * @author Marion Estelle Chambart * @author David Simon Kammer * @author Daniel Pino Muñoz * @author Nicolas Richart * @author Leonardo Snozzi * @author Peter Spijker * @author Marco Vocialta * * @date creation: Wed Aug 04 2010 * @date last modification: Mon Sep 11 2017 * * @brief mathematical operations * * * Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #ifndef AKANTU_AKA_MATH_H_ #define AKANTU_AKA_MATH_H_ namespace akantu { /* -------------------------------------------------------------------------- */ namespace Math { /// tolerance for functions that need one extern Real tolerance; // NOLINT /* ------------------------------------------------------------------------ */ /* Matrix algebra */ /* ------------------------------------------------------------------------ */ /// @f$ y = A*x @f$ void matrix_vector(UInt m, UInt n, const Array & A, const Array & x, Array & y, Real alpha = 1.); /// @f$ y = A*x @f$ inline void matrix_vector(UInt m, UInt n, Real * A, Real * x, Real * y, Real alpha = 1.); /// @f$ y = A^t*x @f$ inline void matrixt_vector(UInt m, UInt n, Real * A, Real * x, Real * y, Real alpha = 1.); /// @f$ C = A*B @f$ void matrix_matrix(UInt m, UInt n, UInt k, const Array & A, const Array & B, Array & C, Real alpha = 1.); /// @f$ C = A*B^t @f$ void matrix_matrixt(UInt m, UInt n, UInt k, const Array & A, const Array & B, Array & C, Real alpha = 1.); /// @f$ C = A*B @f$ inline void matrix_matrix(UInt m, UInt n, UInt k, Real * A, Real * B, Real * C, Real alpha = 1.); /// @f$ C = A^t*B @f$ inline void matrixt_matrix(UInt m, UInt n, UInt k, Real * A, Real * B, Real * C, Real alpha = 1.); /// @f$ C = A*B^t @f$ inline void matrix_matrixt(UInt m, UInt n, UInt k, Real * A, Real * B, Real * C, Real alpha = 1.); /// @f$ C = A^t*B^t @f$ inline void matrixt_matrixt(UInt m, UInt n, UInt k, Real * A, Real * B, Real * C, Real alpha = 1.); template inline void matMul(UInt m, UInt n, UInt k, Real alpha, Real * A, Real * B, Real beta, Real * C); template inline void matVectMul(UInt m, UInt n, Real alpha, Real * A, Real * x, Real beta, Real * y); inline void aXplusY(UInt n, Real alpha, Real * x, Real * y); inline void matrix33_eigenvalues(Real * A, Real * Adiag); inline void matrix22_eigenvalues(Real * A, Real * Adiag); template inline void eigenvalues(Real * A, Real * d); /// solve @f$ A x = \Lambda x @f$ and return d and V such as @f$ A V[i:] = /// d[i] V[i:]@f$ template void matrixEig(UInt n, T * A, T * d, T * V = nullptr); /// determinent of a 2x2 matrix Real det2(const Real * mat); /// determinent of a 3x3 matrix Real det3(const Real * mat); /// determinent of a nxn matrix template Real det(const Real * mat); /// determinent of a nxn matrix template T det(UInt n, const T * A); /// inverse a nxn matrix template inline void inv(const Real * A, Real * inv); /// inverse a nxn matrix template inline void inv(UInt n, const T * A, T * inv); /// inverse a 3x3 matrix inline void inv3(const Real * mat, Real * inv); /// inverse a 2x2 matrix inline void inv2(const Real * mat, Real * inv); /// solve A x = b using a LU factorization template inline void solve(UInt n, const T * A, T * x, const T * b); /// return the double dot product between 2 tensors in 2d inline Real matrixDoubleDot22(Real * A, Real * B); /// return the double dot product between 2 tensors in 3d inline Real matrixDoubleDot33(Real * A, Real * B); /// extension of the double dot product to two 2nd order tensor in dimension n inline Real matrixDoubleDot(UInt n, Real * A, Real * B); /* ------------------------------------------------------------------------ */ /* Array algebra */ /* ------------------------------------------------------------------------ */ /// vector cross product inline void vectorProduct3(const Real * v1, const Real * v2, Real * res); /// normalize a vector inline void normalize2(Real * v); /// normalize a vector inline void normalize3(Real * v); /// return norm of a 2-vector inline Real norm2(const Real * v); /// return norm of a 3-vector inline Real norm3(const Real * v); /// return norm of a vector inline Real norm(UInt n, const Real * v); /// return the dot product between 2 vectors in 2d inline Real vectorDot2(const Real * v1, const Real * v2); /// return the dot product between 2 vectors in 3d inline Real vectorDot3(const Real * v1, const Real * v2); /// return the dot product between 2 vectors inline Real vectorDot(Real * v1, Real * v2, UInt n); /* ------------------------------------------------------------------------ */ /* Geometry */ /* ------------------------------------------------------------------------ */ /// compute normal a normal to a vector inline void normal2(const Real * vec, Real * normal); /// compute normal a normal to a vector inline void normal3(const Real * vec1, const Real * vec2, Real * normal); /// compute the tangents to an array of normal vectors void compute_tangents(const Array & normals, Array & tangents); /// distance in 2D between x and y inline Real distance_2d(const Real * x, const Real * y); /// distance in 3D between x and y inline Real distance_3d(const Real * x, const Real * y); /// radius of the in-circle of a triangle inline Real triangle_inradius(const Real * coord1, const Real * coord2, const Real * coord3); /// radius of the in-circle of a tetrahedron inline Real tetrahedron_inradius(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4); /// volume of a tetrahedron inline Real tetrahedron_volume(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4); /// compute the barycenter of n points inline void barycenter(const Real * coord, UInt nb_points, UInt spatial_dimension, Real * barycenter); /// vector between x and y inline void vector_2d(const Real * x, const Real * y, Real * res); /// vector pointing from x to y in 3 spatial dimension inline void vector_3d(const Real * x, const Real * y, Real * res); /// test if two scalar are equal within a given tolerance inline bool are_float_equal(Real x, Real y); /// test if two vectors are equal within a given tolerance inline bool are_vector_equal(UInt n, Real * x, Real * y); #ifdef isnan #error \ "You probably included which is incompatible with aka_math please use\ or add a \"#undef isnan\" before akantu includes" #endif /// test if a real is a NaN inline bool isnan(Real x); /// test if the line x and y intersects each other inline bool intersects(Real x_min, Real x_max, Real y_min, Real y_max); /// test if a is in the range [x_min, x_max] inline bool is_in_range(Real a, Real x_min, Real x_max); inline Real getTolerance() { return Math::tolerance; } inline void setTolerance(Real tol) { Math::tolerance = tol; } template inline T pow(T x); template ::value and std::is_integral::value> * = nullptr> inline Real kronecker(T1 i, T2 j) { return static_cast(i == j); } /// reduce all the values of an array, the summation is done in place and the /// array is modified Real reduce(Array & array); class NewtonRaphson { public: NewtonRaphson(Real tolerance, Real max_iteration) : tolerance(tolerance), max_iteration(max_iteration) {} template Real solve(const Functor & funct, Real x_0); private: Real tolerance; Real max_iteration; }; struct NewtonRaphsonFunctor { - explicit NewtonRaphsonFunctor(std::string name) : name(std::move(name)) {} + explicit NewtonRaphsonFunctor(const std::string & name) : name(name) {} virtual ~NewtonRaphsonFunctor() = default; NewtonRaphsonFunctor(const NewtonRaphsonFunctor & other) = default; NewtonRaphsonFunctor(NewtonRaphsonFunctor && other) noexcept = default; NewtonRaphsonFunctor & operator=(const NewtonRaphsonFunctor & other) = default; NewtonRaphsonFunctor & operator=(NewtonRaphsonFunctor && other) noexcept = default; virtual Real f(Real x) const = 0; virtual Real f_prime(Real x) const = 0; std::string name; }; } // namespace Math } // namespace akantu /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "aka_math_tmpl.hh" #endif /* AKANTU_AKA_MATH_H_ */ diff --git a/src/fe_engine/shape_functions.cc b/src/fe_engine/shape_functions.cc index a35173c9a..143555306 100644 --- a/src/fe_engine/shape_functions.cc +++ b/src/fe_engine/shape_functions.cc @@ -1,241 +1,241 @@ /** * @file shape_functions.cc * * @author Nicolas Richart * * @date creation: Wed Aug 09 2017 * @date last modification: Wed Oct 11 2017 * * @brief implementation of th shape functions interface * * * Copyright (©) 2016-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "shape_functions.hh" /* -------------------------------------------------------------------------- */ namespace akantu { /* -------------------------------------------------------------------------- */ ShapeFunctions::ShapeFunctions(const Mesh & mesh, UInt spatial_dimension, const ID & id, const MemoryID & memory_id) : Memory(id, memory_id), shapes("shapes_generic", id, memory_id), shapes_derivatives("shapes_derivatives_generic", id, memory_id), mesh(mesh), _spatial_dimension(spatial_dimension) {} /* -------------------------------------------------------------------------- */ template inline void ShapeFunctions::initElementalFieldInterpolationFromIntegrationPoints( const Array & interpolation_points_coordinates, ElementTypeMapArray & interpolation_points_coordinates_matrices, ElementTypeMapArray & quad_points_coordinates_inv_matrices, const Array & quadrature_points_coordinates, GhostType ghost_type, const Array & element_filter) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = this->mesh.getSpatialDimension(); UInt nb_element = this->mesh.getNbElement(type, ghost_type); UInt nb_element_filter; if (element_filter == empty_filter) { nb_element_filter = nb_element; } else { nb_element_filter = element_filter.size(); } - UInt nb_quad_per_element = + auto nb_quad_per_element = GaussIntegrationElement::getNbQuadraturePoints(); - UInt nb_interpolation_points_per_elem = + auto nb_interpolation_points_per_elem = interpolation_points_coordinates.size() / nb_element; AKANTU_DEBUG_ASSERT(interpolation_points_coordinates.size() % nb_element == 0, "Number of interpolation points should be a multiple of " "total number of elements"); - if (!quad_points_coordinates_inv_matrices.exists(type, ghost_type)) { + if (not quad_points_coordinates_inv_matrices.exists(type, ghost_type)) { quad_points_coordinates_inv_matrices.alloc( nb_element_filter, nb_quad_per_element * nb_quad_per_element, type, ghost_type); } else { quad_points_coordinates_inv_matrices(type, ghost_type) .resize(nb_element_filter); } if (!interpolation_points_coordinates_matrices.exists(type, ghost_type)) { interpolation_points_coordinates_matrices.alloc( nb_element_filter, nb_interpolation_points_per_elem * nb_quad_per_element, type, ghost_type); } else { interpolation_points_coordinates_matrices(type, ghost_type) .resize(nb_element_filter); } Array & quad_inv_mat = quad_points_coordinates_inv_matrices(type, ghost_type); Array & interp_points_mat = interpolation_points_coordinates_matrices(type, ghost_type); Matrix quad_coord_matrix(nb_quad_per_element, nb_quad_per_element); Array::const_matrix_iterator quad_coords_it = quadrature_points_coordinates.begin_reinterpret( spatial_dimension, nb_quad_per_element, nb_element_filter); Array::const_matrix_iterator points_coords_begin = interpolation_points_coordinates.begin_reinterpret( spatial_dimension, nb_interpolation_points_per_elem, nb_element); Array::matrix_iterator inv_quad_coord_it = quad_inv_mat.begin(nb_quad_per_element, nb_quad_per_element); Array::matrix_iterator int_points_mat_it = interp_points_mat.begin( nb_interpolation_points_per_elem, nb_quad_per_element); /// loop over the elements of the current material and element type for (UInt el = 0; el < nb_element_filter; ++el, ++inv_quad_coord_it, ++int_points_mat_it, ++quad_coords_it) { /// matrix containing the quadrature points coordinates const Matrix & quad_coords = *quad_coords_it; /// matrix to store the matrix inversion result Matrix & inv_quad_coord_matrix = *inv_quad_coord_it; /// insert the quad coordinates in a matrix compatible with the /// interpolation buildElementalFieldInterpolationMatrix(quad_coords, quad_coord_matrix); /// invert the interpolation matrix inv_quad_coord_matrix.inverse(quad_coord_matrix); /// matrix containing the interpolation points coordinates const Matrix & points_coords = points_coords_begin[element_filter(el)]; /// matrix to store the interpolation points coordinates /// compatible with these functions Matrix & inv_points_coord_matrix = *int_points_mat_it; /// insert the quad coordinates in a matrix compatible with the /// interpolation buildElementalFieldInterpolationMatrix(points_coords, inv_points_coord_matrix); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ShapeFunctions::initElementalFieldInterpolationFromIntegrationPoints( const ElementTypeMapArray & interpolation_points_coordinates, ElementTypeMapArray & interpolation_points_coordinates_matrices, ElementTypeMapArray & quad_points_coordinates_inv_matrices, const ElementTypeMapArray & quadrature_points_coordinates, const ElementTypeMapArray * element_filter) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = this->mesh.getSpatialDimension(); for (auto ghost_type : ghost_types) { auto types_iterable = mesh.elementTypes(spatial_dimension, ghost_type); if (element_filter != nullptr) { types_iterable = element_filter->elementTypes(spatial_dimension, ghost_type); } for (auto type : types_iterable) { UInt nb_element = mesh.getNbElement(type, ghost_type); if (nb_element == 0) { continue; } const Array * elem_filter; if (element_filter != nullptr) { elem_filter = &((*element_filter)(type, ghost_type)); } else { elem_filter = &(empty_filter); } #define AKANTU_INIT_ELEMENTAL_FIELD_INTERPOLATION_FROM_C_POINTS(type) \ this->initElementalFieldInterpolationFromIntegrationPoints( \ interpolation_points_coordinates(type, ghost_type), \ interpolation_points_coordinates_matrices, \ quad_points_coordinates_inv_matrices, \ quadrature_points_coordinates(type, ghost_type), ghost_type, \ *elem_filter) AKANTU_BOOST_REGULAR_ELEMENT_SWITCH( AKANTU_INIT_ELEMENTAL_FIELD_INTERPOLATION_FROM_C_POINTS); #undef AKANTU_INIT_ELEMENTAL_FIELD_INTERPOLATION_FROM_C_POINTS } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ShapeFunctions::interpolateElementalFieldFromIntegrationPoints( const ElementTypeMapArray & field, const ElementTypeMapArray & interpolation_points_coordinates_matrices, const ElementTypeMapArray & quad_points_coordinates_inv_matrices, ElementTypeMapArray & result, GhostType ghost_type, const ElementTypeMapArray * element_filter) const { AKANTU_DEBUG_IN(); UInt spatial_dimension = this->mesh.getSpatialDimension(); auto types_iterable = mesh.elementTypes(spatial_dimension, ghost_type); if (element_filter != nullptr) { types_iterable = element_filter->elementTypes(spatial_dimension, ghost_type); } for (auto type : types_iterable) { UInt nb_element = mesh.getNbElement(type, ghost_type); if (nb_element == 0) { continue; } const Array * elem_filter; if (element_filter != nullptr) { elem_filter = &((*element_filter)(type, ghost_type)); } else { elem_filter = &(empty_filter); } #define AKANTU_INTERPOLATE_ELEMENTAL_FIELD_FROM_C_POINTS(type) \ interpolateElementalFieldFromIntegrationPoints( \ field(type, ghost_type), \ interpolation_points_coordinates_matrices(type, ghost_type), \ quad_points_coordinates_inv_matrices(type, ghost_type), result, \ ghost_type, *elem_filter) AKANTU_BOOST_REGULAR_ELEMENT_SWITCH( AKANTU_INTERPOLATE_ELEMENTAL_FIELD_FROM_C_POINTS); #undef AKANTU_INTERPOLATE_ELEMENTAL_FIELD_FROM_C_POINTS } AKANTU_DEBUG_OUT(); } } // namespace akantu diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/Dockerfile b/test/ci/codeclimate/codeclimate-clang-tidy/Dockerfile new file mode 100644 index 000000000..90200e79c --- /dev/null +++ b/test/ci/codeclimate/codeclimate-clang-tidy/Dockerfile @@ -0,0 +1,25 @@ +FROM alpine:edge +LABEL maintainer "Nicolas Richart " + +WORKDIR /usr/src/app + +RUN apk --update add --no-cache --upgrade \ + clang\ + clang-extra-tools \ + g++ \ + musl-dev \ + boost-dev \ + python3 \ + py3-termcolor && \ + rm -rf /usr/share/ri && \ + adduser -u 9000 -D -s /bin/false app + +#COPY engine.json / +COPY . ./ +RUN chown -R app:app ./ +USER app + +VOLUME /code +WORKDIR /code + +CMD ["/usr/src/app/bin/codeclimate-clang-tidy"] diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/bin/codeclimate-clang-tidy b/test/ci/codeclimate/codeclimate-clang-tidy/bin/codeclimate-clang-tidy new file mode 100755 index 000000000..598027114 --- /dev/null +++ b/test/ci/codeclimate/codeclimate-clang-tidy/bin/codeclimate-clang-tidy @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import os +import sys + +lib_path = os.path.abspath(os.path.join(__file__, '..', '..', 'lib')) +sys.path.append(lib_path) + +from runner import Runner # noqa + +if __name__ == '__main__': + print(f"Arguments: {sys.argv}", file=sys.stderr) + Runner().run() diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/bin/run-clang-tidy b/test/ci/codeclimate/codeclimate-clang-tidy/bin/run-clang-tidy new file mode 100755 index 000000000..0dbac0b25 --- /dev/null +++ b/test/ci/codeclimate/codeclimate-clang-tidy/bin/run-clang-tidy @@ -0,0 +1,337 @@ +#!/usr/bin/env python3 +# +#===- run-clang-tidy.py - Parallel clang-tidy runner --------*- python -*--===# +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +#===-----------------------------------------------------------------------===# +# FIXME: Integrate with clang-tidy-diff.py + + +""" +Parallel clang-tidy runner +========================== + +Runs clang-tidy over all files in a compilation database. Requires clang-tidy +and clang-apply-replacements in $PATH. + +Example invocations. +- Run clang-tidy on all files in the current working directory with a default + set of checks and show warnings in the cpp files and all project headers. + run-clang-tidy.py $PWD + +- Fix all header guards. + run-clang-tidy.py -fix -checks=-*,llvm-header-guard + +- Fix all header guards included from clang-tidy and header guards + for clang-tidy headers. + run-clang-tidy.py -fix -checks=-*,llvm-header-guard extra/clang-tidy \ + -header-filter=extra/clang-tidy + +Compilation database setup: +http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html +""" + +from __future__ import print_function + +import argparse +import glob +import json +import multiprocessing +import os +import re +import shutil +import subprocess +import sys +import tempfile +import threading +import traceback + +try: + import yaml +except ImportError: + yaml = None + +is_py2 = sys.version[0] == '2' + +if is_py2: + import Queue as queue +else: + import queue as queue + + +def find_compilation_database(path): + """Adjusts the directory until a compilation database is found.""" + result = './' + while not os.path.isfile(os.path.join(result, path)): + if os.path.realpath(result) == '/': + print('Error: could not find compilation database.') + sys.exit(1) + result += '../' + return os.path.realpath(result) + + +def make_absolute(f, directory): + if os.path.isabs(f): + return f + return os.path.normpath(os.path.join(directory, f)) + + +def get_tidy_invocation(f, clang_tidy_binary, checks, tmpdir, build_path, + header_filter, allow_enabling_alpha_checkers, + extra_arg, extra_arg_before, quiet, config): + """Gets a command line for clang-tidy.""" + start = [clang_tidy_binary] + if allow_enabling_alpha_checkers: + start.append('-allow-enabling-analyzer-alpha-checkers') + if header_filter is not None: + start.append('-header-filter=' + header_filter) + if checks: + start.append('-checks=' + checks) + if tmpdir is not None: + start.append('-export-fixes') + # Get a temporary file. We immediately close the handle so clang-tidy can + # overwrite it. + (handle, name) = tempfile.mkstemp(suffix='.yaml', dir=tmpdir) + os.close(handle) + start.append(name) + for arg in extra_arg: + start.append('-extra-arg=%s' % arg) + for arg in extra_arg_before: + start.append('-extra-arg-before=%s' % arg) + start.append('-p=' + build_path) + if quiet: + start.append('-quiet') + if config: + start.append('-config=' + config) + start.append(f) + return start + + +def merge_replacement_files(tmpdir, mergefile): + """Merge all replacement files in a directory into a single file""" + # The fixes suggested by clang-tidy >= 4.0.0 are given under + # the top level key 'Diagnostics' in the output yaml files + mergekey = "Diagnostics" + merged=[] + for replacefile in glob.iglob(os.path.join(tmpdir, '*.yaml')): + content = yaml.safe_load(open(replacefile, 'r')) + if not content: + continue # Skip empty files. + merged.extend(content.get(mergekey, [])) + + if merged: + # MainSourceFile: The key is required by the definition inside + # include/clang/Tooling/ReplacementsYaml.h, but the value + # is actually never used inside clang-apply-replacements, + # so we set it to '' here. + output = {'MainSourceFile': '', mergekey: merged} + with open(mergefile, 'w') as out: + yaml.safe_dump(output, out) + else: + # Empty the file: + open(mergefile, 'w').close() + + +def check_clang_apply_replacements_binary(args): + """Checks if invoking supplied clang-apply-replacements binary works.""" + try: + subprocess.check_call([args.clang_apply_replacements_binary, '--version']) + except: + print('Unable to run clang-apply-replacements. Is clang-apply-replacements ' + 'binary correctly specified?', file=sys.stderr) + traceback.print_exc() + sys.exit(1) + + +def apply_fixes(args, tmpdir): + """Calls clang-apply-fixes on a given directory.""" + invocation = [args.clang_apply_replacements_binary] + if args.format: + invocation.append('-format') + if args.style: + invocation.append('-style=' + args.style) + invocation.append(tmpdir) + subprocess.call(invocation) + + +def run_tidy(args, tmpdir, build_path, queue, lock, failed_files): + """Takes filenames out of queue and runs clang-tidy on them.""" + while True: + name = queue.get() + invocation = get_tidy_invocation(name, args.clang_tidy_binary, args.checks, + tmpdir, build_path, args.header_filter, + args.allow_enabling_alpha_checkers, + args.extra_arg, args.extra_arg_before, + args.quiet, args.config) + + proc = subprocess.Popen(invocation, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output, err = proc.communicate() + if proc.returncode != 0: + failed_files.append(name) + with lock: + sys.stdout.write(' '.join(invocation) + '\n' + output.decode('utf-8')) + if len(err) > 0: + sys.stdout.flush() + sys.stderr.write(err.decode('utf-8')) + queue.task_done() + + +def main(): + parser = argparse.ArgumentParser(description='Runs clang-tidy over all files ' + 'in a compilation database. Requires ' + 'clang-tidy and clang-apply-replacements in ' + '$PATH.') + parser.add_argument('-allow-enabling-alpha-checkers', + action='store_true', help='allow alpha checkers from ' + 'clang-analyzer.') + parser.add_argument('-clang-tidy-binary', metavar='PATH', + default='clang-tidy-11', + help='path to clang-tidy binary') + parser.add_argument('-clang-apply-replacements-binary', metavar='PATH', + default='clang-apply-replacements-11', + help='path to clang-apply-replacements binary') + parser.add_argument('-checks', default=None, + help='checks filter, when not specified, use clang-tidy ' + 'default') + parser.add_argument('-config', default=None, + help='Specifies a configuration in YAML/JSON format: ' + ' -config="{Checks: \'*\', ' + ' CheckOptions: [{key: x, ' + ' value: y}]}" ' + 'When the value is empty, clang-tidy will ' + 'attempt to find a file named .clang-tidy for ' + 'each source file in its parent directories.') + parser.add_argument('-header-filter', default=None, + help='regular expression matching the names of the ' + 'headers to output diagnostics from. Diagnostics from ' + 'the main file of each translation unit are always ' + 'displayed.') + if yaml: + parser.add_argument('-export-fixes', metavar='filename', dest='export_fixes', + help='Create a yaml file to store suggested fixes in, ' + 'which can be applied with clang-apply-replacements.') + parser.add_argument('-j', type=int, default=0, + help='number of tidy instances to be run in parallel.') + parser.add_argument('files', nargs='*', default=['.*'], + help='files to be processed (regex on path)') + parser.add_argument('-fix', action='store_true', help='apply fix-its') + parser.add_argument('-format', action='store_true', help='Reformat code ' + 'after applying fixes') + parser.add_argument('-style', default='file', help='The style of reformat ' + 'code after applying fixes') + parser.add_argument('-p', dest='build_path', + help='Path used to read a compile command database.') + parser.add_argument('-extra-arg', dest='extra_arg', + action='append', default=[], + help='Additional argument to append to the compiler ' + 'command line.') + parser.add_argument('-extra-arg-before', dest='extra_arg_before', + action='append', default=[], + help='Additional argument to prepend to the compiler ' + 'command line.') + parser.add_argument('-quiet', action='store_true', + help='Run clang-tidy in quiet mode') + args = parser.parse_args() + + db_path = 'compile_commands.json' + + if args.build_path is not None: + build_path = args.build_path + else: + # Find our database + build_path = find_compilation_database(db_path) + + try: + invocation = [args.clang_tidy_binary, '-list-checks'] + if args.allow_enabling_alpha_checkers: + invocation.append('-allow-enabling-analyzer-alpha-checkers') + invocation.append('-p=' + build_path) + if args.checks: + invocation.append('-checks=' + args.checks) + invocation.append('-') + if args.quiet: + # Even with -quiet we still want to check if we can call clang-tidy. + with open(os.devnull, 'w') as dev_null: + subprocess.check_call(invocation, stdout=dev_null) + else: + subprocess.check_call(invocation) + except: + print("Unable to run clang-tidy.", file=sys.stderr) + sys.exit(1) + + # Load the database and extract all files. + database = json.load(open(os.path.join(build_path, db_path))) + files = [make_absolute(entry['file'], entry['directory']) + for entry in database] + + max_task = args.j + if max_task == 0: + max_task = multiprocessing.cpu_count() + + tmpdir = None + if args.fix or (yaml and args.export_fixes): + check_clang_apply_replacements_binary(args) + tmpdir = tempfile.mkdtemp() + + # Build up a big regexy filter from all command line arguments. + file_name_re = re.compile('|'.join(args.files)) + + return_code = 0 + try: + # Spin up a bunch of tidy-launching threads. + task_queue = queue.Queue(max_task) + # List of files with a non-zero return code. + failed_files = [] + lock = threading.Lock() + for _ in range(max_task): + t = threading.Thread(target=run_tidy, + args=(args, tmpdir, build_path, task_queue, lock, failed_files)) + t.daemon = True + t.start() + + # Fill the queue with files. + for name in files: + if file_name_re.search(name): + task_queue.put(name) + + # Wait for all threads to be done. + task_queue.join() + if len(failed_files): + return_code = 1 + + except KeyboardInterrupt: + # This is a sad hack. Unfortunately subprocess goes + # bonkers with ctrl-c and we start forking merrily. + print('\nCtrl-C detected, goodbye.') + if tmpdir: + shutil.rmtree(tmpdir) + os.kill(0, 9) + + if yaml and args.export_fixes: + print('Writing fixes to ' + args.export_fixes + ' ...') + try: + merge_replacement_files(tmpdir, args.export_fixes) + except: + print('Error exporting fixes.\n', file=sys.stderr) + traceback.print_exc() + return_code=1 + + if args.fix: + print('Applying fixes ...') + try: + apply_fixes(args, tmpdir) + except: + print('Error applying fixes.\n', file=sys.stderr) + traceback.print_exc() + return_code = 1 + + if tmpdir: + shutil.rmtree(tmpdir) + sys.exit(return_code) + + +if __name__ == '__main__': + main() diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/engine.json b/test/ci/codeclimate/codeclimate-clang-tidy/engine.json new file mode 100644 index 000000000..0e520cc6f --- /dev/null +++ b/test/ci/codeclimate/codeclimate-clang-tidy/engine.json @@ -0,0 +1,11 @@ +{ + "name": "codeclimate-clang-tidy", + "description": "clang-tidy is a static analysis tool for C/C++ code.", + "maintainer": { + "name": "Nicolas Richart", + "email": "nicolas.richart@epfl.ch" + }, + "languages" : ["C", "C++"], + "version": "0.0.1", + "spec_version": "0.2.0" +} diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/lib/command.py b/test/ci/codeclimate/codeclimate-clang-tidy/lib/command.py new file mode 100644 index 000000000..ad8c6de0e --- /dev/null +++ b/test/ci/codeclimate/codeclimate-clang-tidy/lib/command.py @@ -0,0 +1,74 @@ +import json +import os +import re + + +class Command: + """Returns command line arguments by parsing codeclimate config file.""" + def __init__(self, config, workspace): + self.config = config + self._workspace = workspace + + def build(self): + command = ['/usr/src/app/bin/run-clang-tidy', + '-clang-tidy-binary', + '/usr/bin/clang-tidy'] + + if 'checks' in self.config: + checks = self.config["checks"] + if not isinstance(checks, list): + command.extend(['-checks', f'\'{checks}\'']) + else: + command.extend(['-checks', f'\'{",".join(checks)}\'']) + + if 'config' in self.config: + command.extend(['-config', self.config["config"]]) + + if 'header-filter' in self.config: + command.extend(['-header-filter', self.config["header-file"]]) + + extra_args = [] + if 'extra-arg' in self.config: + tmp_extra_args = self.config['extra-arg'] + if not isinstance(extra_args, list): + tmp_extra_args = [extra_args] + + extra_args = [] + includes_re = re.compile(r'-I(.*)') + for arg in tmp_extra_args: + match = includes_re.match(arg) + if match: + path = os.path.abspath(match.group(1)) + extra_args.append(f'-I{path}') + else: + extra_args.append(arg) + + if 'compilation-database-path' in self.config: + for arg in extra_args: + command.extend(['-extra-arg', arg]) + + if 'compilation-database-path' in self.config: + command.extend(['-p', self.config['compilation-database-path']]) + else: + include_flags = ' -I'.join(self._workspace.include_paths) + + compile_commands = [] + for file_ in self._workspace.files: + cmd = { + 'directory': os.path.dirname(file_), + 'file': file_, + 'command': f'/usr/bin/clang++ {include_flags} {" ".join(extra_args)} -c {file_} -o dummy.o', # noqa + } + compile_commands.append(cmd) + + location = '/tmp' + compile_database = os.path.join(location, 'compile_commands.json') + with open(compile_database, 'w') as db: + json.dump(compile_commands, db) + + command.extend(['-p', location]) + + command.extend([f'{path}.*' if os.path.isdir(path) else path + for path in self._workspace.paths]) + + return command diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/lib/issue_formatter.py b/test/ci/codeclimate/codeclimate-clang-tidy/lib/issue_formatter.py new file mode 100644 index 000000000..4b0ec3308 --- /dev/null +++ b/test/ci/codeclimate/codeclimate-clang-tidy/lib/issue_formatter.py @@ -0,0 +1,92 @@ +import hashlib +import os + + +class IssueFormatter: + CLASSIFICATIONS = { + 'bugprone': { + 'categories': ['Bug Risk'], + 'severity': 'major', + }, + 'modernize': { + 'categories': ['Clarity', 'Compatibility', 'Style'], + 'severity': 'info' + }, + 'mpi': { + 'categories': ['Bug Risk', 'Performance'], + 'severity': 'critical', + }, + 'openmp': { + 'categories': ['Bug Risk', 'Performance'], + 'severity': 'critical', + }, + 'performance': { + 'categories': ['Performance'], + 'severity': 'minor', + }, + 'readability': { + 'categories': ['Clarity', 'Style'], + 'severity': 'info' + }, + } + + def _get_classifiaction(self, type_): + categories = ['Bug Risk'] + severity = 'blocker' + + if type_ in self.CLASSIFICATIONS: + categories = self.CLASSIFICATIONS[type_]['categories'] + severity = self.CLASSIFICATIONS[type_]['severity'] + elif type_[0] == 'clang': + if type_[1] == 'diagnostic': + categories = ['Bug Risk'] + severity = 'blocker' + elif type_[1] == 'analyzer': + categories = ['Bug Risk'] + severity = 'major' + + return (categories, severity) + + def __init__(self, issue): + self.issue_dict = issue + + def format(self): + self.issue_dict['file'] = os.path.relpath(self.issue_dict['file']) + issue = { + 'type': 'issue', + 'check_name': self.issue_dict['type'], + 'description': self.issue_dict['detail'], + 'location': { + "path": self.issue_dict['file'], + "lines": { + "begin": int(self.issue_dict['line']), + "end": int(self.issue_dict['line']), + }, + "positions": { + "begin": { + "line": int(self.issue_dict['line']), + "column": int(self.issue_dict['column']), + }, + "end": { + "line": int(self.issue_dict['line']), + "column": int(self.issue_dict['column']), + }, + }, + }, + } + + if 'content' in self.issue_dict: + issue['content'] = { + 'body': '```\n' + + '\n'.join(self.issue_dict['content']) + + '\n```' + } + + issue['fingerprint'] = hashlib.md5( + '{file}:{line}:{column}:{type}'.format(**self.issue_dict).encode() + ).hexdigest() + + type_ = self.issue_dict['type'].split('-')[0] + issue['categories'], issue['severity'] = self._get_classifiaction(type_) + + return issue diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/lib/runner.py b/test/ci/codeclimate/codeclimate-clang-tidy/lib/runner.py new file mode 100644 index 000000000..eed340983 --- /dev/null +++ b/test/ci/codeclimate/codeclimate-clang-tidy/lib/runner.py @@ -0,0 +1,102 @@ +import json +import subprocess +import sys +import re +import os +try: + from termcolor import colored +except ImportError: + def colored(text, color): + return text + +from command import Command +from issue_formatter import IssueFormatter +from workspace import Workspace + + +class Runner: + CONFIG_FILE_PATH = '/config.json' + + """Runs clang-tidy, collects and reports results.""" + def __init__(self): + self._config_file_path = self.CONFIG_FILE_PATH + self._config = {} + self._decode_config() + self._ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])') + self._issue_parse = re.compile(r'(?P.*\.(cc|hh)):(?P[0-9]+):(?P[0-9]+): (warning|error): (?P.*) \[(?P.*)\]') # noqa + + self._issues_fpr = [] + + self._workspace = Workspace(self._config.get('include_paths', [])) + self._files = self._workspace.files + self._include_paths = self._workspace.include_paths + + def run(self): + if not len(self._files) > 0: + return + + self._print_debug(f'[clang-tidy] analyzing {len(self._files)} files') + command = Command(self._config, self._workspace).build() + + self._print_debug(f'[clang-tidy] command: {command}') + + self._generate_issues(command) + + def _decode_config(self): + self._print_debug(f"Decoding config file {self._config_file_path}") + + contents = "" + with open(self._config_file_path, "r") as config: + contents = config.read() + + self._config = json.loads(contents) + self._print_debug(f'[clang-tidy] config: {self._config}') + + def _print_issue(self, issue): + issue_ = IssueFormatter(issue).format() + + path = os.path.dirname(os.path.abspath(issue_["location"]["path"])) + if path not in self._include_paths: + return + + if issue_['fingerprint'] in self._issues_fpr: + return + + self._issues_fpr.append(issue_['fingerprint']) + print('{}\0'.format(json.dumps(issue_))) + + def _generate_issues(self, command): + issue = None + for line in self._run_command(command): + clean_line = self._ansi_escape.sub('', line) + match = self._issue_parse.match(clean_line) + if match: + if issue is not None: + self._print_issue(issue) + issue = match.groupdict() + elif issue: + if 'content' in issue: + issue['content'].append(line) + else: + issue['content'] = [line] + self._print_issue(issue) + + def _run_command(self, command): + popen = subprocess.Popen(command, + stdout=subprocess.PIPE, + universal_newlines=True) + + for stdout_line in iter(popen.stdout.readline, ""): + self._print_debug(stdout_line) + yield stdout_line + + popen.stdout.close() + + return_code = popen.wait() + if return_code: + self._print_debug( + f"[clang-tidy] {command} ReturnCode {return_code}") + # raise subprocess.CalledProcessError(return_code, command) + + def _print_debug(self, message): + print(message, file=sys.stderr, flush=True) diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/lib/workspace.py b/test/ci/codeclimate/codeclimate-clang-tidy/lib/workspace.py new file mode 100644 index 000000000..29685c3db --- /dev/null +++ b/test/ci/codeclimate/codeclimate-clang-tidy/lib/workspace.py @@ -0,0 +1,40 @@ +import os + + +class Workspace: + def __init__(self, include_paths, suffixes=['.c', '.cpp', '.cc', '.cxx']): + self._include_paths = include_paths + self._suffixes = suffixes + + @property + def files(self): + paths = self._walk() + return [path for path in paths + if self._should_include(path)] + + @property + def include_paths(self): + paths = self._walk() + return [path for path in paths if os.path.isdir(path)] + + @property + def paths(self): + return [path for path in self._include_paths + if self._should_include(path) or os.path.isdir(path)] + + def _should_include(self, name): + _, ext = os.path.splitext(name) + return ext in self._suffixes + + def _walk(self): + paths = [] + + for path in self._include_paths: + if os.path.isdir(path): + for root, dirs, files in os.walk(path): + paths.extend([os.path.join(root, dir_) for dir_ in dirs]) + paths.extend([os.path.join(root, file_) for file_ in files]) + else: + paths.append(path) + + return [os.path.abspath(path) for path in paths] diff --git a/test/ci/debian:testing/Dockerfile b/test/ci/debian:testing/Dockerfile index ba3923f1a..c0b2da0b0 100644 --- a/test/ci/debian:testing/Dockerfile +++ b/test/ci/debian:testing/Dockerfile @@ -1,30 +1,34 @@ FROM debian:testing MAINTAINER Nicolas Richart # library dependencies RUN apt-get -qq update && apt-get -qq -y install \ g++ gfortran clang cmake \ openmpi-bin libmumps-dev libscotch-dev \ libboost-dev libopenblas-dev \ python3 python3-dev python3-numpy python3-scipy python3-mpi4py \ && rm -rf /var/lib/apt/lists/* # for documentation RUN apt-get -qq update && apt-get -qq -y install \ - python3-sphinx python3-sphinx-rtd-theme python3-breathe doxygen graphviz \ + python3-sphinx \ + python3-sphinxcontrib.bibtex \ + python3-sphinx-rtd-theme \ + python3-breathe \ + doxygen graphviz \ && rm -rf /var/lib/apt/lists/* # for ci RUN apt-get -qq update && apt-get -qq -y install \ gmsh python3-pytest \ ccache clang-format python3-flake8 clang-tidy \ curl git xsltproc jq \ - gcovr binutils \ + gcovr llvm binutils \ && rm -rf /var/lib/apt/lists/* COPY .openmpi /root/.openmpi # for debug RUN apt-get -qq update && apt-get -qq -y install \ gdb valgrind \ && rm -rf /var/lib/apt/lists/* diff --git a/test/ci/includes_for_ci/aka_config.hh b/test/ci/includes_for_ci/aka_config.hh new file mode 100644 index 000000000..737661d83 --- /dev/null +++ b/test/ci/includes_for_ci/aka_config.hh @@ -0,0 +1,90 @@ +/** + * @file aka_config.hh.in + * + * @author Nicolas Richart + * + * @date creation: Sun Sep 26 2010 + * @date last modification: Thu Jan 25 2018 + * + * @brief Compilation time configuration of Akantu + * + * + * Copyright (©) 2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with Akantu. If not, see . + * + */ + +/* -------------------------------------------------------------------------- */ +#ifndef AKANTU_AKA_CONFIG_HH_ +#define AKANTU_AKA_CONFIG_HH_ + +#define AKANTU_VERSION_MAJOR 4 +#define AKANTU_VERSION_MINOR 0 +#define AKANTU_VERSION_PATCH 0 +#define AKANTU_VERSION (AKANTU_VERSION_MAJOR * 10000 \ + + AKANTU_VERSION_MINOR * 100 \ + + AKANTU_VERSION_PATCH) + + +namespace akantu { +using Real = double; +using Int = int; +using UInt = unsigned int; +} // akantu + +#define AKANTU_INTEGER_SIZE 4 +#define AKANTU_FLOAT_SIZE 8 + +/* #undef AKANTU_HAS_STRDUP */ + +/* #undef AKANTU_USE_BLAS */ +#define AKANTU_USE_LAPACK + +#define AKANTU_PARALLEL +#define AKANTU_USE_MPI + +#define AKANTU_USE_SCOTCH +/* #undef AKANTU_USE_PTSCOTCH */ +/* #undef AKANTU_SCOTCH_NO_EXTERN */ + +#define AKANTU_IMPLICIT +#define AKANTU_USE_MUMPS +/* #undef AKANTU_USE_PETSC */ + +#define AKANTU_USE_IOHELPER +/* #undef AKANTU_USE_QVIEW */ +/* #undef AKANTU_USE_BLACKDYNAMITE */ + +#define AKANTU_USE_PYBIND11 + +/* #undef AKANTU_USE_OBSOLETE_GETTIMEOFDAY */ + +/* #undef AKANTU_EXTRA_MATERIALS */ +/* #undef AKANTU_STUDENTS_EXTRA_PACKAGE */ +#define AKANTU_DAMAGE_NON_LOCAL + +#define AKANTU_SOLID_MECHANICS +#define AKANTU_STRUCTURAL_MECHANICS +#define AKANTU_HEAT_TRANSFER +#define AKANTU_PYTHON_INTERFACE + +#define AKANTU_COHESIVE_ELEMENT +/* #undef AKANTU_PARALLEL_COHESIVE_ELEMENT */ + +/* #undef AKANTU_IGFEM */ + +/* #undef AKANTU_USE_CGAL */ +/* #undef AKANTU_EMBEDDED */ + +// Debug tools +/* #undef AKANTU_NDEBUG */ +/* #undef AKANTU_DEBUG_TOOLS */ +#define READLINK_COMMAND /bin/readlink +#define ADDR2LINE_COMMAND /usr/bin/addr2line + +#endif /* AKANTU_AKA_CONFIG_HH_ */ diff --git a/test/ci/includes_for_ci/aka_element_classes_info.hh b/test/ci/includes_for_ci/aka_element_classes_info.hh new file mode 100644 index 000000000..b13600d44 --- /dev/null +++ b/test/ci/includes_for_ci/aka_element_classes_info.hh @@ -0,0 +1,373 @@ +/** + * @file aka_element_classes_info.hh.in + * + * @author Aurelia Isabel Cuba Ramos + * @author Nicolas Richart + * + * @date creation: Sun Jul 19 2015 + * @date last modification: Tue Feb 20 2018 + * + * @brief Declaration of the enums for the element classes + * + * + * Copyright (©) 2015-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) + * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + * details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Akantu. If not, see . + * + */ +/* -------------------------------------------------------------------------- */ +#include "aka_safe_enum.hh" +/* -------------------------------------------------------------------------- */ +#include +/* -------------------------------------------------------------------------- */ + +#ifndef AKANTU_AKA_ELEMENT_CLASSES_INFO_HH_ +#define AKANTU_AKA_ELEMENT_CLASSES_INFO_HH_ + +namespace akantu { + +/* -------------------------------------------------------------------------- */ +/* Element Types */ +/* -------------------------------------------------------------------------- */ + +/// @enum ElementType type of elements +enum ElementType { + _not_defined, + _cohesive_1d_2, + _cohesive_2d_4, + _cohesive_2d_6, + _cohesive_3d_12, + _cohesive_3d_16, + _cohesive_3d_6, + _cohesive_3d_8, + _point_1, + _segment_2, + _segment_3, + _triangle_3, + _triangle_6, + _quadrangle_4, + _quadrangle_8, + _tetrahedron_4, + _tetrahedron_10, + _pentahedron_6, + _pentahedron_15, + _hexahedron_8, + _hexahedron_20, + _bernoulli_beam_2, + _bernoulli_beam_3, + _discrete_kirchhoff_triangle_18, + _max_element_type +}; + + +#define AKANTU_ek_cohesive_ELEMENT_TYPE \ + (_cohesive_1d_2) \ + (_cohesive_2d_4) \ + (_cohesive_2d_6) \ + (_cohesive_3d_12) \ + (_cohesive_3d_16) \ + (_cohesive_3d_6) \ + (_cohesive_3d_8) + +#define AKANTU_ek_regular_ELEMENT_TYPE \ + (_point_1) \ + (_segment_2) \ + (_segment_3) \ + (_triangle_3) \ + (_triangle_6) \ + (_quadrangle_4) \ + (_quadrangle_8) \ + (_tetrahedron_4) \ + (_tetrahedron_10) \ + (_pentahedron_6) \ + (_pentahedron_15) \ + (_hexahedron_8) \ + (_hexahedron_20) + +#define AKANTU_ek_structural_ELEMENT_TYPE \ + (_bernoulli_beam_2) \ + (_bernoulli_beam_3) \ + (_discrete_kirchhoff_triangle_18) + + +#define AKANTU_ALL_ELEMENT_TYPE \ + AKANTU_ek_cohesive_ELEMENT_TYPE \ + AKANTU_ek_regular_ELEMENT_TYPE \ + AKANTU_ek_structural_ELEMENT_TYPE + +/* -------------------------------------------------------------------------- */ +/* Element Kinds */ +/* -------------------------------------------------------------------------- */ + +#define AKANTU_COHESIVE_KIND (_ek_cohesive) +#define AKANTU_REGULAR_KIND (_ek_regular) +#define AKANTU_STRUCTURAL_KIND (_ek_structural) + +#define AKANTU_ELEMENT_KIND \ + AKANTU_COHESIVE_KIND \ + AKANTU_REGULAR_KIND \ + AKANTU_STRUCTURAL_KIND + +enum ElementKind { + BOOST_PP_SEQ_ENUM(AKANTU_ELEMENT_KIND), + _ek_not_defined +}; + + +/* -------------------------------------------------------------------------- */ +struct ElementKind_def { + using type = ElementKind; + static const type _begin_ = BOOST_PP_SEQ_HEAD(AKANTU_ELEMENT_KIND); + static const type _end_ = _ek_not_defined; +}; + +using element_kind_t = safe_enum ; + +/* -------------------------------------------------------------------------- */ +/// @enum GeometricalType type of element potentially contained in a Mesh +enum GeometricalType { + _gt_cohesive_1d_2, + _gt_cohesive_2d_4, + _gt_cohesive_2d_6, + _gt_cohesive_3d_12, + _gt_cohesive_3d_16, + _gt_cohesive_3d_6, + _gt_cohesive_3d_8, + _gt_point, + _gt_segment_2, + _gt_segment_3, + _gt_triangle_3, + _gt_triangle_6, + _gt_quadrangle_4, + _gt_quadrangle_8, + _gt_tetrahedron_4, + _gt_tetrahedron_10, + _gt_hexahedron_8, + _gt_hexahedron_20, + _gt_pentahedron_6, + _gt_pentahedron_15, + _gt_not_defined +}; + +/* -------------------------------------------------------------------------- */ +/* Interpolation Types */ +/* -------------------------------------------------------------------------- */ +#define AKANTU_INTERPOLATION_TYPES \ + (_itp_lagrange_point_1) \ + (_itp_lagrange_segment_2) \ + (_itp_lagrange_segment_3) \ + (_itp_lagrange_triangle_3) \ + (_itp_lagrange_triangle_6) \ + (_itp_lagrange_quadrangle_4) \ + (_itp_serendip_quadrangle_8) \ + (_itp_lagrange_tetrahedron_4) \ + (_itp_lagrange_tetrahedron_10) \ + (_itp_lagrange_hexahedron_8) \ + (_itp_serendip_hexahedron_20) \ + (_itp_lagrange_pentahedron_6) \ + (_itp_lagrange_pentahedron_15)\ + (_itp_hermite_2) \ + (_itp_bernoulli_beam_2) \ + (_itp_bernoulli_beam_3) \ + (_itp_discrete_kirchhoff_triangle_6) \ + (_itp_discrete_kirchhoff_triangle_18) + +/// @enum InterpolationType type of elements +enum InterpolationType { + BOOST_PP_SEQ_ENUM(AKANTU_INTERPOLATION_TYPES), + _itp_not_defined +}; + +/* -------------------------------------------------------------------------- */ +/* Some sub types less probable to change */ +/* -------------------------------------------------------------------------- */ +/// @enum GeometricalShapeType types of shapes to define the contains +/// function in the element classes +enum GeometricalShapeType { + _gst_point, + _gst_triangle, + _gst_square, + _gst_prism, + _gst_not_defined +}; + +/* -------------------------------------------------------------------------- */ +/// @enum GaussIntegrationType classes of types using common +/// description of the gauss point position and weights +enum GaussIntegrationType { + _git_point, + _git_segment, + _git_triangle, + _git_tetrahedron, + _git_pentahedron, + _git_not_defined +}; + +/* -------------------------------------------------------------------------- */ +/// @enum InterpolationKind the family of interpolation types +enum InterpolationKind { + _itk_lagrangian, + _itk_structural, + _itk_not_defined +}; + +/* -------------------------------------------------------------------------- */ +// BOOST PART: TOUCH ONLY IF YOU KNOW WHAT YOU ARE DOING +#define AKANTU_BOOST_CASE_MACRO(r, macro, _type) \ + case _type: { \ + macro(_type); \ + break; \ + } + +#define AKANTU_BOOST_LIST_SWITCH(macro1, list1, var) \ + do { \ + switch (var) { \ + BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, macro1, list1) \ + default: { \ + AKANTU_ERROR("Type (" \ + << var /* NOLINT */ << ") not handled by this function"); \ + } \ + } \ + } while (0) + +#define AKANTU_BOOST_LIST_SWITCH_NO_DEFAULT(macro1, list1, var) \ + do { \ + switch (var) { \ + BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO, macro1, list1) \ + case _not_defined: /* FALLTHRU */ \ + case _max_element_type: \ + break; \ + } \ + } while (0) + +#define AKANTU_BOOST_ELEMENT_SWITCH(macro1, list1) \ + AKANTU_BOOST_LIST_SWITCH(macro1, list1, type) + +#define AKANTU_BOOST_ELEMENT_SWITCH_NO_DEFAULT(macro1, list1) \ + AKANTU_BOOST_LIST_SWITCH_NO_DEFAULT(macro1, list1, type) + +#define AKANTU_BOOST_ALL_ELEMENT_SWITCH(macro) \ + AKANTU_BOOST_ELEMENT_SWITCH(macro, AKANTU_ALL_ELEMENT_TYPE) + +#define AKANTU_BOOST_ALL_ELEMENT_SWITCH_NO_DEFAULT(macro) \ + AKANTU_BOOST_ELEMENT_SWITCH_NO_DEFAULT(macro, AKANTU_ALL_ELEMENT_TYPE) + +#define AKANTU_BOOST_LIST_MACRO(r, macro, type) macro(type) + +#define AKANTU_BOOST_APPLY_ON_LIST(macro, list) \ + BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_LIST_MACRO, macro, list) + +#define AKANTU_BOOST_ALL_ELEMENT_LIST(macro) \ + AKANTU_BOOST_APPLY_ON_LIST(macro, AKANTU_ALL_ELEMENT_TYPE) + +#define AKANTU_GET_ELEMENT_LIST(kind) AKANTU##kind##_ELEMENT_TYPE + +#define AKANTU_BOOST_KIND_ELEMENT_SWITCH(macro, kind) \ + AKANTU_BOOST_ELEMENT_SWITCH(macro, AKANTU_GET_ELEMENT_LIST(kind)) + +// BOOST_PP_SEQ_TO_LIST does not exists in Boost < 1.49 +#define AKANTU_GENERATE_KIND_LIST(seq) \ + BOOST_PP_TUPLE_TO_LIST(BOOST_PP_SEQ_SIZE(seq), BOOST_PP_SEQ_TO_TUPLE(seq)) + +#define AKANTU_ELEMENT_KIND_BOOST_LIST \ + AKANTU_GENERATE_KIND_LIST(AKANTU_ELEMENT_KIND) + +#define AKANTU_BOOST_ALL_KIND_LIST(macro, list) \ + BOOST_PP_LIST_FOR_EACH(AKANTU_BOOST_LIST_MACRO, macro, list) + +#define AKANTU_BOOST_ALL_KIND(macro) \ + AKANTU_BOOST_ALL_KIND_LIST(macro, AKANTU_ELEMENT_KIND_BOOST_LIST) + +#define AKANTU_BOOST_ALL_KIND_SWITCH(macro) \ + AKANTU_BOOST_LIST_SWITCH(macro, AKANTU_ELEMENT_KIND, kind) + + +#define AKANTU_BOOST_COHESIVE_ELEMENT_SWITCH(macro) \ + AKANTU_BOOST_ELEMENT_SWITCH(macro, \ + AKANTU_ek_cohesive_ELEMENT_TYPE) + +#define AKANTU_BOOST_COHESIVE_ELEMENT_LIST(macro) \ + AKANTU_BOOST_APPLY_ON_LIST(macro, \ + AKANTU_ek_cohesive_ELEMENT_TYPE) + +#define AKANTU_BOOST_REGULAR_ELEMENT_SWITCH(macro) \ + AKANTU_BOOST_ELEMENT_SWITCH(macro, \ + AKANTU_ek_regular_ELEMENT_TYPE) + +#define AKANTU_BOOST_REGULAR_ELEMENT_LIST(macro) \ + AKANTU_BOOST_APPLY_ON_LIST(macro, \ + AKANTU_ek_regular_ELEMENT_TYPE) + +#define AKANTU_BOOST_STRUCTURAL_ELEMENT_SWITCH(macro) \ + AKANTU_BOOST_ELEMENT_SWITCH(macro, \ + AKANTU_ek_structural_ELEMENT_TYPE) + +#define AKANTU_BOOST_STRUCTURAL_ELEMENT_LIST(macro) \ + AKANTU_BOOST_APPLY_ON_LIST(macro, \ + AKANTU_ek_structural_ELEMENT_TYPE) + + +// /// define kept for compatibility reasons (they are most probably not needed +// /// anymore) \todo check if they can be removed +// #define AKANTU_REGULAR_ELEMENT_TYPE AKANTU_ek_regular_ELEMENT_TYPE +// #define AKANTU_COHESIVE_ELEMENT_TYPE AKANTU_ek_cohesive_ELEMENT_TYPE +// #define AKANTU_STRUCTURAL_ELEMENT_TYPE AKANTU_ek_structural_ELEMENT_TYPE +// #define AKANTU_IGFEM_ELEMENT_TYPE AKANTU_ek_igfem_ELEMENT_TYPE + +/* -------------------------------------------------------------------------- */ +/* Lists of interests for FEEngineTemplate functions */ +/* -------------------------------------------------------------------------- */ +#define AKANTU_FE_ENGINE_LIST_ASSEMBLE_FIELDS \ + AKANTU_GENERATE_KIND_LIST((_ek_regular) \ + (_ek_structural)) +#define AKANTU_FE_ENGINE_LIST_COMPUTE_SHAPES_DERIVATIVES \ + AKANTU_GENERATE_KIND_LIST((_ek_regular) \ + (_ek_structural)) +#define AKANTU_FE_ENGINE_LIST_COMPUTE_SHAPES \ + AKANTU_GENERATE_KIND_LIST((_ek_regular) \ + (_ek_structural)) +#define AKANTU_FE_ENGINE_LIST_INTERPOLATE \ + AKANTU_GENERATE_KIND_LIST((_ek_regular)) +#define AKANTU_FE_ENGINE_LIST_LAGRANGE_BASE \ + AKANTU_GENERATE_KIND_LIST((_ek_cohesive) \ + (_ek_regular)) +#define AKANTU_FE_ENGINE_LIST_INVERSE_MAP \ + AKANTU_GENERATE_KIND_LIST((_ek_cohesive) \ + (_ek_regular)) +#define AKANTU_FE_ENGINE_LIST_INTERPOLATE_ON_INTEGRATION_POINTS \ + AKANTU_GENERATE_KIND_LIST((_ek_cohesive) \ + (_ek_regular) \ + (_ek_structural)) +#define AKANTU_FE_ENGINE_LIST_GRADIENT_ON_INTEGRATION_POINTS \ + AKANTU_GENERATE_KIND_LIST((_ek_cohesive) \ + (_ek_regular) \ + (_ek_structural)) +#define AKANTU_FE_ENGINE_LIST_GET_SHAPES_DERIVATIVES \ + AKANTU_GENERATE_KIND_LIST((_ek_cohesive) \ + (_ek_regular) \ + (_ek_structural)) +#define AKANTU_FE_ENGINE_LIST_CONTAINS \ + AKANTU_GENERATE_KIND_LIST((_ek_cohesive) \ + (_ek_regular)) +#define AKANTU_FE_ENGINE_LIST_COMPUTE_NORMALS_ON_INTEGRATION_POINTS \ + AKANTU_GENERATE_KIND_LIST((_ek_cohesive) \ + (_ek_regular)) + + +} // akantu + +#endif /* AKANTU_AKA_ELEMENT_CLASSES_INFO_HH_ */ + +#include "aka_element_classes_info_inline_impl.hh" diff --git a/test/ci/includes_for_ci/aka_fortran_mangling.hh b/test/ci/includes_for_ci/aka_fortran_mangling.hh new file mode 100644 index 000000000..d27b675b2 --- /dev/null +++ b/test/ci/includes_for_ci/aka_fortran_mangling.hh @@ -0,0 +1,16 @@ +#ifndef AKA_FC_HEADER_INCLUDED +#define AKA_FC_HEADER_INCLUDED + +/* Mangling for Fortran global symbols without underscores. */ +#define AKA_FC_GLOBAL(name,NAME) name##_ + +/* Mangling for Fortran global symbols with underscores. */ +#define AKA_FC_GLOBAL_(name,NAME) name##_ + +/* Mangling for Fortran module symbols without underscores. */ +#define AKA_FC_MODULE(mod_name,name, mod_NAME,NAME) __##mod_name##_MOD_##name + +/* Mangling for Fortran module symbols with underscores. */ +#define AKA_FC_MODULE_(mod_name,name, mod_NAME,NAME) __##mod_name##_MOD_##name + +#endif diff --git a/test/ci/includes_for_ci/material_list.hh b/test/ci/includes_for_ci/material_list.hh new file mode 100644 index 000000000..21440bce2 --- /dev/null +++ b/test/ci/includes_for_ci/material_list.hh @@ -0,0 +1,46 @@ +/** + * @file material_list.hh.in + * + * @author Nicolas Richart + * + * @date creation: Wed Sep 01 2010 + * @date last modification: Wed Feb 03 2016 + * + * @brief List of materials and all includes + * + * + * Copyright (©) 2014-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) + * + * Akantu is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with Akantu. If not, see . + * + */ + +/* -------------------------------------------------------------------------- */ + +#ifndef __AKANTU_MATERIAL_LIST_HH__ +#define __AKANTU_MATERIAL_LIST_HH__ + +#include "aka_config.hh" + +/* -------------------------------------------------------------------------- */ +/* Material includes */ +/* -------------------------------------------------------------------------- */ +#include "material_cohesive_includes.hh" +#include "material_non_local_includes.hh" +#include "material_core_includes.hh" + +/* -------------------------------------------------------------------------- */ +/* Material list */ +/* -------------------------------------------------------------------------- */ +#define AKANTU_MATERIAL_LIST \ + AKANTU_COHESIVE_MATERIAL_LIST \ + AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST \ + AKANTU_CORE_MATERIAL_LIST \ + +// leave an empty line after the list + +#endif /* __AKANTU_MATERIAL_LIST_HH__ */ diff --git a/test/ci/scripts/clang-tidy2code-quality.py b/test/ci/scripts/clang-tidy2code-quality.py new file mode 100644 index 000000000..1f5c5e615 --- /dev/null +++ b/test/ci/scripts/clang-tidy2code-quality.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +import re +import os +import hashlib +import json +import sys + + +# 7-bit C1 ANSI sequences +ansi_escape = re.compile(r''' + \x1B # ESC + (?: # 7-bit C1 Fe (except CSI) + [@-Z\\-_] + | # or [ for CSI, followed by a control sequence + \[ + [0-?]* # Parameter bytes + [ -/]* # Intermediate bytes + [@-~] # Final byte + ) +''', re.VERBOSE) + +re_log_parse = re.compile( + r'(?P.*\.(cc|hh)):(?P[0-9]+):(?P[0-9]+): warning: (?P.*) \[(?P.*)\]' # noqa +) + + +categories = { + "bugprone": "Bug Risk", + "modernize": "Clarity", + "mpi": "Bug Risk", + "openmp": "Bug Risk", + "performance": "Performance", + "readability": "Clarity", +} + +issues = {} + +with open('clang-tidy-all-out.log', 'r') as log: + for line in log: + clean_line = ansi_escape.sub('', line) + match = re_log_parse.match(clean_line) + if match: + line_dict = match.groupdict() + line_dict['file'] = os.path.relpath(line_dict['file']) + + line_dict['fingerprint'] = hashlib.md5( + '{file}:{line}:{column}:{type}'.format(**line_dict).encode() + ).hexdigest() + + issue = { + 'type': 'issue', + 'description': line_dict['detail'], + 'fingerprint': line_dict['fingerprint'], + 'location': { + "path": line_dict['file'], + "lines": { + "begin": int(line_dict['line']), + "end": int(line_dict['line']), + }, + "positions": { + "begin": { + "line": int(line_dict['line']), + "column": int(line_dict['column']), + }, + }, + + }, + 'severity': 'minor', + } + + category = line_dict['type'].split('-')[0] + if category in categories: + issue['category'] = categories[category] + + # use a dictionnary to avoid duplicates + issues[issue['fingerprint']] = issue + +issues = list(issues.values()) + +json.dump(issues, sys.stdout) diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_plastic_materials.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_plastic_materials.cc index dd1ed42a9..400e57c94 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_plastic_materials.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_plastic_materials.cc @@ -1,191 +1,192 @@ /** * @file test_plastic_materials.cc * * @author Guillaume Anciaux * * @date creation: Fri Nov 17 2017 * @date last modification: Wed Feb 21 2018 * * @brief Tests the plastic material * * * Copyright (©) 2016-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "material_linear_isotropic_hardening.hh" #include "solid_mechanics_model.hh" #include "test_material_fixtures.hh" #include #include /* -------------------------------------------------------------------------- */ using namespace akantu; using mat_types = ::testing::Types< // Traits, // Traits, Traits>; /* -------------------------------------------------------------------------- */ template <> void FriendMaterial>::testComputeStress() { Real E = 1.; // Real nu = .3; Real nu = 0.; Real rho = 1.; Real sigma_0 = 1.; Real h = 0.; Real bulk_modulus_K = E / 3. / (1 - 2. * nu); Real shear_modulus_mu = 0.5 * E / (1 + nu); setParam("E", E); setParam("nu", nu); setParam("rho", rho); setParam("sigma_y", sigma_0); setParam("h", h); auto rotation_matrix = getRandomRotation(); Real max_strain = 10.; Real strain_steps = 100; Real dt = max_strain / strain_steps; std::vector steps(strain_steps); std::iota(steps.begin(), steps.end(), 0.); Matrix previous_grad_u_rot(3, 3, 0.); Matrix previous_sigma(3, 3, 0.); Matrix previous_sigma_rot(3, 3, 0.); Matrix inelastic_strain_rot(3, 3, 0.); Matrix inelastic_strain(3, 3, 0.); Matrix previous_inelastic_strain(3, 3, 0.); Matrix previous_inelastic_strain_rot(3, 3, 0.); Matrix sigma_rot(3, 3, 0.); Real iso_hardening = 0.; Real previous_iso_hardening = 0.; // hydrostatic loading (should not plastify) for (auto && i : steps) { auto t = i * dt; auto grad_u = this->getHydrostaticStrain(t); auto grad_u_rot = this->applyRotation(grad_u, rotation_matrix); this->computeStressOnQuad(grad_u_rot, previous_grad_u_rot, sigma_rot, previous_sigma_rot, inelastic_strain_rot, previous_inelastic_strain_rot, iso_hardening, previous_iso_hardening, 0., 0.); auto sigma = this->reverseRotation(sigma_rot, rotation_matrix); Matrix sigma_expected = t * 3. * bulk_modulus_K * Matrix::eye(3, 1.); Real stress_error = (sigma - sigma_expected).norm(); ASSERT_NEAR(stress_error, 0., 1e-13); ASSERT_NEAR(inelastic_strain_rot.norm(), 0., 1e-13); previous_grad_u_rot = grad_u_rot; previous_sigma_rot = sigma_rot; previous_inelastic_strain_rot = inelastic_strain_rot; previous_iso_hardening = iso_hardening; } // deviatoric loading (should plastify) // stress at onset of plastication Real beta = sqrt(42); Real t_P = sigma_0 / 2. / shear_modulus_mu / beta; Matrix sigma_P = sigma_0 / beta * this->getDeviatoricStrain(1.); for (auto && i : steps) { auto t = i * dt; auto grad_u = this->getDeviatoricStrain(t); auto grad_u_rot = this->applyRotation(grad_u, rotation_matrix); - Real iso_hardening, previous_iso_hardening; + Real iso_hardening{0.}; + Real previous_iso_hardening{0.}; this->computeStressOnQuad(grad_u_rot, previous_grad_u_rot, sigma_rot, previous_sigma_rot, inelastic_strain_rot, previous_inelastic_strain_rot, iso_hardening, previous_iso_hardening, 0., 0.); auto sigma = this->reverseRotation(sigma_rot, rotation_matrix); auto inelastic_strain = this->reverseRotation(inelastic_strain_rot, rotation_matrix); if (t < t_P) { Matrix sigma_expected = shear_modulus_mu * (grad_u + grad_u.transpose()); Real stress_error = (sigma - sigma_expected).norm(); ASSERT_NEAR(stress_error, 0., 1e-13); ASSERT_NEAR(inelastic_strain_rot.norm(), 0., 1e-13); } else if (t > t_P + dt) { // skip the transition from non plastic to plastic auto delta_lambda_expected = dt / t * previous_sigma.doubleDot(grad_u + grad_u.transpose()) / 2.; auto delta_inelastic_strain_expected = delta_lambda_expected * 3. / 2. / sigma_0 * previous_sigma; auto inelastic_strain_expected = delta_inelastic_strain_expected + previous_inelastic_strain; ASSERT_NEAR((inelastic_strain - inelastic_strain_expected).norm(), 0., 1e-13); auto delta_sigma_expected = 2. * shear_modulus_mu * (0.5 * dt / t * (grad_u + grad_u.transpose()) - delta_inelastic_strain_expected); auto delta_sigma = sigma - previous_sigma; ASSERT_NEAR((delta_sigma_expected - delta_sigma).norm(), 0., 1e-13); } previous_sigma = sigma; previous_sigma_rot = sigma_rot; previous_grad_u_rot = grad_u_rot; previous_inelastic_strain = inelastic_strain; previous_inelastic_strain_rot = inelastic_strain_rot; } } namespace { template class TestPlasticMaterialFixture : public ::TestMaterialFixture {}; TYPED_TEST_SUITE(TestPlasticMaterialFixture, mat_types, ); TYPED_TEST(TestPlasticMaterialFixture, ComputeStress) { this->material->testComputeStress(); } TYPED_TEST(TestPlasticMaterialFixture, DISABLED_EnergyDensity) { this->material->testEnergyDensity(); } TYPED_TEST(TestPlasticMaterialFixture, DISABLED_ComputeTangentModuli) { this->material->testComputeTangentModuli(); } TYPED_TEST(TestPlasticMaterialFixture, DISABLED_ComputeCelerity) { this->material->testCelerity(); } } // namespace /*****************************************************************/