diff --git a/.clang-tidy b/.clang-tidy index 59ad5a5e7..92d0c1a8e 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,12 +1,14 @@ Checks: " + -*, modernize-use-*, -modernize-use-trailing-return-type*, performance-*, mpi-*, openmp-*, - bugprone-*, - readability-*, -readability-magic-numbers, -readability-redundant-access-specifiers, - -clang-analyzer-* + -bugprone-*, + readability-*, -readability-magic-numbers, -readability-redundant-access-specifiers, -readability-convert-member-functions-to-static, + -clang-analyzer-*, + -clang-diagnostic-*, " AnalyzeTemporaryDtors: false HeaderFilterRegex: 'src/.*' FormatStyle: file diff --git a/.codeclimate.yml b/.codeclimate.yml index ee811077a..e72a3e9cf 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,50 +1,50 @@ checks: duplicate: enabled: true exclude_patterns: - "test/" - "examples/" structure: enabled: true exclude_patterns: - "test/" plugins: editorconfig: enabled: false config: editorconfig: .editorconfig exclude_patterns: - ".clangd/" - ".cache/" pep8: enabled: true exclude_patterns: - "test/test_fe_engine/py_engine/py_engine.py" cppcheck: enabled: false project: compile_commands.json language: c++ check: warning, style, performance stds: [c++14] fixme: enabled: true exclude_patterns: - "doc/" clang-tidy: enabled: true extra-arg: - -std=c++14 - -Ithird-party/akantu_iterators/include - -Ithird-party/iohelper/src - -Itest/ci/includes_for_ci + - -Isrc/mesh exclude_patterns: - "test/" - "cmake/" - "examples/" - - "extra_packages/igfem/" - - "extra_packages/extra-materials/" + - "extra_packages/" exclude_patterns: - "third-party/" - "build*/" diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4ff213407..86df32a91 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,349 +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 # ------------------------------------------------------------------------------ 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 - CODECLIMATE_DEBUG: 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 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/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/lib/issue_formatter.py b/test/ci/codeclimate/codeclimate-clang-tidy/lib/issue_formatter.py index e3ce5e2f5..4b0ec3308 100644 --- a/test/ci/codeclimate/codeclimate-clang-tidy/lib/issue_formatter.py +++ b/test/ci/codeclimate/codeclimate-clang-tidy/lib/issue_formatter.py @@ -1,80 +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] - if type_ in self.CLASSIFICATIONS: - issue['categories'] = self.CLASSIFICATIONS[type_]['categories'] - issue['severity'] = self.CLASSIFICATIONS[type_]['severity'] - elif self.issue_dict['type'] == 'clang-diagnostic-error': - issue['categories'] = ['Bug Risk'] - issue['severity'] = 'blocker' + 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 index f64028f3e..d25a2e223 100644 --- a/test/ci/codeclimate/codeclimate-clang-tidy/lib/runner.py +++ b/test/ci/codeclimate/codeclimate-clang-tidy/lib/runner.py @@ -1,101 +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): if 'debug' in self._config and self._config['debug'] == 1: print(message, file=sys.stderr)