diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..943cc1d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,53 @@ +name: CI + +on: + workflow_dispatch: + pull_request: + push: + branches: + - master + +jobs: + + default-shell: + + strategy: + fail-fast: false + matrix: + runs-on: [ubuntu-latest, macos-latest, windows-latest] + + defaults: + run: + shell: bash -l {0} + + name: "${{ matrix.runs-on }} • x64 ${{ matrix.args }}" + runs-on: ${{ matrix.runs-on }} + + steps: + + - name: Basic GitHub action setup + uses: actions/checkout@v2 + + - name: Set conda environment "test" + uses: conda-incubator/setup-miniconda@v2 + with: + mamba-version: "*" + channels: conda-forge,defaults + channel-priority: true + environment-file: environment.yaml + activate-environment: test + auto-activate-base: false + + - name: Configure using CMake (with examples) + if: runner.os == 'Linux' + run: cmake . -DBUILD_TESTS=ON -DBUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=RELEASE + + - name: Configure using CMake (without examples) + if: runner.os != 'Linux' + run: cmake . -DBUILD_TESTS=ON -DBUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=RELEASE + + - name: Build C++ tests & examples + run: cmake --build . + + - name: Run C++ tests & examples + run: cmake --build . --target "RUN_TESTS_AND_EXAMPLES" diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ab6a39..62271aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,92 +1,99 @@ # # (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM # cmake_minimum_required(VERSION 3.0) # Basic settings # ============== project(GooseFEM) option(BUILD_TESTS "Build tests" OFF) option(BUILD_EXAMPLES "Build examples" OFF) # Version # ======= file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/GooseFEM/config.h" GooseFEM_version_defines REGEX "#define GOOSEFEM_VERSION_(MAJOR|MINOR|PATCH)") foreach(ver ${GooseFEM_version_defines}) if(ver MATCHES "#define GOOSEFEM_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$") set(GOOSEFEM_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "") endif() endforeach() set(GOOSEFEM_VERSION ${GOOSEFEM_VERSION_MAJOR}.${GOOSEFEM_VERSION_MINOR}.${GOOSEFEM_VERSION_PATCH}) message(STATUS "Building GooseFEM v${GOOSEFEM_VERSION}") # Set target # ========== find_package(xtensor REQUIRED) add_library(GooseFEM INTERFACE) target_include_directories(GooseFEM INTERFACE $ $) target_link_libraries(GooseFEM INTERFACE xtensor) # Installation # ============ include(CMakePackageConfigHelpers) include(GNUInstallDirs) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include) install(TARGETS GooseFEM EXPORT GooseFEM-targets) install( EXPORT GooseFEM-targets FILE GooseFEMTargets.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/GooseFEM") set(_GOOSEFEM ${CMAKE_SIZEOF_VOID_P}) unset(CMAKE_SIZEOF_VOID_P) write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/GooseFEMConfigVersion.cmake" VERSION ${GOOSEFEM_VERSION} COMPATIBILITY AnyNewerVersion) set(CMAKE_SIZEOF_VOID_P ${_GOOSEFEM}) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/GooseFEMConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/GooseFEMConfigVersion.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/GooseFEM") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/GooseFEM.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/GooseFEM.pc" @ONLY) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/GooseFEM.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/") # Add builds # ========== include("GooseFEMConfig.cmake") +set(CTEST_TEST_TARGET_ALIAS RUN_TESTS_AND_EXAMPLES) +include(CTest) + if(BUILD_TESTS) + enable_testing() add_subdirectory(test/basic) + + enable_testing() add_subdirectory(test/gmat) endif() if(BUILD_EXAMPLES) + enable_testing() add_subdirectory(docs/examples) endif() diff --git a/README.md b/README.md index 2cc2080..e1c9a31 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,24 @@ +[![CI](https://github.com/tdegeus/GooseFEM/workflows/CI/badge.svg)](https://github.com/tdegeus/GooseFEM/actions) [![Travis](https://travis-ci.com/tdegeus/GooseFEM.svg?branch=master)](https://travis-ci.com/tdegeus/GooseFEM) [![appveyor](https://ci.appveyor.com/api/projects/status/w20e6gw5mdhnntyx?svg=true)](https://ci.appveyor.com/project/tdegeus/goosefem) [![Documentation Status](https://readthedocs.org/projects/goosefem/badge/?version=latest)](https://readthedocs.org/projects/goosefem/badge/?version=latest) ## GooseFEM Library to perform static or dynamic finite elements computations. The core of the implementation is a C++ library. For user convenience a Python interface is provided too. Please consult the documentation for more information: https://goosefem.readthedocs.io ## Credit / copyright (c) T.W.J. de Geus | [www.geus.me](http://www.geus.me) | [tom@geus.me](mailto:tom@geus.me) Tom de Geus was financially supported by: * [Swiss National Science Foundation (FNSF), Switzerland](http://www.snfs.ch) * [École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland](http://www.epfl.ch) * [Eindhoven University of Technology (TU/e), Eindhoven, The Netherlands](http://www.tue.nl) * [The Netherlands Research Council (NWO), The Netherlands](http://www.nwo.nl) * [Materials Innovation Institute (M2i), The Netherlands](http://www.m2i.nl) diff --git a/docs/examples/CMakeLists.txt b/docs/examples/CMakeLists.txt index 898a4c5..bb4e549 100644 --- a/docs/examples/CMakeLists.txt +++ b/docs/examples/CMakeLists.txt @@ -1,84 +1,107 @@ cmake_minimum_required(VERSION 3.16) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) project(GooseFEM-examples) find_package(GooseFEM REQUIRED CONFIG) endif() -option(WARNINGS "Show build warnings" ON) +set(ASSERT OFF) +set(DEBUG OFF) option(SIMD "Enable xsimd" ON) -option(DEBUG "Enable all assertions" OFF) +option(WARNINGS "Enable warnings" ON) set(HIGHFIVE_USE_BOOST 0) set(HIGHFIVE_USE_XTENSOR 1) find_package(HighFive REQUIRED) find_package(XDMFWrite_HighFive REQUIRED) +find_package(GMatElastic REQUIRED) +find_package(GMatElastoPlastic REQUIRED) +# find_package(GMatElastoPlasticFiniteStrainSimo REQUIRED) +find_package(GMatNonLinearElastic REQUIRED) add_library(libraries INTERFACE IMPORTED) -target_link_libraries(libraries INTERFACE GooseFEM HighFive XDMFWrite_HighFive) +target_link_libraries(libraries INTERFACE + GooseFEM + HighFive + XDMFWrite_HighFive + GMatElastic + GMatElastoPlastic + # GMatElastoPlasticFiniteStrainSimo + GMatNonLinearElastic) -if (SIMD) +if(SIMD) target_link_libraries(libraries INTERFACE xtensor::optimize xtensor::use_xsimd) endif() -if (WARNINGS) +if(WARNINGS) target_link_libraries(libraries INTERFACE GooseFEM::compiler_warnings) endif() -if (DEBUG) +if(ASSERT) + target_link_libraries(libraries INTERFACE GooseFEM::assert) +endif() + +if(DEBUG) target_link_libraries(libraries INTERFACE GooseFEM::debug) endif() # create executable set(exec "statics_FixedDisplacements_LinearElastic_example") set(source "statics/FixedDisplacements_LinearElastic/example.cpp") add_executable(${exec} ${source}) target_link_libraries(${exec} PRIVATE libraries) +add_test(NAME ${exec} COMMAND ${exec}) # create executable set(exec "statics_FixedDisplacements_LinearElastic_manual_partition") set(source "statics/FixedDisplacements_LinearElastic/manual_partition.cpp") add_executable(${exec} ${source}) target_link_libraries(${exec} PRIVATE libraries) +add_test(NAME ${exec} COMMAND ${exec}) # create executable set(exec "statics_MixedPeriodic_LinearElastic_example") set(source "statics/MixedPeriodic_LinearElastic/example.cpp") add_executable(${exec} ${source}) target_link_libraries(${exec} PRIVATE libraries) +add_test(NAME ${exec} COMMAND ${exec}) # create executable set(exec "statics_Periodic_ElastoPlastic_main") set(source "statics/Periodic_ElastoPlastic/main.cpp") add_executable(${exec} ${source}) target_link_libraries(${exec} PRIVATE libraries) +add_test(NAME ${exec} COMMAND ${exec}) # create executable -set(exec "statics_Periodic_ElastoPlasticFiniteStrainSimo_main") -set(source "statics/Periodic_ElastoPlasticFiniteStrainSimo/main.cpp") -add_executable(${exec} ${source}) -target_link_libraries(${exec} PRIVATE libraries) +# set(exec "statics_Periodic_ElastoPlasticFiniteStrainSimo_main") +# set(source "statics/Periodic_ElastoPlasticFiniteStrainSimo/main.cpp") +# add_executable(${exec} ${source}) +# target_link_libraries(${exec} PRIVATE libraries) +# add_test(NAME ${exec} COMMAND ${exec}) # create executable set(exec "statics_Periodic_LinearElastic_main") set(source "statics/Periodic_LinearElastic/main.cpp") add_executable(${exec} ${source}) target_link_libraries(${exec} PRIVATE libraries) +add_test(NAME ${exec} COMMAND ${exec}) # create executable set(exec "statics_Periodic_NonLinearElastic_main") set(source "statics/Periodic_NonLinearElastic/main.cpp") add_executable(${exec} ${source}) target_link_libraries(${exec} PRIVATE libraries) +add_test(NAME ${exec} COMMAND ${exec}) diff --git a/environment.yaml b/environment.yaml new file mode 100644 index 0000000..d2152e4 --- /dev/null +++ b/environment.yaml @@ -0,0 +1,21 @@ +channels: + - conda-forge +dependencies: + - cmake + - xtensor + - xsimd + - eigen + - python + - numpy + - pyxtensor + - catch2 + - h5py + - highfive + - xdmfwrite_highfive + - xdmfwrite_h5py + - gmatelastic + - gmatnonlinearelastic + - gmatelastoplastic + - gmatelastoplasticfinitestrainsimo + - gmatelastoplasticqpot + # - python-gmatelastic diff --git a/include/GooseFEM/MatrixPartitionedTyings.hpp b/include/GooseFEM/MatrixPartitionedTyings.hpp index 8c2ed70..aee2b6f 100644 --- a/include/GooseFEM/MatrixPartitionedTyings.hpp +++ b/include/GooseFEM/MatrixPartitionedTyings.hpp @@ -1,454 +1,455 @@ /* (c - GPLv3) T.W.J. de Geus (Tom) | tom@geus.me | www.geus.me | github.com/tdegeus/GooseFEM */ #ifndef GOOSEFEM_MATRIXPARTITIONEDTYINGS_HPP #define GOOSEFEM_MATRIXPARTITIONEDTYINGS_HPP #include "MatrixPartitionedTyings.h" namespace GooseFEM { inline MatrixPartitionedTyings::MatrixPartitionedTyings( const xt::xtensor& conn, const xt::xtensor& dofs, const Eigen::SparseMatrix& Cdu, const Eigen::SparseMatrix& Cdp) : m_conn(conn), m_dofs(dofs), m_Cdu(Cdu), m_Cdp(Cdp) { GOOSEFEM_ASSERT(Cdu.rows() == Cdp.rows()); m_nnu = static_cast(m_Cdu.cols()); m_nnp = static_cast(m_Cdp.cols()); m_nnd = static_cast(m_Cdp.rows()); m_nni = m_nnu + m_nnp; m_ndof = m_nni + m_nnd; m_iiu = xt::arange(m_nnu); m_iip = xt::arange(m_nnu, m_nnu + m_nnp); m_iid = xt::arange(m_nni, m_nni + m_nnd); m_nelem = m_conn.shape(0); m_nne = m_conn.shape(1); m_nnode = m_dofs.shape(0); m_ndim = m_dofs.shape(1); m_Cud = m_Cdu.transpose(); m_Cpd = m_Cdp.transpose(); m_Tuu.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); m_Tup.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); m_Tpu.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); m_Tpp.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); m_Tud.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); m_Tpd.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); m_Tdu.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); m_Tdp.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); m_Tdd.reserve(m_nelem * m_nne * m_ndim * m_nne * m_ndim); m_Auu.resize(m_nnu, m_nnu); m_Aup.resize(m_nnu, m_nnp); m_Apu.resize(m_nnp, m_nnu); m_App.resize(m_nnp, m_nnp); m_Aud.resize(m_nnu, m_nnd); m_Apd.resize(m_nnp, m_nnd); m_Adu.resize(m_nnd, m_nnu); m_Adp.resize(m_nnd, m_nnp); m_Add.resize(m_nnd, m_nnd); GOOSEFEM_ASSERT(m_ndof <= m_nnode * m_ndim); GOOSEFEM_ASSERT(m_ndof == xt::amax(m_dofs)() + 1); } inline size_t MatrixPartitionedTyings::nelem() const { return m_nelem; } inline size_t MatrixPartitionedTyings::nne() const { return m_nne; } inline size_t MatrixPartitionedTyings::nnode() const { return m_nnode; } inline size_t MatrixPartitionedTyings::ndim() const { return m_ndim; } inline size_t MatrixPartitionedTyings::ndof() const { return m_ndof; } inline size_t MatrixPartitionedTyings::nnu() const { return m_nnu; } inline size_t MatrixPartitionedTyings::nnp() const { return m_nnp; } inline size_t MatrixPartitionedTyings::nni() const { return m_nni; } inline size_t MatrixPartitionedTyings::nnd() const { return m_nnd; } inline xt::xtensor MatrixPartitionedTyings::dofs() const { return m_dofs; } inline xt::xtensor MatrixPartitionedTyings::iiu() const { return m_iiu; } inline xt::xtensor MatrixPartitionedTyings::iip() const { return m_iip; } inline xt::xtensor MatrixPartitionedTyings::iii() const { return xt::arange(m_nni); } inline xt::xtensor MatrixPartitionedTyings::iid() const { return m_iid; } inline void MatrixPartitionedTyings::assemble(const xt::xtensor& elemmat) { GOOSEFEM_ASSERT(xt::has_shape(elemmat, {m_nelem, m_nne * m_ndim, m_nne * m_ndim})); m_Tuu.clear(); m_Tup.clear(); m_Tpu.clear(); m_Tpp.clear(); m_Tud.clear(); m_Tpd.clear(); m_Tdu.clear(); m_Tdp.clear(); m_Tdd.clear(); for (size_t e = 0; e < m_nelem; ++e) { for (size_t m = 0; m < m_nne; ++m) { for (size_t i = 0; i < m_ndim; ++i) { size_t di = m_dofs(m_conn(e, m), i); for (size_t n = 0; n < m_nne; ++n) { for (size_t j = 0; j < m_ndim; ++j) { size_t dj = m_dofs(m_conn(e, n), j); if (di < m_nnu && dj < m_nnu) { m_Tuu.push_back(Eigen::Triplet( di, dj, elemmat(e, m * m_ndim + i, n * m_ndim + j))); } else if (di < m_nnu && dj < m_nni) { m_Tup.push_back(Eigen::Triplet( di, dj - m_nnu, elemmat(e, m * m_ndim + i, n * m_ndim + j))); } else if (di < m_nnu) { m_Tud.push_back(Eigen::Triplet( di, dj - m_nni, elemmat(e, m * m_ndim + i, n * m_ndim + j))); } else if (di < m_nni && dj < m_nnu) { m_Tpu.push_back(Eigen::Triplet( di - m_nnu, dj, elemmat(e, m * m_ndim + i, n * m_ndim + j))); } else if (di < m_nni && dj < m_nni) { m_Tpp.push_back(Eigen::Triplet( di - m_nnu, dj - m_nnu, elemmat(e, m * m_ndim + i, n * m_ndim + j))); } else if (di < m_nni) { m_Tpd.push_back(Eigen::Triplet( di - m_nnu, dj - m_nni, elemmat(e, m * m_ndim + i, n * m_ndim + j))); } else if (dj < m_nnu) { m_Tdu.push_back(Eigen::Triplet( di - m_nni, dj, elemmat(e, m * m_ndim + i, n * m_ndim + j))); } else if (dj < m_nni) { m_Tdp.push_back(Eigen::Triplet( di - m_nni, dj - m_nnu, elemmat(e, m * m_ndim + i, n * m_ndim + j))); } else { m_Tdd.push_back(Eigen::Triplet( di - m_nni, dj - m_nni, elemmat(e, m * m_ndim + i, n * m_ndim + j))); } } } } } } m_Auu.setFromTriplets(m_Tuu.begin(), m_Tuu.end()); m_Aup.setFromTriplets(m_Tup.begin(), m_Tup.end()); m_Apu.setFromTriplets(m_Tpu.begin(), m_Tpu.end()); m_App.setFromTriplets(m_Tpp.begin(), m_Tpp.end()); m_Aud.setFromTriplets(m_Tud.begin(), m_Tud.end()); m_Apd.setFromTriplets(m_Tpd.begin(), m_Tpd.end()); m_Adu.setFromTriplets(m_Tdu.begin(), m_Tdu.end()); m_Adp.setFromTriplets(m_Tdp.begin(), m_Tdp.end()); m_Add.setFromTriplets(m_Tdd.begin(), m_Tdd.end()); m_changed = true; } inline Eigen::VectorXd MatrixPartitionedTyings::AsDofs_u(const xt::xtensor& dofval) const { GOOSEFEM_ASSERT(dofval.size() == m_ndof); Eigen::VectorXd dofval_u(m_nnu, 1); #pragma omp parallel for for (size_t d = 0; d < m_nnu; ++d) { dofval_u(d) = dofval(m_iiu(d)); } return dofval_u; } inline Eigen::VectorXd MatrixPartitionedTyings::AsDofs_u(const xt::xtensor& nodevec) const { GOOSEFEM_ASSERT(xt::has_shape(nodevec, {m_nnode, m_ndim})); Eigen::VectorXd dofval_u = Eigen::VectorXd::Zero(m_nnu, 1); #pragma omp parallel for for (size_t m = 0; m < m_nnode; ++m) { for (size_t i = 0; i < m_ndim; ++i) { if (m_dofs(m, i) < m_nnu) { dofval_u(m_dofs(m, i)) = nodevec(m, i); } } } return dofval_u; } inline Eigen::VectorXd MatrixPartitionedTyings::AsDofs_p(const xt::xtensor& dofval) const { GOOSEFEM_ASSERT(dofval.size() == m_ndof); Eigen::VectorXd dofval_p(m_nnp, 1); #pragma omp parallel for for (size_t d = 0; d < m_nnp; ++d) { dofval_p(d) = dofval(m_iip(d)); } return dofval_p; } inline Eigen::VectorXd MatrixPartitionedTyings::AsDofs_p(const xt::xtensor& nodevec) const { GOOSEFEM_ASSERT(xt::has_shape(nodevec, {m_nnode, m_ndim})); Eigen::VectorXd dofval_p = Eigen::VectorXd::Zero(m_nnp, 1); #pragma omp parallel for for (size_t m = 0; m < m_nnode; ++m) { for (size_t i = 0; i < m_ndim; ++i) { if (m_dofs(m, i) >= m_nnu && m_dofs(m, i) < m_nni) { dofval_p(m_dofs(m, i) - m_nnu) = nodevec(m, i); } } } return dofval_p; } inline Eigen::VectorXd MatrixPartitionedTyings::AsDofs_d(const xt::xtensor& dofval) const { GOOSEFEM_ASSERT(dofval.size() == m_ndof); Eigen::VectorXd dofval_d(m_nnd, 1); #pragma omp parallel for for (size_t d = 0; d < m_nnd; ++d) { dofval_d(d) = dofval(m_iip(d)); } return dofval_d; } inline Eigen::VectorXd MatrixPartitionedTyings::AsDofs_d(const xt::xtensor& nodevec) const { GOOSEFEM_ASSERT(xt::has_shape(nodevec, {m_nnode, m_ndim})); Eigen::VectorXd dofval_d = Eigen::VectorXd::Zero(m_nnd, 1); #pragma omp parallel for for (size_t m = 0; m < m_nnode; ++m) { for (size_t i = 0; i < m_ndim; ++i) { if (m_dofs(m, i) >= m_nni) { dofval_d(m_dofs(m, i) - m_nni) = nodevec(m, i); } } } return dofval_d; } template inline void MatrixPartitionedTyingsSolver::factorize(MatrixPartitionedTyings& matrix) { if (!matrix.m_changed && !m_factor) { return; } matrix.m_ACuu = matrix.m_Auu + matrix.m_Aud * matrix.m_Cdu + matrix.m_Cud * matrix.m_Adu + matrix.m_Cud * matrix.m_Add * matrix.m_Cdu; matrix.m_ACup = matrix.m_Aup + matrix.m_Aud * matrix.m_Cdp + matrix.m_Cud * matrix.m_Adp + matrix.m_Cud * matrix.m_Add * matrix.m_Cdp; // matrix.m_ACpu = matrix.m_Apu + matrix.m_Apd * matrix.m_Cdu + matrix.m_Cpd * matrix.m_Adu // + matrix.m_Cpd * matrix.m_Add * matrix.m_Cdu; // matrix.m_ACpp = matrix.m_App + matrix.m_Apd * matrix.m_Cdp + matrix.m_Cpd * matrix.m_Adp // + matrix.m_Cpd * matrix.m_Add * matrix.m_Cdp; m_solver.compute(matrix.m_ACuu); m_factor = false; matrix.m_changed = false; } template inline void MatrixPartitionedTyingsSolver::solve( MatrixPartitionedTyings& matrix, const xt::xtensor& b, xt::xtensor& x) { GOOSEFEM_ASSERT(xt::has_shape(b, {matrix.m_nnode, matrix.m_ndim})); GOOSEFEM_ASSERT(xt::has_shape(x, {matrix.m_nnode, matrix.m_ndim})); this->factorize(matrix); Eigen::VectorXd B_u = matrix.AsDofs_u(b); Eigen::VectorXd B_d = matrix.AsDofs_d(b); Eigen::VectorXd X_p = matrix.AsDofs_p(x); B_u += matrix.m_Cud * B_d; Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - matrix.m_ACup * X_p)); Eigen::VectorXd X_d = matrix.m_Cdu * X_u + matrix.m_Cdp * X_p; #pragma omp parallel for for (size_t m = 0; m < matrix.m_nnode; ++m) { for (size_t i = 0; i < matrix.m_ndim; ++i) { if (matrix.m_dofs(m, i) < matrix.m_nnu) { x(m, i) = X_u(matrix.m_dofs(m, i)); } else if (matrix.m_dofs(m, i) >= matrix.m_nni) { x(m, i) = X_d(matrix.m_dofs(m, i) - matrix.m_nni); } } } } template inline void MatrixPartitionedTyingsSolver::solve( MatrixPartitionedTyings& matrix, const xt::xtensor& b, xt::xtensor& x) { GOOSEFEM_ASSERT(b.size() == matrix.m_ndof); GOOSEFEM_ASSERT(x.size() == matrix.m_ndof); this->factorize(matrix); Eigen::VectorXd B_u = matrix.AsDofs_u(b); Eigen::VectorXd B_d = matrix.AsDofs_d(b); Eigen::VectorXd X_p = matrix.AsDofs_p(x); Eigen::VectorXd X_u = m_solver.solve(Eigen::VectorXd(B_u - matrix.m_ACup * X_p)); Eigen::VectorXd X_d = matrix.m_Cdu * X_u + matrix.m_Cdp * X_p; #pragma omp parallel for for (size_t d = 0; d < matrix.m_nnu; ++d) { x(matrix.m_iiu(d)) = X_u(d); } #pragma omp parallel for for (size_t d = 0; d < matrix.m_nnd; ++d) { x(matrix.m_iid(d)) = X_d(d); } } template inline void MatrixPartitionedTyingsSolver::solve_u( MatrixPartitionedTyings& matrix, const xt::xtensor& b_u, const xt::xtensor& b_d, const xt::xtensor& x_p, xt::xtensor& x_u) { + UNUSED(b_d); GOOSEFEM_ASSERT(b_u.size() == matrix.m_nnu); GOOSEFEM_ASSERT(b_d.size() == matrix.m_nnd); GOOSEFEM_ASSERT(x_p.size() == matrix.m_nnp); GOOSEFEM_ASSERT(x_u.size() == matrix.m_nnu); this->factorize(matrix); Eigen::Map(x_u.data(), x_u.size()).noalias() = m_solver.solve(Eigen::VectorXd( Eigen::Map(b_u.data(), b_u.size()) - matrix.m_ACup * Eigen::Map(x_p.data(), x_p.size()))); } template inline xt::xtensor MatrixPartitionedTyingsSolver::Solve( MatrixPartitionedTyings& matrix, const xt::xtensor& b, const xt::xtensor& x) { xt::xtensor ret = x; this->solve(matrix, b, ret); return ret; } template inline xt::xtensor MatrixPartitionedTyingsSolver::Solve( MatrixPartitionedTyings& matrix, const xt::xtensor& b, const xt::xtensor& x) { xt::xtensor ret = x; this->solve(matrix, b, ret); return ret; } template inline xt::xtensor MatrixPartitionedTyingsSolver::Solve_u( MatrixPartitionedTyings& matrix, const xt::xtensor& b_u, const xt::xtensor& b_d, const xt::xtensor& x_p) { xt::xtensor x_u = xt::empty({matrix.m_nnu}); this->solve_u(matrix, b_u, b_d, x_p, x_u); return x_u; } } // namespace GooseFEM #endif diff --git a/test/basic/CMakeLists.txt b/test/basic/CMakeLists.txt index 1ce56fd..55f36b9 100644 --- a/test/basic/CMakeLists.txt +++ b/test/basic/CMakeLists.txt @@ -1,45 +1,49 @@ cmake_minimum_required(VERSION 3.0) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) project(GooseFEM-test-basic) find_package(GooseFEM REQUIRED CONFIG) endif() -option(WARNINGS "Show build warnings" ON) +set(ASSERT ON) +set(DEBUG ON) option(SIMD "Enable xsimd" ON) -option(ASSERT "Enable assertions" ON) -option(DEBUG "Enable all assertions" ON) +option(WARNINGS "Enable warnings" ON) + +set(test_name "test-basic") find_package(Catch2 REQUIRED) -add_executable(test-basic +add_executable(${test_name} main.cpp Allocate.cpp ElementHex8.cpp ElementQuad4.cpp Iterate.cpp Matrix.cpp MatrixDiagonal.cpp Mesh.cpp MeshQuad4.cpp Vector.cpp VectorPartitioned.cpp) -target_link_libraries(test-basic PRIVATE Catch2::Catch2 GooseFEM) +target_link_libraries(${test_name} PRIVATE Catch2::Catch2 GooseFEM) -if (SIMD) - target_link_libraries(test-basic PRIVATE xtensor::optimize xtensor::use_xsimd) +if(SIMD) + target_link_libraries(${test_name} PRIVATE xtensor::optimize xtensor::use_xsimd) endif() -if (WARNINGS) - target_link_libraries(test-basic PRIVATE GooseFEM::compiler_warnings) +if(WARNINGS) + target_link_libraries(${test_name} PRIVATE GooseFEM::compiler_warnings) endif() -if (ASSERT) - target_link_libraries(test-basic PRIVATE GooseFEM::assert) +if(ASSERT) + target_link_libraries(${test_name} PRIVATE GooseFEM::assert) endif() -if (DEBUG) - target_link_libraries(test-basic PRIVATE GooseFEM::debug) +if(DEBUG) + target_link_libraries(${test_name} PRIVATE GooseFEM::debug) endif() + +add_test(NAME ${test_name} COMMAND ${test_name}) diff --git a/test/gmat/CMakeLists.txt b/test/gmat/CMakeLists.txt index d7c2854..0db8ada 100644 --- a/test/gmat/CMakeLists.txt +++ b/test/gmat/CMakeLists.txt @@ -1,57 +1,61 @@ cmake_minimum_required(VERSION 3.0) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) project(GooseFEM-test-gmat) find_package(GooseFEM REQUIRED CONFIG) endif() -option(WARNINGS "Show build warnings" ON) +set(ASSERT ON) +set(DEBUG ON) option(SIMD "Enable xsimd" ON) -option(ASSERT "Enable assertions" ON) -option(DEBUG "Enable all assertions" ON) +option(WARNINGS "Enable warnings" ON) + +set(test_name "test-gmat") find_package(Catch2 REQUIRED) if(NOT WIN32) find_package(GMatElastic REQUIRED) find_package(GMatElastoPlasticQPot REQUIRED) - add_executable(test-gmat + add_executable(${test_name} main.cpp hybrid-elastic.cpp hybrid-elastoplasticqpot.cpp) - target_link_libraries(test-gmat PRIVATE + target_link_libraries(${test_name} PRIVATE Catch2::Catch2 GooseFEM GMatElastic GMatElastoPlasticQPot) else() find_package(GMatElastoPlasticQPot REQUIRED) - add_executable(test-gmat + add_executable(${test_name} main.cpp hybrid-elastoplasticqpot.cpp) - target_link_libraries(test-gmat PRIVATE + target_link_libraries(${test_name} PRIVATE Catch2::Catch2 GooseFEM GMatElastoPlasticQPot) endif() -if (SIMD) - target_link_libraries(test-gmat PRIVATE xtensor::optimize xtensor::use_xsimd) +if(SIMD) + target_link_libraries(${test_name} PRIVATE xtensor::optimize xtensor::use_xsimd) endif() -if (WARNINGS) - target_link_libraries(test-gmat PRIVATE GooseFEM::compiler_warnings) +if(WARNINGS) + target_link_libraries(${test_name} PRIVATE GooseFEM::compiler_warnings) endif() -if (ASSERT) - target_link_libraries(test-gmat PRIVATE GooseFEM::assert) +if(ASSERT) + target_link_libraries(${test_name} PRIVATE GooseFEM::assert) endif() -if (DEBUG) - target_link_libraries(test-gmat PRIVATE GooseFEM::debug) +if(DEBUG) + target_link_libraries(${test_name} PRIVATE GooseFEM::debug) endif() + +add_test(NAME ${test_name} COMMAND ${test_name})